Jak otworzyć plik z polskimi literami w ścieżce?

2015-02-08 08:06
0

procedure TForm1.OtworzPlik;
var
  Sciezka: String;
  Plik: TextFile;
  Linia: String;
begin
  Sciezka := 'Łukasz/info.txt';
  AssignFile(Plik, Sciezka);
  Reset(Plik);
  while not EOF(Plik) do
    begin
      readln(Plik, Linia);
      ShowMessage(Linia);
    end;
  CloseFile(Plik);
end;

Podany kod nie znajduje pliku przez umieszczenie polskiego znaku w ścieżce. W przypadku zamienienia Sciezka := 'Łukasz/info.txt'; na Sciezka := 'Lukasz/info.txt'; wszystko działa prawidłowo. Zapewne da się to jakoś ominąć. Takich folderów z polskimi literami mam kilkadziesiąt wiec nie bardzo chce mi się zmieniać nazwy, szczególnie, że musiałbym dodać jeszcze funkcje usuwającą polskie litery w przypadku podawania ścieżki przez użytkownika. Druga sprawa że w kodzie mam kilka takich miejsc gdzie podobny błąd może wystąpić. Program pisałem na szybko, byle tylko działał i jakakolwiek modyfikacja kody jest w tym momencie bardzo trudna, a sam program jest mi bardzo potrzebny i to jak najszybciej. Dlatego proszę o jakąś poradę jak to naprawić.

Pozostało 580 znaków

2015-02-08 08:41
paweld
1
sciezka:=UTF8ToAnsi(sciezka) 

Pozdrawiam

Pozostało 580 znaków

2015-02-08 10:34
0

Plus sprawdź kodowanie samego pliku źródłowego.


Pozostało 580 znaków

2015-02-08 17:44
0

Z samym plikiem problemów nie ma. Chodzi tylko o nazwę folderu. Plik otworzyć mogę, gdy nie ma polskich liter w ścieżce.

Pozostało 580 znaków

2015-02-09 03:50
0

Nie potrafię sobie poradzić z tym kodowaniem. Mam dwa pliki. Oba mają kodowanie ANSI. W pierwszym zapisuje się wszystko bez problemów. W drugim... nie. Chciałem wklejać tam tekst z Edita. Próbowałem używać ANSIToUTF8 i UTF8ToANSI, ale za każdym razem wyświetla się inaczej, ale zawsze nie tak jak powinno.

Mój błąd. W pierwszym pliku wcześniej miałem kodowanie UTF-8, dlatego wszystko się zapisywało prawidłowo.

Spróbowałem zmienić kodowanie plików na UTF-8. Zapisuje się wtedy prawidłowo. Ale problem jest z odczytem. W pierwszej linii się coś dodaje i program odczytuje ją inaczej niż jest zapisana.

edytowany 1x, ostatnio: dani17, 2015-02-09 04:14

Pozostało 580 znaków

2015-02-09 15:50
0

@dani17 - ładowanie i zapisywanie danych z i do plików nijak ma się do problemu z otwieraniem plików...

W pierwszym zapisuje się wszystko bez problemów.

Pokaż jakiś (aktualny) kod, żeby było wiadomo co robisz;

W drugim... nie

Też pokaż kod;

Chciałem wklejać tam tekst z Edita.

Komponenty i całe LCL domyślnie korzysta z UTF-8, więc jeśli plik ma być kodowany w ANSI - łańcuchy musisz konwertować;

Próbowałem używać ANSIToUTF8 i UTF8ToANSI, ale za każdym razem wyświetla się inaczej, ale zawsze nie tak jak powinno.

No to jakieś cuda muszą się u Ciebie dziać... Jeśli ładujesz dane z pliku, to nie konwertuj ich na ANSI, bo one są już kodowane w ANSI; Natomiast jeśli tekst pobierasz z komponentów - konwertuj na ANSI; A najlepiej to nie baw się i wszędzie używaj UTF-8 - przecież to nie problem i nijak nie wpływa na poprawność danych;


A tak przy okazji - szkoda, że biblioteka standardowa FPC nie posiada jakiegoś strumienia, który pozwoliłby ładować pojedyncze linie z pliku tekstowego do pamięci; Albo ja o niej jeszcze nie dowiedziałem się; Wtedy można by spokojnie używać strony kodowej UTF-8, bez kombinacji z konwersjami; Samo napisanie takiej klasy było by dość proste i nawet mógłbym się tego podjąć, jednak czasu jak zwykle za mało...

A tak to albo trzeba korzystać ze starej konstrukcji, albo ładować wszystko do pamięci (używając TStringList).


edytowany 1x, ostatnio: furious programming, 2015-02-09 15:50

Pozostało 580 znaków

2015-02-10 01:44
0

Jeśli chodzi o kodowanie to ustawiłem wszystko na UTF-8. Jakiś czas temu już nie pamiętam dlaczego potrzebowałem kodowania ANSI, ale nie wiem czy to nie było jeszcze kiedy zaczynałem od zwykłego Pascala i konsoli. Później tak mi zostało że wszystko robiłem na ANSI.

Nie mam problemów z otwieraniem tylko właśnie z kodowaniem. Przez złe kodowanie program nie może znaleźć plików i przez to ich otworzyć.

Pokazać jakiś kod? Może nie jest to napisane najlepiej, ale to tak na szybko tylko.


procedure TForm1.Odczyt;
var
  Plik: TextFile;
  Linie: Array of String;
  Ilosc: Integer;
  I: Integer;
  K: Integer;
begin
  Ilosc := 0;
  AssignFile(Plik, 'info.txt');
  Reset(Plik);
  While not EOF(Plik) do
    begin
      Inc(Ilosc);
      SetLength(Linie, (Ilosc + 1));
      ReadLn(Plik, Linie[Ilosc]);
    end;
  CloseFile(Plik);
  For I := 1 to Ilosc do
    If Linie[I] = '[start]' then
      begin
        K := I;
        Repeat
          Inc(K);
          SzukajParametry;
        Until (K = Ilosc) or (Linie[K] = '[start]');
      end;
end;

Tak na prawdę problem pojawia się w If Linie[I] = '[start]' then. Znak strukturę pliku. W pierwszej linijce jest [start], jednak program w przypadku gdy I = 0 nie widzi tego. Tak jakby ta pierwsza linijka zawierała coś innego. O ile w tym przypadku mogę to zabezpieczyć w taki sposób If (Linie[I] = '[start]') or (I = 1) then to w przypadku gdy nie będę wiedział jaką strukturę ma plik może się to okazać dużym problemem.

edytowany 1x, ostatnio: dani17, 2015-02-10 04:01

Pozostało 580 znaków

2015-02-10 03:45
2

Po pierwsze - masz wyciek pamięci, bo otwierasz plik przez Reset, ale nigdzie nie zamykasz go za pomocą CloseFile; Poza tą metodą nie masz już dostępu do zmiennej lokalnej Plik, więc nie możesz zwolnić uchwytu - stąd wyciek pamięci;

Po drugie - łańcuch [start] zarówno w kodowaniu ASCII, ANSI, jak i UTF-8 zawsze będzie opisany na siedmiu bajtach, więc nawet jeśli wczytasz z pliku linię kodowaną w ANSI oraz przyrównasz ją do literału (kodowanego w UTF-8) - porównanie zwróci True;

Po trzecie - jeżeli operujesz na łańcuchach kodowanych w UTF-8, to dobrą praktyką jest użycie typu UTF8String (jest to alias na typ AnsiString); Mniej będziesz miał później problemów;

Po czwarte - skoro i tak ładujesz całą zawartość do pliku, to skorzystaj z klasy TStringList; Po pierwsze mniej kodu trzeba będzie, a po drugie - znalezienie linijki z wartością [start] to jedno wywołanie metody IndexOf, która oczywiście zwróci indeks linii, w której ta wartość jest zapisana; A jeśli nie znajdzie, to zwróci -1;

Podsumowując - łatwiej by było, gdybyś napisał co chcesz osiągnąć, czyli co ma kod wykonać.


edytowany 4x, ostatnio: furious programming, 2015-02-10 21:44
Mały bubel był - poprawiłem; - furious programming 2015-02-10 03:51

Pozostało 580 znaków

2015-02-10 04:01
0
furious programming napisał(a):

