und nehme an, es handelt sich um einen Bug in TListbox.Items.LoadfromFile bzw. in UTF8Length (aus lazutf8).
Ist es ein Bug, oder bin ich nur zu blöd dafür...?
Windows 7,
FPC-Version 3.1.1,
64bit
Ich habe eine csv-Datei mit Excel erstellt, welche nur in der obersten linken Zelle das Wort "Abfüllstation" enthält.
In Notepad++ sehe ich, dass sie die Codierung "UTF-8" (also quasi mit BOM) hat.
Hexadezimal sieht das komplette File so aus:
00000000 ef bb bf 41 62 66 c3 bc 6c 6c 73 74 61 74 69 6f
00000010 6e 0d 0a
Ok, so nun eine Listbox aufs Formular und einen Timer und folgende Ereignisbehandlung:
Der Output in der Listbox ist:procedure TForm1.Timer1Timer(Sender: TObject);
var
s, s1, s2:string;
begin
Timer1.enabled:=false;
Listbox1.Items.LoadFromFile('test.csv');
Listbox1.Items.Add(UTF8Trim(Listbox1.Items[0]));
s1:=Listbox1.Items[0];
s2:=Listbox1.Items[1];
s:='Abfüllstation';
Form1.Listbox1.Items.Add('UTFLength(s1) = ' + inttostr(UTF8Length(s1)));
Form1.Listbox1.Items.Add('UTFLength(s2) = ' + inttostr(UTF8Length(s2)));
if s1=s then Listbox1.Items.Add('s1 = s') else Listbox1.Items.Add('s1 <> s');
if s2=s then Listbox1.Items.Add('s2 = s') else Listbox1.Items.Add('s2 <> s');
//s1 beginnt anscheinend mit einem unsichtbaren Zeichen (3 Bytes UTF-8-Byte-Order-Marking) 239 187 191
end;
Debuggen ergibt, dass anscheinend s1 mit der unsichtbaren Bytefolge 239 187 191 (BOM) beginnt.Abfüllstation
Abfüllstation
UTFLength(s1) = 14
UTFLength(s2) = 13
s1 <> s
s2 = s
Allerdings muss man sagen, dass das ein gemeines Problem ist, weil man das unsichtbare Zeichen ja auch nicht so ohne weiteres im Debugger sieht. Zumindest mir war am Anfang nicht klar, warum der Vergleich s1=s false ergibt.
Quintessenz:
- Die Listbox läd zumindest den ersten UTF-8-String mit BOM herein.
- Die Listbox zeigt diesen String und den mit Add hinzugefügten String gleich an.
- UTF8Length liefert für den ersten String aber 14 anstatt 13 (d.h. das BOM zählt mit; Bug??)
- UTF8Trim behebt das Problem
- Das BOM bewirkt, dass der Gleichheitsoperator fehlschlägt
- UTF8CompareStr ist auch false (wozu ist das eigentlich)
Sollte nicht LoadFromFile der Listbox das BOM des strings entfernen?
Mein Workaround ist aktuell, nach LoadFromFile in einer Schleife für jedes TListbox.Item UTF8Trim aufzurufen, aber das kann ja auch nicht im Sinne des Erfinders sein..... Andere Leute wollen vielleicht Strings einlesen, die auf Leerzeichen enden.
LG Helmut