AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Mal wieder Kodierungsprobleme. ANSI UTF8 UTF16
Thema durchsuchen
Ansicht
Themen-Optionen

Mal wieder Kodierungsprobleme. ANSI UTF8 UTF16

Ein Thema von LTE5 · begonnen am 17. Nov 2017 · letzter Beitrag vom 20. Nov 2017
Antwort Antwort
Seite 4 von 4   « Erste     234   
LTE5

Registriert seit: 13. Nov 2017
355 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#31

AW: Mal wieder Kodierungsprobleme. ANSI UTF8 UTF16

  Alt 18. Nov 2017, 12:49
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:
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;
Ich habe nun nach ein paar Stunden alles nach Unicode umgestellt. Alle Daten, egal wo im Programm, werden korrekt geschrieben und gelesen.
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.

Geändert von LTE5 (18. Nov 2017 um 15:06 Uhr)
  Mit Zitat antworten Zitat
LTE5

Registriert seit: 13. Nov 2017
355 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#32

AW: Mal wieder Kodierungsprobleme. ANSI UTF8 UTF16

  Alt 18. Nov 2017, 17:28
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

The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)

Ich verwende nun UTF-8.
  Mit Zitat antworten Zitat
mensch72

Registriert seit: 6. Feb 2008
838 Beiträge
 
#33

AW: Mal wieder Kodierungsprobleme. ANSI UTF8 UTF16

  Alt 18. Nov 2017, 18:45
..."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
  Mit Zitat antworten Zitat
LTE5

Registriert seit: 13. Nov 2017
355 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#34

AW: Mal wieder Kodierungsprobleme. ANSI UTF8 UTF16

  Alt 18. Nov 2017, 18:53
Zitat:
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.
Ich gucke einfach ob Fehler auftreten und erst dann ändere ich was. Richtig verstanden habe ich das eh nicht und dieses Byte-geschupse mit Streams... davon halte ich mich eh fern

Ich arbeite mit strings, nicht mit utf8strings.
  Mit Zitat antworten Zitat
Benutzerbild von p80286
p80286

Registriert seit: 28. Apr 2008
Ort: Stolberg (Rhl)
6.659 Beiträge
 
FreePascal / Lazarus
 
#35

AW: Mal wieder Kodierungsprobleme. ANSI UTF8 UTF16

  Alt 18. Nov 2017, 22:12
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
Programme gehorchen nicht Deinen Absichten sondern Deinen Anweisungen
R.E.D retired error detector
  Mit Zitat antworten Zitat
LTE5

Registriert seit: 13. Nov 2017
355 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#36

AW: Mal wieder Kodierungsprobleme. ANSI UTF8 UTF16

  Alt 18. Nov 2017, 22:28
Es gibt noch das hier aber wie man das anwendet ist mir ein Rätsel.
http://chsdet.sourceforge.net/

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:
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;
Hier noch eine schöne Version. Gibt aber leider bei ANSI auch true zurück
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;

Geändert von LTE5 (18. Nov 2017 um 22:46 Uhr)
  Mit Zitat antworten Zitat
LTE5

Registriert seit: 13. Nov 2017
355 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#37

AW: Mal wieder Kodierungsprobleme. ANSI UTF8 UTF16

  Alt 19. Nov 2017, 00:10
Ich habe mich an der ganzen Sache nun mal versucht. Schöner bekomme ich es leider nicht hin

Delphi-Quellcode:
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) = 'EFBBBFthen
   ShowMessage('UTF-8 BOM')
  else if BytesToHex(Bytes) = 'FEFFthen
   ShowMessage('UTF-16 BE');

 finally
  Stream.Free;
 end;
end;
Ich hätte auch noch das hier im Angebot:
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;

Geändert von LTE5 (19. Nov 2017 um 12:12 Uhr)
  Mit Zitat antworten Zitat
freimatz

Registriert seit: 20. Mai 2010
1.456 Beiträge
 
Delphi 11 Alexandria
 
#38

AW: Mal wieder Kodierungsprobleme. ANSI UTF8 UTF16

  Alt 20. Nov 2017, 12:12
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
Warum sollte man intern mit UTF8 arbeiten? Der Vorteil hat sich mir noch nicht erschlossen. Ich selber nehme intern das Delphi übliche UTF-16. Nach außen wandele ich dann was gerade dran ist wei z.B. ANSI oder UTF-8. Intern muss ich noch teilweise noch Hand anlegen wgen altem Code und weil die Unterstützung von Delphi für Surrogaten recht bescheiden ist.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 4 von 4   « Erste     234   


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 22:20 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