![]() |
AW: Mal wieder Kodierungsprobleme. ANSI UTF8 UTF16
Danke für die Erklärung.
Könnte haarig werden. Ich verwende hier und dort TFile.AppendAllText. Hier kann ich ja einfach TEncoding.Unicode dranhängen. Wie ich es beim LESEN mache (TFile.ReadAllText), muss ich noch gucken. Vielleicht eine kleine INterposer-Klasse für TFile oder so, wo ich dann im überschriebenem ReadAllText das Encoding prüfe.. Mal gucken Habe nun diese drei Proceduren/Funktionen in meine Shared-Utils-Sammlung aufgenommen. Bei Bedarf erweiterbar. Das hier ist erst der Anfang und soll nur eine zentrale Stelle Bilden, wo sich der Code zum Schreiben/Lesen befindet. Muss ich etwas ändern, ist es nur an einer Stelle und nicht an 100. Bisher funktioniert alles einwandfrei. UTF-16 LE wird problemlos geschrieben und gelesen.
Delphi-Quellcode:
Ich habe nun nach ein paar Stunden alles nach Unicode umgestellt. Alle Daten, egal wo im Programm, werden korrekt geschrieben und gelesen.
class procedure TFileUtils.FileAppendText(const Path, Contents: string; const Encoding: TEncoding);
begin TFile.AppendAllText(Path, Contents, Encoding); end; class procedure TFileUtils.FileWriteText(const Path, Contents: string; const Encoding: TEncoding); begin TFile.WriteAllText(Path, Contents, Encoding); end; class function TFileUtils.FileGetTextReadAllText(const Path: string; const Encoding: TEncoding): string; begin Result := TFile.ReadAllText(Path, Encoding); end; Lediglich da wo ich zu 100% weiß, dass niemals etwas anderes als a-z und 0-9 gespeichert wird, schreibe und lese ich trotzdem noch im utf-8-Format. Ich nutze UTF-16 aus einem einfachen Grund: wird eine Datei gelesen, die nicht UTF-16 ist, gibt es keine Fehlermeldung. |
AW: Mal wieder Kodierungsprobleme. ANSI UTF8 UTF16
Folgender Artikel hat mir die Augen geöffnet. Ist ein bisschen was zu lesen. Aber es ließt sich zum Glück einfacher als andere englische Texte
![]() Ich verwende nun UTF-8. |
AW: Mal wieder Kodierungsprobleme. ANSI UTF8 UTF16
..."Ich verwende nun UTF-8."...
keine schlechte Entscheidung, viele "alte" C/C++-Programmierer mit dem Dogma "ein String" ist und bleibt ein ByteArray sind diesen Weg gegangen! ->aber akzeptiere mit Delphi XE10.x das du nun überall ausser bei WebSeiten dich selbst stets beim Einlesen und Ausgeben und ALLEN WinApi Funktionen um die paassende Konvertierung kümmern musst, bzw immer prüfen ob die implizite Typkonvertierung von Delphi noch/schon richtig arbeitet. Denn leider ist "draussen" und in allen SYSTEM-APIs wenn UTF, dann UTF-16 verbreitet. Aber Kopfhoch, Lazerus/FreePascal schafft das ja auch, denn die arbeiten intern mit UTF8 und da gibt es von PC,Linux,Mac,Android,IOS,Rasperry,... "alles". Wenn du mal in Delphi mit UTF8 nicht weiter kommst, sieh eventuell mal in die Sourcen der LCL wie die das dort an der vergleichbaren Stelle machen. Ich arbeite intern auch mit UTF8. Da ich eh durchgehend mit Getter&Setter Funktionen für "string" Propertys arbeite ist das relativ problemlos. Man muss nur bei UTF8 beachten, das man als ZeichenAnzahl nicht simpel die Byteanzahl nimmt, weil diese ja eben oft nicht mit der realen Zeichenanzahl übereinstimmt... daher ist eine "eigene" Funktion ala "CharCount(utf8String)" gleich von Anfang an eine der wichtigsten Funktionen sie man sicher "einmal richtig" selbst schreiben(und verstehen) sollte. Wenn ich in meinen Programmen mit "CharCount" arbeite, geht es fast immer um Positionierung oder visuelle Begrenzungen. Wenn ich in meinen Programmen mit "Length" oder "StrLen" arbeite geht es bei mir weiter um Speicherplatz und echtes Lesen&Schreiben von "Bytes". ;)Ich hoffe ich habe dir hiermit nicht die "Lust" auf eigenes interes UTF8 verdorben.... aber 98% der aktuellen Delphi&Windowsprogrammier nehmen ja nicht zufällig lieber UTF-16, bzw. wissen garnicht das sie intern mit UTF-16 arbeiten;) |
AW: Mal wieder Kodierungsprobleme. ANSI UTF8 UTF16
Zitat:
Ich arbeite mit strings, nicht mit utf8strings. |
AW: Mal wieder Kodierungsprobleme. ANSI UTF8 UTF16
Wenn Du in Deiner Datei den Wert x90 findest, dann kann dieser für NOP stehen, ist sicher, daß an dieser Position Buchstaben zu finden sind, dann könnte es das Zeichen É sein (Extended ASCII) oder das zweite Byte in einer UTF8-Sequenz. Oder anders ausgedrückt es handelt sich nicht um eine ANSI-Kodierung. (Ich hoffe ich habe da recht).
Die Kodierung gibt an in welches Zeichen ein Wert bzw. eine Wertfolge übersetzt wird. Unter diesen Bedingungen wirst Du nur dann eine Fehlermeldung bekommen, wenn eine Kodierung dekodiert werden soll, die nicht zulässig ist (im Rahmen der gewählten Kodierung). Gruß K-H |
AW: Mal wieder Kodierungsprobleme. ANSI UTF8 UTF16
Es gibt noch das hier aber wie man das anwendet ist mir ein Rätsel.
![]() Sonst habe ich noch das hier gefunden, bin aber gerade unfähig eine ansi-Datei zu erstellen. Daher bekomme ich bei jeder Datei true zurück
Delphi-Quellcode:
Hier noch eine schöne Version. Gibt aber leider bei ANSI auch true zurück
function FileMayBeUTF8(FileName: WideString): Boolean;
var Stream: TMemoryStream; BytesRead: Integer; ArrayBuff: array [0 .. 127] of Byte; PreviousByte: Byte; i: Integer; YesSequences, NoSequences: Integer; begin if not FileExists(FileName) then Exit; YesSequences := 0; NoSequences := 0; Stream := TMemoryStream.Create; try Stream.LoadFromFile(FileName); repeat {read from the TMemoryStream} BytesRead := Stream.Read(ArrayBuff, High(ArrayBuff) + 1); {Do the work on the bytes in the buffer} if BytesRead > 1 then begin for i := 1 to BytesRead - 1 do begin PreviousByte := ArrayBuff[i - 1]; if ((ArrayBuff[i] and $C0) = $80) then begin if ((PreviousByte and $C0) = $C0) then begin inc(YesSequences) end else begin if ((PreviousByte and $80) = $0) then inc(NoSequences); end; end; end; end; until (BytesRead < (High(ArrayBuff) + 1)); // Below, >= makes ASCII files = UTF-8, which is no problem. // Simple > would catch only UTF-8; Result := (YesSequences >= NoSequences); finally Stream.Free; end; end;
Delphi-Quellcode:
function UTF8CharLength(const c: Byte): Integer;
begin // First Byte: 0xxxxxxx if ((c and $80) = $00) then begin Result := 1; end // First Byte: 110yyyyy else if ((c and $E0) = $C0) then begin Result := 2; end // First Byte: 1110zzzz else if ((c and $F0) = $E0) then begin Result := 3; end // First Byte: 11110uuu else if ((c and $F8) = $F0) then begin Result := 4; end // not valid, return the error value else begin Result := -1; end; end; function UTF8IsTrailChar(const c: Byte): Boolean; begin // trail bytes have this form: 10xxxxxx Result := ((c and $C0) = $80); end; function IsUTF8Memory(AMem: PBYTE; ASize: Int64): Boolean; var i: Int64; c: Integer; begin Result := True; i := 0; while (i < ASize) do begin // get the length if the current UTF-8 character c := UTF8CharLength(AMem^); // check if it is valid and fits into ASize if ((c >= 1) and (c <= 4) and ((i + c - 1) < ASize)) then begin Inc(i, c); Inc(AMem); // if it is a multi-byte character, check the trail bytes while (c > 1) do begin if (not UTF8IsTrailChar(AMem^)) then begin Result := False; Break; end else begin Dec(c); Inc(AMem); end; end; end else begin Result := False; end; if (not Result) then Break; end; end; |
AW: Mal wieder Kodierungsprobleme. ANSI UTF8 UTF16
Ich habe mich an der ganzen Sache nun mal versucht. Schöner bekomme ich es leider nicht hin
Delphi-Quellcode:
Ich hätte auch noch das hier im Angebot:
function ByteToHex(AByte: Byte): string;
const Digits: array [0 .. 15] of char = '0123456789ABCDEF'; begin Result := Digits[AByte shr 4] + Digits[AByte and $0F]; end; function BytesToHex(ABytes: TBytes): string; var i: Integer; begin for i := 0 to High(ABytes) do Result := Result + ByteToHex(ABytes[i]); end; function GetFileEncoding(const FileName: string): string; var Stream: TBytesStream; Bytes: TBytes; begin Stream := TBytesStream.Create; try Stream.LoadFromFile(FileName); if Stream.Size >= 3 then begin SetLength(Bytes, 3); Stream.ReadData(Bytes, 3); end else if Stream.Size >= 2 then begin SetLength(Bytes, 2); Stream.ReadData(Bytes, 2); end; if BytesToHex(Bytes) = 'EFBBBF' then ShowMessage('UTF-8 BOM') else if BytesToHex(Bytes) = 'FEFF' then ShowMessage('UTF-16 BE'); finally Stream.Free; end; end;
Delphi-Quellcode:
function IsTextUnicode(const Text: string): Boolean;
var C: Char; begin Result := False; for C in Text do begin if C > #127 then begin Result := True; Break; end; end; end; function IsFileUnicode(const AFile: string): Boolean; var i: Int64; Stream: TBytesStream; begin Result := False; Stream := TBytesStream.Create; try Stream.LoadFromFile(AFile); for i := 0 to Stream.Size - 1 do begin if Char(Stream.Bytes[i]) > #127 then begin Result := True; Break; end; end; finally Stream.Free; end; end; |
AW: Mal wieder Kodierungsprobleme. ANSI UTF8 UTF16
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:04 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz