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 1 von 2  1 2      
ioster

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

WideStringlist in UTF-8 mit Delphi 2007 speichern

  Alt 30. Aug 2023, 16:12
Moin,

ich habe eine Anwendung, die Textzeilen nach einem vorgegebenen Format in einer Stringlist sammelt und dann in einer Textdatei wegschreibt, die von einem Konverter zur Weiterverarbeitung abgegriffen wird.

Nun stand eine Änderung an, weil in den Strings Zeichen aus dem erweiterten Zeichensatz verarbeitet werden sollten. Konkret geht es um slowakische Sonderzeichen.

Deswegen musste ich die Routinen auf Widestrings und eine Widestringlist umbauen. Funktioniert inzwischen so weit auch wunderbar, ABER der Konverter streikt, da die neuen Textdateien in UTF-16-LE und nicht mehr in UTF-8 codiert werden.

Ich nutze zur Speicherung die Methode SaveToFile, die leider keine Optionen in Sachen Codierung bietet. Anhand der Sourcen konnte ich auch nur ermitteln, dass beim Aufruf der Methode ein FileStream zur Speicherung genutzt wird.

Delphi-Quellcode:
procedure TWideStrings.SaveToFile(const Filename: WideString);
var
  Stream: TStream;
begin
  Stream := TFileStream.Create(Filename, fmCreate);
  try
    SaveToStream(Stream);
  finally
    Stream.Free;
  end;

procedure TWideStrings.SaveToStream(Stream: TStream);
var
  S: WideString;
begin
  S := GetTextStr;
  Stream.WriteBuffer(Pointer(S)^, Length(S) * SizeOf(WideChar));
end;
Ich gehe davon aus, dass die UTF-Codierung irgendwo an einer anderen Stelle festgelegt ist.

Hat jemand eine Idee, wie ich mit einer ähnlichen Funktion die Codierung des Outputs selber steuern kann? Alles was ich gefunden habe, passte nicht zu Delphi 2007.

Danke im Voraus.
Ingo
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

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

AW: WideStringlist in UTF-8 mit Delphi 2007 speichern

  Alt 30. Aug 2023, 16:23
Wenn UTF-8, dann kann das auch eine normale TStringList (nur das BOM, falls nötig, mußt du einfach als erstes Zeichen in die erste Zeile einfügen).

Delphi-Referenz durchsuchenTEncoding, in aktuelleren Delphis,
aber hier geht auch MSDN-Library durchsuchenWideCharToMultiByte mit CP_UTF8
oder eine der vielen UTF8-Konvertierungs-Funktionen aus der System.pas


PS: Der Delphi-Referenz durchsuchenUTF8String ist einfach ein AnsiString, mit entsprechender CodePage.
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.

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

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

AW: WideStringlist in UTF-8 mit Delphi 2007 speichern

  Alt 31. Aug 2023, 08:44
Moin,

ich kann in dem Projekt nur auf die Möglichkeiten von Delphi 2007 zurückgreifen. Anhand von Foreneinträgen und technischen Tipps habe ich schon festgestellt, dass sich der Hersteller inzwischen einiges mehr zu dem Thema einfallen lassen hat.

Eine TStringlist habe ich bisher genutzt. Doch damit komme ich nicht weiter, wenn ich den erweiterten Zeichensatz verarbeiten möchte. Den kann ich nur mit WideStrings auslesen und ich wurde auch schon gerüffelt, als ich bei den Kollegen nachfragte, warum denn die Sonderzeichen bei der Zuweisung in die TStringlist wieder verschwinden würden. Daran merkt man, dass ich bisher mit den WideStrings in der Form nichts zu tun hatte.

Jetzt habe ich gestern versucht, die WideStringliste Zeile für Zeile mit einem Filestream abzuspeichern, habe dabei aber nichts Brauchbares erzeugen können. Wenn ich die Textdatei mit einem Editor öffne, bekomme ich Sonderzeichen aus dem südostasiatischen Raum angezeigt - vermutlich chinesisch.

Ich möchte zusätzlich auch den BOM mitgeben, weil es der Konverterhersteller sich so wünscht. Aus Codebeispielen habe ich versucht, mir eine eigene Prozedur zusammenzustellen, die so aussieht:

Delphi-Quellcode:
procedure SaveToUTF16(const Filename: string; Content: TWidestringlist);
var
  BOM : WideChar;
  Stream : TFileStream;
  Zaehler : integer;
  Zeile : WideString;
begin
  Stream := TFileStream.Create(Filename, fmCreate);
  
  try
    BOM := WideChar($FFFE);
    Stream.WriteBuffer(BOM, SizeOf(BOM));

    FOR Zaehler := 0 to Content.Count - 1 Do
      begin
        Zeile := WideString(Content[Zaehler] + sLineBreak);
        Stream.WriteBuffer(PWideChar(Zeile)^, Length(Zeile) * SizeOf(WideChar));
      end;
  finally
    Stream.Free;
end;
Ich fürchte nur, dass ich ein Problem bei der Umwandlung oder bei der Positionierung des Streams habe.

Es hat schon seinen Grund, warum ich sonst gerne auf bestehende Methoden wie SaveToFile zurückgreife.

Danke im Voraus.

Viele Grüße
Ingo
  Mit Zitat antworten Zitat
shebang
Online

Registriert seit: 7. Feb 2020
124 Beiträge
 
Delphi 11 Alexandria
 
#4

AW: WideStringlist in UTF-8 mit Delphi 2007 speichern

  Alt 31. Aug 2023, 08:54
Wenn ich die Textdatei mit einem Editor öffne, bekomme ich Sonderzeichen aus dem südostasiatischen Raum angezeigt - vermutlich chinesisch.
Erkennt der Editor denn die von dir gewünschte Kodierung?
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

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

AW: WideStringlist in UTF-8 mit Delphi 2007 speichern

  Alt 31. Aug 2023, 09:32
In deinem Code speicherst du aber UTF-16 anstatt UTF-8. Ist das denn so gewollt?

ABER der Konverter streikt, da die neuen Textdateien in UTF-16-LE und nicht mehr in UTF-8 codiert werden.
Mit dieser kleinen Routine kannst du auch UTF-8 schreiben:
Delphi-Quellcode:
uses
  WideStrings, WideStrUtils;

procedure SaveToUTF8(const Filename: string; Content: TWideStrings);
var
  Stream : TFileStream;
  Zeile : UTF8String;
begin
  Zeile := UTF8Encode(Content.Text);
  Stream := TFileStream.Create(Filename, fmCreate);
  try
    Stream.WriteBuffer(sUTF8BOMString[1], Length(sUTF8BOMString));
    Stream.WriteBuffer(Zeile[1], Length(Zeile));
  finally
    Stream.Free;
  end;
end;
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
ioster

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

AW: WideStringlist in UTF-8 mit Delphi 2007 speichern

  Alt 31. Aug 2023, 09:58
Wenn ich die Textdatei mit einem Editor öffne, bekomme ich Sonderzeichen aus dem südostasiatischen Raum angezeigt - vermutlich chinesisch.
Erkennt der Editor denn die von dir gewünschte Kodierung?
Da ich Textdateien erzeuge, öffne ich sie mit Doppelklick mit dem Editor, der von Microsoft in Windows zur Verfügung gestellt wird. Der unterscheidet die Codierungen.
editor_codierung.png
Darüber habe ich auch den Unterschied zwischen den Textdateien aus Stringlist und WideStringlist feststellen können. Mit einem Hex-Editor gehe ich an so etwas nicht heran.

Speichere ich nun Textzeilen mit der oben aufgeführten Routine, dann wird als Codierung UTF-16-BE angezeigt, doch der Dateiinhalt ist alles andere als lesbar.
utf_16be.png
Nach meinem Verständnis müsste dort trotzdem Klartext erkennbar sein.
  Mit Zitat antworten Zitat
ioster

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

AW: WideStringlist in UTF-8 mit Delphi 2007 speichern

  Alt 31. Aug 2023, 10:00
In deinem Code speicherst du aber UTF-16 anstatt UTF-8. Ist das denn so gewollt?

ABER der Konverter streikt, da die neuen Textdateien in UTF-16-LE und nicht mehr in UTF-8 codiert werden.
Mit dieser kleinen Routine kannst du auch UTF-8 schreiben:
Delphi-Quellcode:
uses
  WideStrings, WideStrUtils;

procedure SaveToUTF8(const Filename: string; Content: TWideStrings);
var
  Stream : TFileStream;
  Zeile : UTF8String;
begin
  Zeile := UTF8Encode(Content.Text);
  Stream := TFileStream.Create(Filename, fmCreate);
  try
    Stream.WriteBuffer(sUTF8BOMString[1], Length(sUTF8BOMString));
    Stream.WriteBuffer(Zeile[1], Length(Zeile));
  finally
    Stream.Free;
  end;
end;
Der Konverterhersteller schrieb mir, ich könne auch UTF-16 verwenden, wenn ich den fehlenden BOM $FFFE mitgeben würde. Ich werde die Funktion mit UTF-8 gleich einmal ausprobieren.

Viele Grüße
Ingo
  Mit Zitat antworten Zitat
ioster

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

AW: WideStringlist in UTF-8 mit Delphi 2007 speichern

  Alt 31. Aug 2023, 10:21
In deinem Code speicherst du aber UTF-16 anstatt UTF-8. Ist das denn so gewollt?

ABER der Konverter streikt, da die neuen Textdateien in UTF-16-LE und nicht mehr in UTF-8 codiert werden.
Mit dieser kleinen Routine kannst du auch UTF-8 schreiben:
Delphi-Quellcode:
uses
  WideStrings, WideStrUtils;

procedure SaveToUTF8(const Filename: string; Content: TWideStrings);
var
  Stream : TFileStream;
  Zeile : UTF8String;
begin
  Zeile := UTF8Encode(Content.Text);
  Stream := TFileStream.Create(Filename, fmCreate);
  try
    Stream.WriteBuffer(sUTF8BOMString[1], Length(sUTF8BOMString));
    Stream.WriteBuffer(Zeile[1], Length(Zeile));
  finally
    Stream.Free;
  end;
end;
Die UTF8-Routine funktioniert. Vielen lieben Dank!!!

Was müsste ich denn jetzt ändern, um UTF16 ausgeben zu können. Die Konvertierung entfällt dann ja. Grundsätzlich dürfte sich das Verfahren ja nicht unterscheiden, oder?

Viele Grüße
Ingo
  Mit Zitat antworten Zitat
ioster

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

AW: WideStringlist in UTF-8 mit Delphi 2007 speichern

  Alt 31. Aug 2023, 12:13
Ich bin irgendwie zu blöd, um zu kapieren, wie man den BOM in eine UTF-16-Datei geschrieben bekommt.

Nun habe ich die UTF8-Lösung und habe auf dem CodeGear-Quellcode basierend das für den Fall der Fälle das für UTF-16 umsetzen wollen. Sobald ich den BOM wegschreibe, kommt in der Datei nichts Vernünftiges an.

Es dürfte doch jetzt eigentlich nur noch um eine Zeile gehen.

Delphi-Quellcode:
  BOM := WideChar($FFFE);
  Stream.WriteBuffer(BOM, SizeOf(BOM));
Muss ich bei WriteBuffer mit Length oder SizeOf arbeiten und wie muss ich den BOM bearbeiten?
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

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

AW: WideStringlist in UTF-8 mit Delphi 2007 speichern

  Alt 31. Aug 2023, 15:19
Jupp, das #$FEFF ist das Unicode-BOM.

Es wird in der jeweiligen Codepage gespeichert. (wenn sie es darstellen kann)


Am Einfachsten als Char/WideChar an den Anfang des Textes.
BOM geht z.B. beim UTF-16-LE, UTF-16-BE und UTF-8. (ja, die 3 UTF8-Bytes sind jenes Char)

Delphi-Quellcode:
  Zeile := UTF8Encode(#$FEFF + Content.Text);
  Stream := TFileStream.Create(Filename, fmCreate);
  try
    //Stream.WriteBuffer(sUTF8BOMString[1], Length(sUTF8BOMString));
    Stream.WriteBuffer(Zeile[1], Length(Zeile)); // natürlich würde @Zeile[1] knallen, wenn der String leer ist
  finally
    Stream.Free;
  end;
Hach, wie schön doch ein Delphi-Referenz durchsuchenTFile.WriteAllText sein kann.
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.

Geändert von himitsu (31. Aug 2023 um 17:25 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      

 

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 15:01 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