AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

WideStringlist in UTF-8 mit Delphi 2007 speichern

Ein Thema von ioster · begonnen am 30. Aug 2023 · letzter Beitrag vom 31. Aug 2023
Antwort Antwort
Seite 2 von 2     12   
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.476 Beiträge
 
Delphi 12 Athens
 
#11

AW: WideStringlist in UTF-8 mit Delphi 2007 speichern

  Alt 31. Aug 2023, 15:42
Delphi-Quellcode:
procedure SaveToUTF16(const Filename: string; Content: TWideStrings);
var
  BOM: TBytes;
  Stream : TFileStream;
  Zeile : WideString;
begin
  Zeile := Content.Text;
  Stream := TFileStream.Create(Filename, fmCreate);
  try
    BOM := TBytes.Create($FF, $FE);
    Stream.WriteBuffer(BOM[0], Length(BOM));
    Stream.WriteBuffer(Zeile[1], Length(Zeile)*Sizeof(Zeile[1]));
  finally
    Stream.Free;
  end;
end;
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#12

AW: WideStringlist in UTF-8 mit Delphi 2007 speichern

  Alt 31. Aug 2023, 16:35
Wie gesagt, Arrayzugriffe auf leere Strings/Arrays, knallen gern mal, daher
Delphi-Quellcode:
if Zeile <> 'then
  Stream.WriteBuffer(Zeile[1], Length(Zeile)*Sizeof(WideChar));

// oder

Stream.WriteBuffer(PWideChar(Zeile)^, Length(Zeile)*Sizeof(WideChar));
Wenn man das BOM vorher als CHAR in den String einfügt, ist es egal, da dann der String nie leer ist.




PS: die TWideStrings und TWideStringList der Unit Delphi-Referenz durchsuchenWideStrings speichern auch das BOM.
Weiß nicht ob und wie vor Delphi XE das gemacht wurde, aber diese Unit gab es auch schon in Delphi 7, wenn ich mich nicht total irre.

Delphi-Quellcode:
procedure TWideStrings.SaveToStream(Stream: TStream; Encoding: TEncoding);
var
  Buffer, Preamble: TBytes;
begin
  if Encoding = nil then
    Encoding := TEncoding.Unicode; // The default encoding is UTF-16

  Buffer := Encoding.GetBytes(string(GetTextStr));
  Preamble := Encoding.GetPreamble;

  if Length(Preamble) > 0 then
    Stream.WriteBuffer(Preamble[0], Length(Preamble));

  Stream.WriteBuffer(Buffer[0], Length(Buffer));
end;
$2B or not $2B

Geändert von himitsu (31. Aug 2023 um 16:53 Uhr)
  Mit Zitat antworten Zitat
ioster

Registriert seit: 15. Aug 2008
84 Beiträge
 
Delphi 10.3 Rio
 
#13

AW: WideStringlist in UTF-8 mit Delphi 2007 speichern

  Alt 31. Aug 2023, 16:47
Wie gesagt, Arrayzugriffe auf leere Strings/Arrays, knallen gern mal, daher
Delphi-Quellcode:
if Zeile <> 'then
  Stream.WriteBuffer(Zeile[1], Length(Zeile)*Sizeof(WideChar));

// oder

Stream.WriteBuffer(PWideChar(Zeile)^, Length(Zeile)*Sizeof(WideChar));
Wenn man das BOM vorher als CHAR in den String einfügt, ist es egal, da dann der String nie leer ist.




PS: die TWideStrings und TWideStringList der Unit [OH]WideStrings[OH] speichern auch das BOM.
Weiß nicht ob und wie vor Delphi XE das gemacht wurde, aber diese Unit gab es auch schon in Delphi 7, wenn ich mich nicht total irre.

Delphi-Quellcode:
procedure TWideStrings.SaveToStream(Stream: TStream; Encoding: TEncoding);
var
  Buffer, Preamble: TBytes;
begin
  if Encoding = nil then
    Encoding := TEncoding.Unicode; // The default encoding is UTF-16

  Buffer := Encoding.GetBytes(string(GetTextStr));
  Preamble := Encoding.GetPreamble;

  if Length(Preamble) > 0 then
    Stream.WriteBuffer(Preamble[0], Length(Preamble));

  Stream.WriteBuffer(Buffer[0], Length(Buffer));
end;
In Delphi 2007 ist das offenbar nicht der Fall. Die originäre Routine von CodeGear hatte ich eingangs als Delphi-Quellcode eingefügt. Der fehlende BOM verursachte für mich erst das Problem, weil der Konverter ohne dem die Dateiinhalte nicht lesen konnte.

Dein Quellcode mit der UTF8-Umwandlung habe ich nicht verstanden. Als Ergebnis kam bei mir eine ANSI-Datei heraus, deren Zeichen mit einem Leerzeichen voneinander getrennt waren.

