Umlaute aus Textdatei in TStringList

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
baba
Beiträge: 265
Registriert: Mi 4. Apr 2007, 17:47

Umlaute aus Textdatei in TStringList

Beitrag von baba »

Moin, moin

habe ich da was übersehen?

Code: Alles auswählen

 
 
var
   xHandle : TextFile;
   xZeile  : string;
 
...               
   AssignFile(xHandle, FFileName);                   // DATEI ÖFFNEN
   try
      Reset(xHandle);
      while not Eof(xHandle) do begin
         Readln(xHandle, xZeile);          // NÄCHSTE ZEILE EINLESEN
 
         STabZeilen.Add(xZeile);
      end;
   finally
      CloseFile(xHandle);
   end;

STabZeilen ist eine TStinglist.

Egal ob ich wie oben, also selbst, oder mit der Methode "LoadFromFile" eine Textdatei auslese, sobald ein Umlaut in der
Zeile steht, wird nur ein Leerstring eingelesen. Ändere ich in der Textdatei die Zeile - den Umlaut z.B. von Müller in Mueller - wird sie gelesen.

Guß
Baba.

monta
Lazarusforum e. V.
Beiträge: 2809
Registriert: Sa 9. Sep 2006, 18:05
OS, Lazarus, FPC: Linux (L trunk FPC trunk)
CPU-Target: 64Bit
Wohnort: Dresden
Kontaktdaten:

Re: Umlaute aus Textdatei in TStringList

Beitrag von monta »

Kodier die Datei mal als UTF-8, dann sollte es gehen.


Ich hatte da zumindest ähnliche Probleme mit einer ini-Dateien, die nicht eingelesen wurde, wenn sie Umlaute enthielt und nicht UTf-8 kodiert war.
Johannes

Benutzeravatar
theo
Beiträge: 10869
Registriert: Mo 11. Sep 2006, 19:01

Re: Umlaute aus Textdatei in TStringList

Beitrag von theo »

http://bugs.freepascal.org/view.php?id=12676" onclick="window.open(this.href);return false;

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Umlaute aus Textdatei in TStringList

Beitrag von mschnell »

Die neue LCL (und damit alles was den Inhalt der Stringlist anzeigt) benutzt UTF8String als API.

readln liest Byte-weise die Datei ein gibt also die Codierung aus, die die Datei hat. Unabhängig vom Typ der Variablen. Wenn Die Datei eine "normale" Textdatei ist, ist sie ANSI-Codiert (entsprechend der "locale"-Einstellung Deines Rechners). Der richtige Typ in Pascal dafür ist statt "String" der "ANSISTring" (sollte richtigerweise automatisch entsprechend der "locale"-Einstellung interpretiert werden, was Vor der Einführung von Unicode auch so war, weil schließlich alles entsprechend der "locale"-Einstellung interpretiert worden ist).

Der Compiler kann UTF8String und ANSIString aber leider nicht unterscheiden, deshalb kann er nicht automatisch umkodieren und Du musst die ANSI->Unicode - Umcodierung (genau: ANSIString->UTF8String) von Hand aufrufen.

-Michael

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Re: Umlaute aus Textdatei in TStringList

Beitrag von Christian »

Code: Alles auswählen

 
var
   xHandle : TextFile;
   xZeile  : string;
...               
   AssignFile(xHandle, FFileName);                   // DATEI ÖFFNEN
   try
      Reset(xHandle);
      while not Eof(xHandle) do begin
         Readln(xHandle, xZeile);          // NÄCHSTE ZEILE EINLESEN
         STabZeilen.Add(SysToUTF8(xZeile));
      end;
   finally
    CloseFile(xHandle);
   end;                 
 

Code: Alles auswählen

...               
  STabZeilen.LoadFromFile(FFilename);
sollten beide Varianten gehn ...
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

Benutzeravatar
theo
Beiträge: 10869
Registriert: Mo 11. Sep 2006, 19:01

Re: Umlaute aus Textdatei in TStringList

Beitrag von theo »

mschnell hat geschrieben: readln liest Byte-weise die Datei ein gibt also die Codierung aus, die die Datei hat.
Wie meinst du das?
mschnell hat geschrieben: Der Compiler kann UTF8String und ANSIString aber leider nicht unterscheiden, deshalb kann er nicht automatisch umkodieren und Du musst die ANSI->Unicode - Umcodierung (genau: ANSIString->UTF8String) von Hand aufrufen.
Das hat mit der Datei-Leserei aber nichts zu tun. Byte ist Byte. Wenn kein BOM da ist, kann man höchstens statistisch analysieren, ob die Datei in ANSI oder UTF-8 vorliegt.

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Umlaute aus Textdatei in TStringList

Beitrag von mschnell »

Wenn nirgendwo was umcodiert wird, landen die Bytes aus der Datei direkt in der LCL-API. Die ist in der neuen Version mit UTF8 gemacht. Wenn die Datei also nicht UTF8-Codiert ist (sondern in der lokalen ANSI Variante), sieht man etwas anderes als man erwartet.

-Michael

baba
Beiträge: 265
Registriert: Mi 4. Apr 2007, 17:47

Re: Umlaute aus Textdatei in TStringList

Beitrag von baba »

[quote="Christian"]

Code: Alles auswählen

 
    STabZeilen.Add(SysToUTF8(xZeile));
 
... mit diesem Ansatz konnte ich das Problem lösen! Beim Lesen konvertiere ich mit "SysToUTF8(xZeile)" beim Schreiben nutze ich "UTF8ToSys(xZeile)". (Beide Funktionen benötigen die UNIT FileUtil)

Werden die beiden Funktionen "SaveToFile" und "LoadFromFile" benutzt, werden die Daten gespeichert, können auch mit jedem Texteditor gelesen werden, "LoadFromFile" liest Leerzeilen* wenn Umlaute vorhanden sind.

Ich meine das Problem verhält sich wie folgt:

STabZeilen.SaveToFile(FName) -> Speichert ANSI
STabZeilen.LoadFromFile(FName) -> Erwartet UTF8

Gruß
Baba.

*Leerzeilen sind es auch nicht. Length() auf die Zeile gibt die Länge bis in etwa zum Sonderzeichen aus. Ein Copy(xZeile, 1, x) wobei x eine Position vor dem Sonderzeichen sein muß, zeigt den sonst nicht lesbaren String an.

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Umlaute aus Textdatei in TStringList

Beitrag von mschnell »

Nochmal:

StringList und damit STabZeilen (falls Du da nichts besonderes einbaust) weiß nichts von ANSI oder UTF8, sondern arbeitet einfach mit Strings von Bytes (die allerdings Char genannt werden). Die Bedeutung / Codierung ist dabei völlig unerheblich,

Das gilt auch für Dateien und damit für "LoadFromFile".

ASCI/ANSI/Unicode/utf8/... kommt erst zum Tragen, wenn man etwas anzeigen möchte und das ist bei Lazarus dann, wenn man LCL-Funktionen (wie TCaption, TLabel, TMemo, ... anspricht. Oder bei einer Datei z.B. einen Editor verwendet. (Tastatur-Eingaben gehören natürlich auch dazu.) Bei Zuweisungen von und zu WideString oder Konstanten passiert natürlich auch eine automatischen Konvertierung - nicht immer die, die man erwartet :) .

Wenn Der Compiler und die RTL später einmal unterschiedliche Typen von Byte-Strings (wie ANSString und UTF8String) unterschiedlich behandeln, oder ein ganz anderes String-Handling implementiert wird (wie bei Delphi 2009), könnte sich das ändern und TStringList je nach String-Codierung verschiedene Sachen tun (z.B, Umcodieren).

-Michael
Zuletzt geändert von mschnell am Do 20. Nov 2008, 23:58, insgesamt 1-mal geändert.

baba
Beiträge: 265
Registriert: Mi 4. Apr 2007, 17:47

Re: Umlaute aus Textdatei in TStringList

Beitrag von baba »

mschnell hat geschrieben:Nochmal:

StringList und damit STabZeilen (falls Du da nichts besonderes einbaust) weiß nichts von ANSI oder UTF8, sondern arbeitet einfach mit Strings von Bytes (die allerdings Char genannt werden). Die Bedeutung / Codierung ist dabei völlig unerheblich,

Das gilt auch für Dateien und damit für "LoadFromFile".
Das habe ich schon verstanden.

Was ich nicht verstehe ist folgendes:

Code: Alles auswählen

1:
StringList.Add('Erwin Müller'); // Ist Müller nun UTF8
StringList.SaveToFile('TEST.TXT'); // (Editor: Eine Zeile, Erwin Müller)
StringList.Clear;
StringList.LoadFromFile('TEST.TXT');
ShowMessage(StringList.Strings[0]); // Anzeige leeres Fenster
 
2:
StringList.Add('Erwin Meier');
StringList.SaveToFile('TEST.TXT'); // (Editor: Eine Zeile, Erwin Meier)
StringList.Clear;
StringList.LoadFromFile('TEST.TXT');
ShowMessage(StringList.Strings[0]); // Anzeige Erwin Meier 
Baba.
arbeitet einfach mit Strings von Bytes. Das gilt auch für Dateien und damit für "LoadFromFile".
???? Siehe die Diskusion zu Theos Link ????
Well using UTF8Encode as your "hack" suggests, you are already assuming the file's content is UTF-8 encoded. But yes I understand the issue - it is a bit more complex as first perceived. I'll discuss this further in the FPC-Devel mailing list, I'm busy writing that message now.

Benutzeravatar
theo
Beiträge: 10869
Registriert: Mo 11. Sep 2006, 19:01

Re: Umlaute aus Textdatei in TStringList

Beitrag von theo »

Bist du auf Windows?
Auf Linux geht dein Beispiel 1 auch einwandfrei.
Wie sieht denn die TEST.TXT Kodierung im Hex-Editor aus?

Bei mir ist es UTF-8, also:
Hex: 45 72 77 69 6e 20 4d c3 bc 6c 6c 65 72 0a
Dez: 069 114 119 105 110 032 077 195 188 108 108 101 114 010

Benutzeravatar
theo
Beiträge: 10869
Registriert: Mo 11. Sep 2006, 19:01

Re: Umlaute aus Textdatei in TStringList

Beitrag von theo »

mschnell hat geschrieben:Nochmal:
StringList und damit STabZeilen (falls Du da nichts besonderes einbaust) weiß nichts von ANSI oder UTF8, sondern arbeitet einfach mit Strings von Bytes (die allerdings Char genannt werden). Die Bedeutung / Codierung ist dabei völlig unerheblich,
Das hätte ich auch angenommen, aber mindestens unter Windows läuft das scheint's nicht so.
Dieser Herr hier http://bugs.freepascal.org/view.php?id=12676" onclick="window.open(this.href);return false; berichtet auch ein Lines.Count von 0 (allerdings für TMemo)

baba
Beiträge: 265
Registriert: Mi 4. Apr 2007, 17:47

Re: Umlaute aus Textdatei in TStringList

Beitrag von baba »

theo hat geschrieben:Bist du auf Windows?
Auf Linux geht dein Beispiel 1 auch einwandfrei.
Wie sieht denn die TEST.TXT Kodierung im Hex-Editor aus?
... jupp, Windows und WinCe.

Ich bekomme über WLan (TCP/iNet) Daten, diese speichere erst in einem Stringgrid und schreibe sie dann in eine Datei auf SD-Karte.
Wenn ich sie wieder einlese, entstehen die bekannten Probleme, in den Zeilen, in denen Umlaute vorkommen.

Baba.

Benutzeravatar
theo
Beiträge: 10869
Registriert: Mo 11. Sep 2006, 19:01

Re: Umlaute aus Textdatei in TStringList

Beitrag von theo »

Aber was steht denn nun Byte-mässig in der Datei?
Kann sie gelesen werden, wenn du sie in Notepad nach Latin1 bzw. UTF-8 umwandlest?

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Umlaute aus Textdatei in TStringList

Beitrag von mschnell »

baba hat geschrieben:

Code: Alles auswählen

1:
StringList.Add('Erwin Müller'); // Ist Müller nun UTF8
 
Bei Zuweisungen von Konstanten passiert natürlich eine Umwandlung (Konstanten sind schließlich (in der Quelltext-Anzeige) sichtbarer Text) - allerdings nicht unbedingt die, die man erwartet: der Kompiler weiß ja nicht, ob man utf8 oder ANSI in seiner Stringlist haben will, weil es keine für ihn unterscheidbaren Typen dafür gibt.
-Michael

Antworten