Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Software-Projekte der Mitglieder (https://www.delphipraxis.net/26-software-projekte-der-mitglieder/)
-   -   Vorstellung Unit: File encoding detector (https://www.delphipraxis.net/194428-vorstellung-unit-file-encoding-detector.html)

LTE5 19. Nov 2017 12:23


Vorstellung Unit: File encoding detector
 
Ich möchte euch gerne meine Arbeit aus den vergangenen Tagen vorstellen.
Ich bin kein Profi und habe mich erst vor wenigen Tagen in Streams eingelesen.

Ich brauchte eine Lösung, um mehr oder weniger zuverlässig das Encoding einer Datei herausfinden zu können.
Über BOM ist das ja leider nicht immer feststellbar, daher habe ich eine andere Lösung entworfen.

Sie ist weder professionell noch gut, aber sie funktioniert. Es ist mehr oder weniger eine Zusammenstellung aus Dingen die ich im Internet gefunden habe.
Daher bitte ich um Feedback! Ihr könnt die Unit auch gerne kopieren, anpassen und hier im Beitrag wieder posten.

Der Aufruf ist einfach
Delphi-Quellcode:
var IsUnicode: Boolean;
begin
 IsUnicode := TEncodingDetect.IsFileUnicode('pfad-zur-datei.txt');
So ist es auch möglich
Delphi-Quellcode:
 Memo1.Lines.Clear;

 Memo1.Lines.Add('File unicode: ' + BoolToStr(TEncodingDetect.IsFileUnicode('pfad-zur-datei.txt'), True));
 Memo1.Lines.Add('String unicode: ' + BoolToStr(TEncodingDetect.IsTextUnicode('ʥ'), True));
 Memo1.Lines.Add('String unicode: ' + BoolToStr(TEncodingDetect.IsTextUnicode('ABC'), True));
 Memo1.Lines.Add('File content: ' + TFile.ReadAllText('pfad-zur-datei.txt', TEncodingDetect.GetEncoding('pfad-zur-datei.txt')));

Der schöne Günther 19. Nov 2017 13:26

AW: Vorstellung Unit: File encoding detector
 
Hallo-

Wenn du statt (oder zumindest zusätzlich zu) String-Pfadangaben den Benutzer auch
Delphi-Quellcode:
TStream
reinstecken lässt, lassen sich viel besser Unit-Tests dafür schreiben :thumb:
Es wäre beispielsweise viel einfacher Daten aus einem ZIP-Archiv, einem Email-Anhang oder einem Netzwerk-Stream zu analysieren. So müsste ich ihn erst einmal auf der Platte speichern oder in einen zusätzlichen String speichern.

Als Kritik hätte ich sonst noch die Enumeration
Delphi-Quellcode:
TUnicodeType
- Mir wäre lieber ich bekäme eine frisch erstellte
Delphi-Quellcode:
TEncoding
-Instanz zurück. Wahrscheinlich Geschmackssache.

PS: Den Typ "NoBOM" zurückzubekommen wenn die angegeben Datei nicht existiert finde ich ehrlich gesagt nicht gut. Da gehört eine Exception geworfen.

LTE5 19. Nov 2017 13:28

AW: Vorstellung Unit: File encoding detector
 
Danke erst einmal.
TEncoding wäre mir auch lieber. Was TEncoding aber nicht kennt sind die UTF32-Varianten von Endian. Oder zählt UTF32 unter TEncoding.Unicode?

Was mich auch stört ist, dass ich bei nur einem Aufruf von IsFileUnicode 2x TBytesStream erzeuge, wenn es ganz durch geht.
Das könnte man mit einem Konstruktor und Destruktor-Konstrukt lösen. Aber dann wäre es kein Einzeiler mehr.

Was mir auch nicht gefällt ist die Art und Weise des Vergleichs auf das BOM. Besser bekomme ich es leider nicht hin.

Der schöne Günther 19. Nov 2017 13:39

AW: Vorstellung Unit: File encoding detector
 
Meinst du den Vergleich mit den hardkodierten Werten? Ich würde stattdessen
Delphi-Quellcode:
TEncoding.UTF8.GetPreamble()
nehmen?

Ich habe so etwas ähnliches in eine Nummer kleiner auch irgendwo herumliegen, aber nur auf der Arbeit. Da kann ich ab nächster Woche ja mal schauen zum Vergleichen...

Luckie 19. Nov 2017 13:39

AW: Vorstellung Unit: File encoding detector
 
Ich habe noch zwei interessante Links dazu:
https://blogs.msdn.microsoft.com/old...7-00/?p=27223/
https://blogs.msdn.microsoft.com/old...24-00/?p=40093

Der schöne Günther 19. Nov 2017 13:40

AW: Vorstellung Unit: File encoding detector
 
https://en.wikipedia.org/wiki/Bush_hid_the_facts

LTE5 19. Nov 2017 13:44

AW: Vorstellung Unit: File encoding detector
 
Zitat:

Zitat von Luckie (Beitrag 1386621)
Ich habe noch zwei interessante Links dazu:
https://blogs.msdn.microsoft.com/old...7-00/?p=27223/

Also im Prinzip habe ich mich Tage lang umsonst bemüht?

Zitat:

Meinst du den Vergleich mit den hardkodierten Werten? Ich würde stattdessen TEncoding.UTF8.GetPreamble() nehmen?
GetPreamble ist gut. Aber TEncoding kennt wie gesagt UTF32 nicht.
Wäre also eine Lösung für alles, bis auf UTF32. Ich füge es oben gleich mal an.

Uwe Raabe 19. Nov 2017 13:53

AW: Vorstellung Unit: File encoding detector
 
Zitat:

Findet sich ein Charakter > 127 (also außerhalb des ASCII-Bereichs), wird unterbrochen denn es ist vermutlich Unicode.
Erfahrungsgemäß ist das gerade im deutschsprachigen Umfeld eher selten der Fall: Ein Zeichen > #127 ist dort in der Regel ein Umlaut.

Nur so als Hinweis: Die Unit System.Character enthält ein paar Methoden für UTF-32 Zeichen und in System ist auch ein Typ UCS4String definiert, der allerdings nichts mit einem üblichen Delphi-String gemein hat.

LTE5 19. Nov 2017 14:03

AW: Vorstellung Unit: File encoding detector
 
Irgendwie habe ich den Eindruck meine Unit ist mehr als nutzlos in diesem Encoding-Labyrinth.
Aber mehr als "erraten" kann man ja eh nicht. Also versuche ich jedenfalls das.

Wenn jemand eine bessere Unit bauen kann, würde sich jemand dazu bereit erklären?


Zitat:

Findet sich ein Charakter > 127 (also außerhalb des ASCII-Bereichs), wird unterbrochen denn es ist vermutlich Unicode.
Was ich damit meine ist, wenn ein Zeichen > 127 vorkommt, ist es etwas anderes als ANSI.

# Ich habe die Unit in #1 nochmal angepasst.

# Ich habe die Unit in #1 noch einmal angepasst. Rückgabewert ist jetzt TEncoding.
Ich habe lange getestet. Wenn ich nicht gerade in den Kopfdaten einer Datei rumwühle und komische Werte eintrage, wird die Datei immer korrekt gelesen.

# Einen Fall habe ich doch gefunden. Wenn man eine utf-8-Datei ohne BOM prüft und kein Default-Encoding angibt, kommt natürlich ANSI zurück und é kann nicht dargestellt werden.
Deswegen gibt es nun eine überladene Version von TEncodingDetect.GetFileEncoding().

HolgerX 19. Nov 2017 15:47

AW: Vorstellung Unit: File encoding detector
 
Hmm..

Zitat:

Zitat von LTE5 (Beitrag 1386629)
Zitat:

Findet sich ein Charakter > 127 (also außerhalb des ASCII-Bereichs), wird unterbrochen denn es ist vermutlich Unicode.
Was ich damit meine ist, wenn ein Zeichen > 127 vorkommt, ist es etwas anderes als ANSI.

Nicht ganz:

ASCII entspricht 7 Bit = 0-127
ANSI entspricht 8 Bit = 0-255

https://de.wikipedia.org/wiki/ANSI-Zeichencode

Somit kann ein gültiges ANSI-Zeichen auch als Zahl 240 sein.. ;)

LTE5 19. Nov 2017 15:48

AW: Vorstellung Unit: File encoding detector
 
Wie genau müsste man denn dann nachprüfen?
Einfach bis 255 klingt ja zu einfach.

Uwe Raabe 19. Nov 2017 16:26

AW: Vorstellung Unit: File encoding detector
 
Die Problematik liegt eigentlich in der Unterscheidung zwischen ANSI und UTF-8 ohne BOM. Welche CodePage bei ANSI verwendet werden soll kannst du eh kaum raus finden, wenn du keine Informationen über die Art des Inhaltes hast (manche Zeichen kommen in einer bestimmten Art Text halt nicht vor und sind ein Trigger für eine falsche Codierung). Allerdings beginnen in UTF-8 alle Zeichen > #127 mit einer bestimmten Sequenz. Sind also Zeichen > #127 vorhanden, die nicht mit einer dieser UTF-8 Sequenzen beginnen, handelt es sich offenbar nicht um ein UTF-8 Encoding.

Ein sehr einfacher Ansatz um ANSI und UTF-8 zu unterscheiden wäre z.B. einfach erst mit TEncoding.UTF8 (BOM oder nicht erkennt er automatisch) einzulesen und falls das eine Exception wirft eben mit TEncoding.ANSI zu lesen. Bei dieser Vorgehensweise braucht man auch nicht erst das Encoding ermitteln, sondern bekommt das beim Lesen gleich mit. Das spart ein erneutes Durchlaufen zur eigentlichen Verarbeitung der Daten, denn wozu brauche ich das Encoding der Daten, wenn ich sie danach nicht damit lesen will. Das könnte dann in etwa so aussehen:
Delphi-Quellcode:
function StreamToString(Stream: TStream): string;
var
  enc: TEncoding;
  reader: TStreamReader;
  savePosition: Int64;
begin
  savePosition := Stream.Position;
  try
    { ANSI als letztes, denn das klappt immer } 
    for enc in TArray<TEncoding>.Create(TEncoding.UTF8, TEncoding.ANSI) do begin
      Stream.Position := savePosition;
      reader := TStreamReader.Create(Stream, enc, false);
      try
        try
          result := reader.ReadToEnd;
          { Wenn es geklappt hat, Schleife verlassen }
          Break;
        except
          on EEncodingError do ;
        end;
      finally
        reader.Free;
      end;
    end;
  finally
    Stream.Position := savePosition;
  end;
end;

Wosi 19. Nov 2017 16:27

AW: Vorstellung Unit: File encoding detector
 
Für den Fall, dass es keinen BOM gibt:
Gibt es nur Zeichen bis #127, dann ist es sicher den Stream als ASCII-String zu interpretieren.
Liegen einzelne Byte jedoch im Wertebereich zwischen #128 und #255 dann wird es komplizierter. Dann könnte es sich um UTF8 oder ANSI oder ein anderes lokales Format handeln.
Es gibt dabei leider kein 100% sicheres Vorgehen um das korrekte Encoding zu ermitteln. Es existieren lediglich Vorgehensweisen um ein möglichst gutes Ergebnis zu erzielen.

Ich musste mal ein Problem lösen, bei dem eine Software muss regelmäßig entscheiden musste, ob eine Datei UTF8 oder ANSI beinhaltet. So habe ich es damals gelöst:

- Ist ein BOM-Header vorhanden, dann nimm das passende Encoding für den BOM-Header
- Ansonsten untersuche den Bytestream auf gültige UTF8-Multi-Byte-Zeichen. Gibt es eine Byte-Sequenz, die nicht UTF8-Konform ist, dann nimm ANSI. Entspricht der Byte-Stream hingegen bis zum Ende gültigem UTF8, dann nimm UTF8.

Die Definition von Multi-Byte-Zeichen gibt es bei Wikipedia.
Das beschriebene Vorgehen funktioniert generell ganz gut. Allerdings scheitert es, wenn
- wenn sich mindestens ein ungültiges Multi-Byte-Zeichen in einer ansonsten gültigen UTF8-Datei befindet (von Text-Editoren werden diese Zeichen in der Regel als "�" dargestellt)
- wenn der Dateiinhalt weder ANSI noch UTF8 ist

LTE5 19. Nov 2017 16:40

AW: Vorstellung Unit: File encoding detector
 
Habe wieder viel zu lesen! Melde mich gleich.
Ich habe in der Zwischenzeit Support für Streams eingebaut. Schreibe ich gleich in Beitrag #1.

Zitat:

Das spart ein erneutes Durchlaufen zur eigentlichen Verarbeitung der Daten, denn wozu brauche ich das Encoding der Daten, wenn ich sie danach nicht damit lesen will.
Genau das will ich ja aber. Ich brauche das Encoding, eben damit ich die Daten lesen kann. Sonst würde ich mir die ganze Mühe nicht machen.

Zitat:

Allerdings beginnen in UTF-8 alle Zeichen > #127 mit einer bestimmten Sequenz. Sind also Zeichen > #127 vorhanden, die nicht mit einer dieser UTF-8 Sequenzen beginnen, handelt es sich offenbar nicht um ein UTF-8 Encoding.
Welche Sequenz ist das denn genau und wie prüfe ich danach?

Sollte man demnach hier unten also besser bis 255 prüfen und ab 127 zusätzlich diese Sequenz prüfen?
Delphi-Quellcode:
class function TEncodingDetect.IsStreamUnicode(const Stream: TStream): Boolean;
var
 i: Integer;
 B: Byte;
begin
 Result := False;

 if Stream.Size = 0 then
  Exit;

 for i := 0 to Stream.Size - 1 do
  begin
   Stream.ReadData(B, Sizeof(B));
   Result := Ord(B) > 127;
   if Result then
    Break;
  end;
end;
Zitat:

- Ansonsten untersuche den Bytestream auf gültige UTF8-Multi-Byte-Zeichen. Gibt es eine Byte-Sequenz, die nicht UTF8-Konform ist, dann nimm ANSI. Entspricht der Byte-Stream hingegen bis zum Ende gültigem UTF8, dann nimm UTF8.
Ich werde mich mal dran versuchen und TEncodingDetect.IsStreamUnicode anpassen. Könnte jedenfalls schwer werden, denn von dem Wikipedia-Artikel verstehe ich nichts.

Uwe Raabe 19. Nov 2017 16:56

AW: Vorstellung Unit: File encoding detector
 
Zitat:

Zitat von LTE5 (Beitrag 1386642)
Genau das will ich ja aber. Ich brauche das Encoding, eben damit ich die Daten lesen kann. Sonst würde ich mir die ganze Mühe nicht machen.

Die gezeigte Funktion liefert dir ja auch den String korrekt decodiert zurück. Den kannst du dann ja weiter verarbeiten ohne dich noch um das Encoding der Datei kümmern zu müssen.

Zitat:

Zitat von LTE5 (Beitrag 1386642)
Welche Sequenz ist das denn genau und wie prüfe ich danach?

Kannst du bei Wikipedia nachsehen: Zulässige Bytes und ihre Bedeutung

LTE5 19. Nov 2017 16:59

AW: Vorstellung Unit: File encoding detector
 
Zitat:

Die gezeigte Funktion liefert dir ja auch den String korrekt decodiert zurück.
Leider bringt mir der String aber nicht, wenn es um das Encoding geht, welches ich bei TMemIniFile brauche.

Zitat:

Kannst du bei Wikipedia nachsehen: Zulässige Bytes und ihre Bedeutung
Auf soviele verschiedene Bytes kann ich doch gar nicht prüfen.
Oder sind das insgesamt nur 6?


Ich habe mich mal so daran versucht. Ist das so richtig?
Delphi-Quellcode:
var i: Integer; B: Byte; Bytes: TBytes;
begin
 Stream.Position := 0;
 for i := 0 to Stream.Size - 1 do
  begin
   SetLength(Bytes, 2);
   Stream.Read(Bytes, Length(Bytes));

   if
    (Bytes = TBytes.Create($C0, $C1)) or
    (Bytes = TBytes.Create($F5, $F7)) or
    (Bytes = TBytes.Create($F8, $FB)) or
    (Bytes = TBytes.Create($FC, $FD)) or
    (Bytes = TBytes.Create($FE, $FF)) then
     ShowMessage('Ungültige Sequenz gefunden.');
    end;
  end;
end;

Uwe Raabe 19. Nov 2017 17:47

AW: Vorstellung Unit: File encoding detector
 
Zitat:

Zitat von LTE5 (Beitrag 1386645)
Auf soviele verschiedene Bytes kann ich doch gar nicht prüfen.
Oder sind das insgesamt nur 6?

Angenommen du liest jedes Byte nacheinander, dann sind alle Bytes im Bereich $00 - $7F gültige Zeichen. Ist das nicht der Fall, musst du prüfen, ob eine UTF-8 Sequenz folgt. Diese wird eingeleitet von einem Byte im Bereich $C2..$F4 - alles andere wäre ein Fehler. Die Länge der UTF-8 Sequenz wird durch dieses Byte bestimmt. Liegt es im Bereich $C2..$DF folgt ein weiteres Byte, liegt es im Bereich $E0..$EF folgen zwei weitere Bytes und liegt es im Bereich $F0..$F4 folgen drei weitere Bytes. Alle diese weiteren Bytes müssen im Bereich $80..$BF liegen. Nachdem du die entsprechende Menge weiterer Bytes gelesen hast, beginnt das Spiel wieder von vorn. Liegt ein Byte außerhalb des gerade erwarteten Bereichs liegt ein Fehler vor oder es handelt sich nicht um eine UTF-8 Codierung.

Eine Prüfroutine für UTF-8 könnte etwa so aussehen (ungetestet):
Delphi-Quellcode:
function IsUTF8(Bytes: TBytes): Boolean;
var
  B: Byte;
  weitere: 0..3;
begin
  weitere := 0;
  for B in Bytes do begin
    case B of
      $00..$7F: ; { ASCII }
      $80..$BF: begin
        if weitere > 0 then begin
          Dec(weitere);
        end
        else begin
          Exit(False);
        end;
      end;
      $C2..$DF: weitere := 1;
      $E0..$EF: weitere := 2;
      $F0..$F4: weitere := 3;
    else
      Exit(False);
    end;
  end;
  Result := True;
end;

LTE5 19. Nov 2017 17:54

AW: Vorstellung Unit: File encoding detector
 
Spätestens hier resigniere ich.

Ich muss mir das heute Abend mal in Ruhe angucken. Speziell dieses weitere mit inkrementieren und dekrementieren.

Ist es möglich von irgendeiner Quelle UTF-8-Dateien mit absichtlichen Fehlern zu bekommen?

himitsu 19. Nov 2017 17:58

AW: Vorstellung Unit: File encoding detector
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1386650)
Eine Prüfroutine für UTF-8 könnte etwa so aussehen (ungetestet)

Billigvariante: (testet nicht nur, sondern wandelt um und braucht zusätzlichen etwas RAM)
Delphi-Quellcode:
function IsUTF8(Bytes: RawByteString{oder TBytes}): Boolean;
begin
  Result := {(Bytes = '') and} (UTF8ToString(Bytes) <> ''); // inkl. dem Auskommentierten, wird auch ein Leerstring als UTF-8 erkannt, auch wenn "garnichts" im String ist.
end;
Der Code in der System-Unit wirft keine Exception, sondern gibt einfach nichts zurück (Leerstring), wenn es man kein valides UTF-8 rein gibt.

Wosi 19. Nov 2017 18:06

AW: Vorstellung Unit: File encoding detector
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1386650)
Eine Prüfroutine für UTF-8 könnte etwa so aussehen (ungetestet):

Vom Ansatz her gut aber du prüfst nicht, ob eine Multibyte-Sequenz vorzeitig abgebrochen wird.
Ebenfalls ungetesteter Fix:

Delphi-Quellcode:
function IsUTF8(Bytes: TBytes): Boolean;
var
  B: Byte;
  weitere: 0..3;
begin
  weitere := 0;
  for B in Bytes do begin
    case B of
      $00..$7F: if weitere > 0 then Exit(False); { ASCII }
      $80..$BF: begin
        if weitere > 0 then begin
          Dec(weitere);
        end
        else begin
          Exit(False);
        end;
      end;
      $C2..$DF: if weitere > 0 then Exit(False) else weitere := 1;
      $E0..$EF: if weitere > 0 then Exit(False) else weitere := 2;
      $F0..$F4: if weitere > 0 then Exit(False) else weitere := 3;
    else
      Exit(False);
    end;
  end;
  Result := True;