Die Lösung ist jetzt aber dank Uwe Raabe da. Der Ansatz funktioniert, wobei ich immer noch nicht durchblicke, wann mit SizeOf, Length etc. gearbeitet werden muss. Ich hatte mir etliche Beispiele angeschaut, die sich aber meistens auf neuere Delphi-Versionen bezogen und somit nicht 1:1 umzusetzen waren.

Viele Grüße
Ingo
  Mit Zitat antworten Zitat
ioster

Registriert seit: 15. Aug 2008
84 Beiträge
 
Delphi 10.3 Rio
 
#14

AW: WideStringlist in UTF-8 mit Delphi 2007 speichern

  Alt 31. Aug 2023, 16:49
Delphi-Quellcode:
procedure SaveToUTF16(const Filename: string; Content: TWideStrings);
var
  BOM: TBytes;
  Stream : TFileStream;
  Zeile : WideString;
begin
  Zeile := Content.Text;
  Stream := TFileStream.Create(Filename, fmCreate);
  try
    BOM := TBytes.Create($FF, $FE);
    Stream.WriteBuffer(BOM[0], Length(BOM));
    Stream.WriteBuffer(Zeile[1], Length(Zeile)*Sizeof(Zeile[1]));
  finally
    Stream.Free;
  end;
end;
DANKE!!!! Das hat geholfen, wobei ich das inhaltlich immer noch nicht verstehe. Doch ich kann das Programm nun wieder in Kombination mit dem Konverter einsetzen ohne manuell per Editor den Dateiinhalt mit einer anderen Codierung abspeichern zu müssen.

Viele Grüße
Ingo
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#15

AW: WideStringlist in UTF-8 mit Delphi 2007 speichern

  Alt 31. Aug 2023, 17:22
der eizige Unterschied ist
* man kann das codierte BOM und anschließend den codierten Text in den Stream/Datei schreiben
* man kann aber auch das uncodierte BOM in den Text einfügen und das dann zusammen codiert in den Stream/Datei schreiben


#$FFFF ist ungültig/verboten (laut Unicode-Standard)
#$FFFE ist ungültig/verboten, aber wird als Char für den ByteOrderMark verwendet
#$FEFF ist ungültig/verboten, wegen Konflikt mit dem ByteOrderMark
und der Bereich #$Fxxxxxxx ist sowieso nicht existent (somit kein Konflikt möglich)

Folgendes sind BOM, welche alle dem Char #$FFFF entsprechen, jeweils in ihrer Codepage dargestellt.
EF BB BF = UTF-8
FE FF = UTF-16 (sowie auch UCS2), jeweils BigEndian und LittleEndian (kleinstes oder größtes Byte der Chars zuerst)
FF FE
00 00 FE FF = UTF-32, jeweils BigEndian und LittleEndian
FF FE 00 00


https://www.compart.com/de/unicode/U+FEFF
https://de.wikipedia.org/wiki/Byte_Order_Mark

Achtung $FF $FE ist $FEFF und nicht $FFFE


Windows ist LittleEndian (nicht so wie Apple früher mal BigEndian)
und in Dateien wird oft auch LittleEdnian gespeichert (also praktischer Weise sind somit Datei und RAM gleich)
-> zuerst das kleinste Byte
-> beim Dezimal und HEX aber die Ziffern der einzelnen Bytes wiederum BigEndian

Größere mehrstellige "Zahlen" sind aber BigEndian, im Text/Quellcode
-> zuerst die größte Ziffer

Im HTML/CSS sind Farbwerte aber andersrum, also LittleEndian, gegen über TColor -> #RRGGBB vs. $BBGGRR
$2B or not $2B

Geändert von himitsu (31. Aug 2023 um 17:40 Uhr)
  Mit Zitat antworten Zitat
mytbo

Registriert seit: 8. Jan 2007
472 Beiträge
 
#16

AW: WideStringlist in UTF-8 mit Delphi 2007 speichern

  Alt 31. Aug 2023, 17:28
Wenn umfangreicher mit UTF-8 gearbeitet wird, kannst du ab Delphi 7 mORMot verwenden. Ist der Eingang ein WideString, dann mit WideStringToUtf8 konvertieren:
Delphi-Quellcode:
type
  mormot.core.data,
  mormot.core.unicode;
  
var
  line: WideString;
  list: TRawUtf8List;
begin
  list := TRawUtf8List.Create;
  try
    line := '...';
    list.Add(WideStringToUtf8(line));
    list.SaveToFile('test.txt'); // write all lines into a new UTF-8 file
  finally
    list.Free;
  end;
Ansonsten den String-Typ RawUtf8 verwenden. Mit den Funktionen StringToUtf8/Utf8ToString diesen Typ in allen Delphi Versionen konvertieren.

Bis bald...
Thomas
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#17

AW: WideStringlist in UTF-8 mit Delphi 2007 speichern

  Alt 31. Aug 2023, 17:43
Eine Delphi-Vesion weiter (2009) war Unicode/UTF-8 dann auch nativ besser nutzbar.
$2B or not $2B
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 2     12   

 

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:52 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz