Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Kaputte Datei ohne Encoding mit Umlauten in StringList laden+Zeichen erhalten (https://www.delphipraxis.net/200371-kaputte-datei-ohne-encoding-mit-umlauten-stringlist-laden-zeichen-erhalten.html)

DieDolly 14. Apr 2019 16:47


Kaputte Datei ohne Encoding mit Umlauten in StringList laden+Zeichen erhalten
 
Spoiler: die Daten wären verloren :lol:

Ich komme bei einem Problem nicht weiter. Ich lade mit TFile und TEncoding.UTF8 eine Datei in eine StringList. Ich möchte es jedenfalls.

Aber meine Datei scheint kaputt zu sein.
Die Datei ist laut Notepad++ ohne Encoding. Laut Sublime Western (Windows 1252).

Die Datei hat vor dem Speichern den Inhalt
Zitat:

Ä ʘ Ü
und hat laut Notepad++ wie gesagt danach kein Encoding. Sublime ließt die Datei als
Zitat:

Ä ? Ü
ein.
Ich habe vorerst eine Behandlung eingebaut die auf TEncoding.Default zurückgreift, wenn das Laden in meiner eigenen TFile mit UTF8 fehlschlägt. So bekomme ich ebenfalls das Sublime Ergebnis.

Kann man das schöner behandeln?

Delphi-Quellcode:
 try
  Result := TFile.ReadAllText(Path, TEncoding.UTF8);
 except
  Result := TFile.ReadAllText(Path, TEncoding.Default);
 end;

peterbelow 15. Apr 2019 10:53

AW: Kaputte Datei ohne Encoding mit Umlauten in StringList laden+Zeichen erhalten
 
Wenn die Datei Utf-8 ist, aber halt keine BOM hat, versuch mal eine Instanz dieses encodings:

Delphi-Quellcode:
type
  {!
  <summary>
   UTF8 encoding class without BOM, can be used to write files in
   UTF8 encoding without a BOM, e.g. XML or XHTML files.
  </summary>}
  TNoBomUTF8Encoding = class(TUTF8Encoding)
  public
    {!
    <summary>
     Return a zero-elements array to use as a BOM.
    </summary>}
    function GetPreamble: System.TArray<System.Byte>; override;
  end;

function TNoBomUTF8Encoding.GetPreamble: System.TArray<System.Byte>;
begin
  SetLength(Result,0);
end;

DieDolly 15. Apr 2019 12:10

AW: Kaputte Datei ohne Encoding mit Umlauten in StringList laden+Zeichen erhalten
 
Die Datei ist nicht UTF-8. Sie ist Western Windows 1252.

Schokohase 15. Apr 2019 12:14

AW: Kaputte Datei ohne Encoding mit Umlauten in StringList laden+Zeichen erhalten
 
Zitat:

Zitat von DieDolly (Beitrag 1430332)
Die Datei ist nicht UTF-8. Sie ist Western Windows 1252.

Hier wäre eine Klarstellung notwendig.

Im ersten Post schreibst du, dass
Zitat:

Zitat von DieDolly (Beitrag 1430291)
Die Datei ist laut Notepad++ ohne Encoding. Laut Sublime Western (Windows 1252).

Welches Encoding für diese Text-Datei verwendet wurde kann (ohne BOM) nur der Ersteller der Text-Datei zuverlässig mitteilen, alles andere ist reine Spekulation oder basiert auf Vermutungen/Annahmen.

Also: Ist deine Angabe zum Encoding nun eine gesicherte Information vom Ersteller der Datei oder eben diese geschätzte Annahme von Sublime (der trotz dieser Annahme die Datei nicht richtig darstellen kann).

BTW: Jede Textdatei hat ein Encoding. Ohne Encoding ist es keine Textdatei, sondern nur ein Haufen Bytes. Wenn Notepad++ kein Encoding angibt, dann heißt das nicht, es gibt dort kein Encoding, sondern die verwendeten Prüfverfahren von Notepad++ konnten kein Encoding aus der Datei herauslesen.

DieDolly 15. Apr 2019 12:18

AW: Kaputte Datei ohne Encoding mit Umlauten in StringList laden+Zeichen erhalten
 
Leider weiß ich nicht wie diese Datei erzeugt wurde.
Ich habe nur noch ein seltenes Exemplar davon auf meinem Computer.

Zitat:

Also: Ist deine Angabe zum Encoding nun eine gesicherte Information vom Ersteller der Datei oder eben diese geschätzte Angabe von Sublime (der trotz dieser Annahme die Datei nicht richtig darstellen kann).
Das ist von Sublime. Ich glaube nicht, dass das Unicodezeichen überhaupt noch in der Datei existiert. Das Encoding fehlt schließlich.

Soll ich die Datei mal hier hochladen? Sie ist 5 Bytes groß (3 Zeichen, 2 Leerstellen), offensichtlich kein Multibyte.

Schokohase 15. Apr 2019 12:26

AW: Kaputte Datei ohne Encoding mit Umlauten in StringList laden+Zeichen erhalten
 
Die brauchst du nicht hochladen, sondern diese 5 Bytes kannst du auch als Hex-Zeichenfolge hier direkt posten.

Gibt es einen Hinweis, was für eine Information diese 5 Bytes beinhalten sollen? Denn bei 5 Zeichen (effektiv 3) ist der Informationsgehalt für Text doch recht dürftig

DieDolly 15. Apr 2019 12:40

AW: Kaputte Datei ohne Encoding mit Umlauten in StringList laden+Zeichen erhalten
 
Das ist eine Datei mit freiem, zuzfälligem Testinhalt.
Egal was drin stünde, die Daten wären verloren zwecks fehlendem Encoding. Das ist mir jetzt klar.

Zitat:

C4 20 3F 20 DC

A ? Ü
3F, Fragezeichen. Da wäre im schlimmsten Fall nix zu retten.

Gilt hier als Notlösung so eine Datei einfach mit TEncoding.Default zu laden?

Schokohase 15. Apr 2019 13:00

AW: Kaputte Datei ohne Encoding mit Umlauten in StringList laden+Zeichen erhalten
 
Zitat:

Zitat von DieDolly (Beitrag 1430338)
Gilt hier als Notlösung so eine Datei einfach mit TEncoding.Default zu laden?

NEIN - Wenn du das Encoding nicht kennst und auch in keiner Weise herleiten kannst, dann kannst du die Datei nicht so interpretieren, wie du es müsstest.

Das gleiche Problem hast du mit einer PNG-Datei (dir so nicht bewusst) und du das pauschal eben dann einfach als BMP öffnest. Dort gibt es auch nur Murks (bzw. da wirst du eine Fehlermeldung bekommen). Bei Text gibt es aber keine Fehlermeldungen bei falsch gewähltem Encoding (bzw. sehr selten).

Wenn du aber nicht weißt, was diese Datei bedeutet, warum willst du diese dann öffnen/verarbeiten? Das ergibt keinen Sinn.

Einen Zettel mit irgendwelchen kryptischen Zeichen drauf ergibt auch keinen Sinn, wenn man keinen Anhaltspunkt hat, was der zu bedeuten hat. Vielleicht nur eine Schriftprobe?

Delphi.Narium 15. Apr 2019 13:41

AW: Kaputte Datei ohne Encoding mit Umlauten in StringList laden+Zeichen erhalten
 
3F ist der Hexadezimalwert für das Fragezeichen im ASCII-Zeichensatz, da dürfte es (beinahe) egal sein, ob nun "Western Windows 1252" oder sonst irgendwas aus der "ISO 8859-Ecke".

Das Fragezeichen ist ein reguläres Fragezeichen und nicht das Fragezeichen, dass man zuweilen angezeigt bekommt, wenn eine Datei irgendwas enthält, was man mit dem gewählten / erratenen Zeichensatz nicht darstellen kann.

Uwe Raabe 15. Apr 2019 13:53

AW: Kaputte Datei ohne Encoding mit Umlauten in StringList laden+Zeichen erhalten
 
Das 3F- Fragezeichen entsteht aber wohl schon weiter hinten in der Kette, denn

Zitat:

Zitat von DieDolly (Beitrag 1430291)
Die Datei hat vor dem Speichern den Inhalt
Zitat:

Ä ʘ Ü


DieDolly 15. Apr 2019 14:18

AW: Kaputte Datei ohne Encoding mit Umlauten in StringList laden+Zeichen erhalten
 
Genau und wenn ich die Datei mit UTF8 Encoding laden möchte knallt es. Deswegen try-except und im except dann TEncoding.Default.

Erst gucke ich ob ein BOM vorhanden ist. Wenn nicht prüfe ich jedes Zeichen der Datei (Stream) ob es über #127 hinaus geht. Wenn ja, sind zumindest Zeichen außerhalb der 8 bit vorhanden.
Dann versuche ich mit UTF8 Encoding die Datei zu laden was auch bei vernünftigen Dateien funktioniert. Knallt es dann im Except kommt Default zum Einsatz.

Gausi 15. Apr 2019 15:03

AW: Kaputte Datei ohne Encoding mit Umlauten in StringList laden+Zeichen erhalten
 
Zitat:

Zitat von DieDolly (Beitrag 1430350)
Wenn nicht prüfe ich jedes Zeichen der Datei (Stream) ob es über #127 hinaus geht. Wenn ja, sind zumindest Zeichen außerhalb der 8 bit vorhanden.

Mit dem Test auf #127 erreichst du aber nur 7 Bit. D.h. wenn du eine "Ansi-kodierte" Datei hast (oder Windows 1252, oder eine andere 1-Byte-Kodierung), und du hast Umlaute drin, dann schlägt das schon fehl - denn die sind jenseits von #127. Wenn du dann mit UTF8 dran gehst, dann dürfte es regelmäßig knallen, würde ich vermuten. Oder es kommt zumindest anderweitig Unsinn raus.

Uwe Raabe 15. Apr 2019 15:23

AW: Kaputte Datei ohne Encoding mit Umlauten in StringList laden+Zeichen erhalten
 
Du könntest die Überprüfung noch etwas verfeinern, in dem du auf eine gültige UTF-8 Kodierung prüfst:
  1. Ist das höchste Bit 0, ist es ein ASCII-Zeichen (entspricht deinem Test)
  2. Sind die höchsten drei Bit eine 110, dann kommt als nächstes ein Folgebyte
  3. Sind die höchsten vier Bit eine 1110, dann kommen als nächstes zwei Folgebyte
  4. Sind die höchsten fünf Bit eine 11110, dann kommen als nächstes drei Folgebyte
  5. Ein Folgebyte hat als höchste zwei Bit eine 10

DieDolly 15. Apr 2019 16:10

AW: Kaputte Datei ohne Encoding mit Umlauten in StringList laden+Zeichen erhalten
 
Habe ich eben reingeschrieben.
Ich erhalte jetzt TEncoding.Default immer dann zurück, wenn alle Versuche UTF-8 zu erkennen schief gehen und nichts vorhanden ist.
UTF-8 mit und ohne BOM erkennen ist ja relativ einfach. Aber solche Western Dateien die fallen durch alle Raster und ganz am Ende der Prüfkette muss man dann eben auf Default ausweichen.

Eine andere Lösung für das Problem ist, dass ich das was zu speichern ist prüfe. Notwendig eigentlich nicht.
Delphi-Quellcode:
for Ch in Str do
 begin
  if (Ch >= #32) and (Ch <= #127) then
   Result := Result + Ch;
 end;
Bis zu welchem Bereich kann man bedenkenlos prüfen, um noch im UTF-8-Bereich zu bleiben?
ASCII ist ja scheinbar bis 127. Bis wohin geht denn UTF-8? Weil irgendwann sind die Zeichen so groß, dass sie unter UTF-16 fallen.
Und standardmäßig lade und speichere ich Daten in meinem Programm mit UTF-8-Encoding.

Obwohl ich gerade sehe, dass ich bis Unicode U+5613 gehen kann und alles richtig gespeichert und geladen wird mit UTF-8.
Das passt denke ich.

" U+24F5C " wird auch korrekt mit UTF 8 kodiert gespeichert und gelesen.
Entweder war mein Delphi damals einfach zu alt für solche Spielchen oder es liegt an Windows 10 dass jetzt alles mit solchen Zeichen funktioniert
https://de.wikipedia.org/wiki/UTF-16

Uwe Raabe 15. Apr 2019 16:41

AW: Kaputte Datei ohne Encoding mit Umlauten in StringList laden+Zeichen erhalten
 
Zitat:

Zitat von DieDolly (Beitrag 1430356)
Bis wohin geht denn UTF-8?

UTF-8 ist ja nicht durch einen Zahlenbereich gekennzeichnet, sondern wie oben beschrieben über bestimmte Bitmuster. Insbesondere gibt es Bytes bzw. Bytefolgen zwischen 128 und 255, die kein UTF-8 darstellen. Deswegen kann ja auch das Decodieren mit UTF-8 zu einer Exception führen.

ANSI-Decodieren (wie z.b. 1252) geht aber immer, da dort alle Zeichen im Bereich 0..255 gültig sind (vielleicht nicht sinnvoll, aber gültig). Was dann allerdings dabei heraus kommt ist eben von der verwendeten Codepage abhängig. Wenn du ein mit CP 1253 codiertes File als CP 1252 decodierst, kann eben was falsches raus kommen und du würdest es nicht mal merken, wenn du das gewünschte Ergebnis nicht kennst.

Mit UTF-8 kannst du im Grunde jedes Unicode Zeichen codieren. Du brauchst halt für manche Zeichen eben mehr als 1 Byte.

DieDolly 15. Apr 2019 16:48

AW: Kaputte Datei ohne Encoding mit Umlauten in StringList laden+Zeichen erhalten
 
Bei meinen Tests bin ich von 1 bis 4 Byte pro Zeichen gekommen und UTF-8 ging immer gut.
Ich versuche nur das Schlimmste zu vermeiden. Aber wenn jemand in den Daten rumspielt und sie absichtlich verändert kann ich auch nix mehr machen :gruebel:


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:21 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