Po pierwsze - masz wyciek pamięci, bo otwierasz plik przez Reset, ale nigdzie nie zamykasz go za pomocą CloseFile; Poza tą metodą nie masz już dostępu do zmiennej lokalnej Plik, więc nie możesz zwolnić uchwytu - stąd wyciek pamięci;

CloseFile mam w kodzie. Tak banalnego błędu bym nie popełnił. Przez przypadek tylko nie skopiowałem tej linijki.

Po drugie - łańcuch [start] zarówno w kodowaniu ASCII, ANSI, jak i UTF-8 zawsze będzie opisany na siedmiu bajtach, więc nawet jeśli wczytasz z pliku linię kodowaną w ANSI oraz przyrównasz ją do literału (kodowanego w UTF-8) - porównanie zwróci True;

Tu jest problem tylko z pierwszą linijką. Jeśli [start] będzie w innej niż pierwsza wszystko działa prawidłowo. Jeśli wyświetlę tą pierwszą linijkę bez zmiany kodowania to wyświetla się prawidłowo, ale porównując ją w ten sposób: If Linia[1] = "[start]" to zwraca False. Teraz tak myśląc nad tym, zastanawiam się czy wina nie może być po stronie samego pliku? Może zmiana kodowania coś takiego spowodowała?

Po trzecie - jeżeli operujesz na łańcuchach kodowanych w UTF-8, to dobrą praktyką jest użycie typu UTF8String (jest to alias na typ String); Mniej będziesz miał później problemów;

A jakie mógłbym mieć później problemy? Dużo to zmienia?

Po czwarte - skoro i tak ładujesz całą zawartość do pliku, to skorzystaj z klasy TStringList; Po pierwsze mniej kodu trzeba będzie, a po drugie - znalezienie linijki z wartością [start] to jedno wywołanie metody IndexOf, która oczywiście zwróci indeks linii, w której ta wartość jest zapisana; A jeśli nie znajdzie, to zwróci -1;

Podsumowując - łatwiej by było, gdybyś napisał co chcesz osiągnąć, czyli co ma kod wykonać.

Wydaje mi się, że nie mógłbym tego użyć, w taki sposób, aby potrzebne było mniej kodu. Struktura pliku jest taka


[start]
id = numer
nazwa atrybutu = wartosc
nazwa 2 atrybutu = wartosc
...

[start]
id = numer
nazwa atrybutu = wartosc
nazwa 2 atrybutu = wartosc
...

[start]
id = numer
nazwa atrybutu = wartosc
nazwa 2 atrybutu = wartosc
...

Gdy program znajdzie linijkę [start] to uruchamiana jest procedura, która w zakresie od [start] do następnego [start] wyszukuje odpowiednich parametrów i przypisuje do tablicy zdefiniowanego przeze mnie typu. Przy czym może się zdarzyć, że pierwsza "sekcja" będzie miała 10 atrybutów, a następna tylko np. 2.

edytowany 3x, ostatnio: dani17, 2015-02-10 04:05

Pozostało 580 znaków

2015-02-10 05:29
2

Problem ze [start] w pierwszej linijce może polegać na tym że plik ma kodowanie UTF-8 z BOM i wtedy przed [start] występują inne znaki (tzw. bom) http://pl.wikipedia.org/wiki/BOM_%28informatyka%29 zmień kodowanie pliku albo w inny sposób się przed tym zabezpiecz.


Nie odpowiadam na PW w sprawie pomocy programistycznej.
Pytania zadawaj na forum, bo:
od tego ono jest ;) | celowo nie zawracasz gitary | przeczyta to więcej osób a więc większe szanse że ktoś pomoże.
Ach, to samo chciałem teraz napisać... :D - furious programming 2015-02-10 20:59

Pozostało 580 znaków

2015-02-10 07:50
0

Kodowania już teraz nie będę zmieniał bo wszystko pozostałe działa prawidłowo. A jeśli chodzi o zabezpieczenie to w jaki sposób jest to możliwe? O ile w tym przypadku znam strukturę pliku to w jeśli będę pisał program który będzie używał pliku, którego zawartości pierwszej linii nie będę znał to jak ją właściwie odczytać?

Pozostało 580 znaków

Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0