end;

LTE5 19. Nov 2017 18:25

AW: Vorstellung Unit: File encoding detector
 
Ich habe mir eben mal einen HexEditor besorgt.
Damit verstehe ich das alles vielleicht besser wenn ich dann noch alles mit Haltepunkten durchgehe oder anderweitig mir anzeigen lasse was gerade los ist.

Der Hex-Editor hat ein wenig, aber nicht komplett, Licht ins Dunkle gebracht. Interessant war nur zu sehen, dass mein HexEditor keine UTF-8 mit BOM-Dateien lesen konnte.
Muss vielleicht einen neuen suchen.

Darf ich euch meine neue Version der Unit MIT (!) Codefragmenten von euch zeigen?
Hinzugefügt habe ich Funktionen die Streams entgegennehmen können. Die haben mir intern auch bei so manchem Problem geholfen.

Was Himitus "Billigvariante" mit UTF8ToString angeht: das funktioniert bestimmt wie gewünscht. Da ich aber nur das boolsche Resultat benötige und nichts umwandeln muss, lasse ich die Version raus.

LTE5 19. Nov 2017 20:37

AW: Vorstellung Unit: File encoding detector
 
Alle Änderungen wurden übernommen.
Alle Funktionen nehmen nun auch Streams entgegen.

Es gibt einen kleinen Aufbaufehler, den ich notgedrungen mit der Variablen SkipBOMCheck lösen musste. Sonst würde sich eine Funktion immer wieder selber aufrufen.

Grund dafür, dass GetFileEncoding aber in IsStreamUnicode steckt ist, weil IsStreamUnicode am niedrigsten Punkt ist und von allen übergeordneten Funktionen angesprochen wird.

Uwe Raabe 19. Nov 2017 20:53

AW: Vorstellung Unit: File encoding detector
 
Zitat:

Zitat von Wosi (Beitrag 1386654)
Vom Ansatz her gut aber du prüfst nicht, ob eine Multibyte-Sequenz vorzeitig abgebrochen wird.

Gut erkannt :thumb:
Ist mir dann auch noch so in den Sinn gekommen. Ich würde das dann aber doch etwas kompakter schreiben:
Delphi-Quellcode:
function IsUTF8(Bytes: TBytes): Boolean;
var
  B: Byte;
  weitere: 0..3;
begin
  weitere := 0;
  for B in Bytes do begin
    if weitere > 0 then begin
      if not (B in [$80..$BF]) then Exit(False);
      Dec(weitere);
    end
    else begin
      case B of
        $00..$7F: ; { ASCII }
        $C2..$DF: weitere := 1;
        $E0..$EF: weitere := 2;
        $F0..$F4: weitere := 3;
      else
        Exit(False);
      end;
    end;
  end;
  Result := True;
end;

LTE5 20. Nov 2017 09:35

AW: Vorstellung Unit: File encoding detector
 
Zitat:

Es gibt einen kleinen Aufbaufehler, den ich notgedrungen mit der Variablen SkipBOMCheck lösen musste. Sonst würde sich eine Funktion immer wieder selber aufrufen.
Einen zweiten habe ich gerade auch noch gefunden.
Wenn IsStreamUnicode aufgerufen wird, wird als erstes GetFileEncoding aufgerufen. Findet GetFileEncoding kein BOM, wird wieder IsStreamUnicode aufgerufen. IsStreamUnicode läuft also im schlimmsten Fall zweimal durch.

Hat jemand eine Idee wie man diese beiden unschönen Fehler weg bekommt?

Der schöne Günther 20. Nov 2017 09:54

AW: Vorstellung Unit: File encoding detector
 
Ich hoffe dass kommt jetzt nicht als super-harte Kritik wie von Marcel Reich-Ranicki, aber ich fange an hieran zu zweifeln. Ich wollte ein paar Tests schreiben - Es scheitert schon wenn ich einen völlig offensichtlichen Unicode-String wie
Delphi-Quellcode:
&#9584;( &#865;° &#860;&#662; &#865;° )&#12388;&#9472;&#9472;&#9734;*:&#12539;&#65439;
reinstecke und bekomme für
Delphi-Quellcode:
IsTextUnicode
ein
Delphi-Quellcode:
False
zurück.

Ganz abgesehen davon dass der dort erstellte
Delphi-Quellcode:
TStringStream
nicht freigegeben wird.

LTE5 20. Nov 2017 09:55

AW: Vorstellung Unit: File encoding detector
 
Deswegen habe ich im ersten Beitrag im Feedback und Korrekturen gebeten.

Zitat:

Ich hoffe dass kommt jetzt nicht als super-harte Kritik
Doch, eigentlich schon.

Wie gesagt. Ich würde mich sehr freuen wenn ihr mir helft, dass es funktioniert. Mehr als das was im ersten Beitrag steht schaffe ich nicht.

sakura 20. Nov 2017 10:07

AW: Vorstellung Unit: File encoding detector
 
Die Funktion
Delphi-Quellcode:
IsTextUnicode
kann so nicht funktionieren, da die Steuerzeichen nicht vorhanden sind, auch im Stream davon nicht. Des Weiteren ist intern der Delphi-string immer Unicode (Der Standardtyp für Strings ist UnicodeString). ;-)

...:cat:...

LTE5 20. Nov 2017 10:08

AW: Vorstellung Unit: File encoding detector
 
Edit

ich habe die Funktion IsTextUnicode jetzt komplett entfernt. Ich brauchte sie eh nicht.
Dafür funktioniert bei mir der Rest wenigstens wie erwartet.

Feedback trotzdem gerne willkommen, denn schön ist die Unit meiner Meinung nach nicht.

LTE5 20. Nov 2017 20:45

AW: Vorstellung Unit: File encoding detector
 
Ich habe gerade eben Version 0.3 in den ersten Beitrag gepackt. Ich habe ein wenig aufgeräumt und umgebaut.
Eigentlich sollte nun einiges funktionieren.

Die BOM-Prüfung wird bisher nur von IsFileUnicode() genutzt.

Nachtrag: sollte etwas nicht funktionieren und das sogar sehr offensichtlich, und ich habe es nicht gesehen, dann bitte ich um ein paar Ohrfeigen.

Wosi 20. Nov 2017 21:53

AW: Vorstellung Unit: File encoding detector
 
Kleiner Verbesserungsvorschlag: Bei der Methode IsUtf8 sollte der Parameter besser mit const gekennzeichnet werden.

LTE5 20. Nov 2017 21:58

AW: Vorstellung Unit: File encoding detector
 
Ich musste deine Antwort zweimal lesen. Denn ich habe eigentlich noch mit Kritik gerechnet und dass irgendetwas, was absolut funktionieren muss, nicht funktioniert.

Aber wenn es bisher nur das ist :thumb:

Fukiszo 15. Jan 2018 09:16

AW: Vorstellung Unit: File encoding detector
 
Ich arbeite gerade an einem Tool namens "FileID".
Es identifiziert enorm viel Datei-Formate, über 3000 verschiedene binärer art.
Unter anderem auch Text dateien und deren "Encoding", was ich bei mir so realisiert hab:
ich les an offset 0 der datei das erste byte und bestimme dadurch mit was es codiert wurde.
Als referenz nahm ich mir Notepad++ und erstellte pro format ein paar dateien.
(des weiteren prüft mein tool ob irgendwelche nicht-lesbaren (binär) zeichen enthalten sind
um generell zu bestimmen ob's ne text-datei ist)
Ich hoff es hilft. (ist halt ne andere methode um ans ziel zu gelangen)

himitsu 15. Jan 2018 09:58

AW: Vorstellung Unit: File encoding detector
 
Zitat:

ich les an offset 0 der datei das erste byte und bestimme dadurch mit was es codiert wurde.
Falsch!

Bei UTF-8 ist das BOM genau 3 Byte lang.
Im Prinzip ist das mit dem BOM recht einfach zu verstehen, denn es ist zufällig das Unicodezeichen #$FEFF welches mit dem jeweiligen Encoding (Codepage) codiert wurde und was praktisch an erster Stelle des decodierten Unicode-Textes steht.

siehe $FFFE http://www.unicode.org/charts/PDF/UFFF0.pdf
https://de.wikipedia.org/wiki/Byte_Order_Mark
Seinen Namen hat das Byte-Order-Mark von den Codes $FFFE und $FEFF der UTF-16 / UCS2 in Big Endian und Little Endian.


Bei vielen "Binär"-Dateien ist das Magic-Byte, auch wenn es sich "Byte" nennt oft 2 bis 4 Byte lang.
z.B. "PE" bei Portable Execute, also den kompilierten EXE und DLL (und BPL, welche auch "nur" aufgemotzte DLL sind)



Und was sind "nicht-lesbare (binär) zeichen"?
Bei Chinesisch, Russisch, Swahili und Dergleichen, ist für "uns" Vieles nicht lesbar. :stupid:

Fukiszo 15. Jan 2018 10:27

AW: Vorstellung Unit: File encoding detector
 
nicht lesbar = code $00 - $21 (oder war's $23?) zum beispiel.
mit nicht lesbar mein ich man sollte nicht versuchen diese ascii codes darzustellen, sie enthalten keine "schriftzeichen", egal von wo.
und ich start meine identifizierung mit dem ersten byte, danach geht identifierung weiter mit zweitem dritten usw.
es gibt viele dateien deren signatur mit $FF beginnt.

ich hoff es hilft.

ps: ich gab ja keine werte zum vergleich an, ich meint halt nur das ich signaturen per byte abfrage kontrolliere,
und nicht per CLASS definitionen auslese.

Daniel 15. Jan 2018 10:30

AW: Vorstellung Unit: File encoding detector
 
Moin,

weitere Ideen sind ja grundsätzlich nichts schlechtes. Aber ich bin nicht sicher, ob Du dieses Thema gelesen hast. Es geht hier gerade auch um Dateien, die keine entsprechende Kennung aufweisen. Der von Dir vorgestellte Ansatz wurde auf Seite 2 diskutiert und verworfen.
Lass Dich nicht entmutigen, das kann passieren - aber wirf bitte vorher kurz einen Blick auf die Themen, zu denen Du etwas schreiben möchtest.


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