Delphi-PRAXiS
Seite 3 von 5     123 45      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi Datei auf Indikatoren für Binärdatei testen? (https://www.delphipraxis.net/185028-datei-auf-indikatoren-fuer-binaerdatei-testen.html)

PeterPanino 9. Mai 2015 22:18

AW: Datei auf Indikatoren für Binärdatei testen?
 
Zitat:

Zitat von himitsu (Beitrag 1300881)
* man kann nur prüfen "ist das keine Datei eines/mehrerer bestimmter Textformate" (vermutlich ungültige Zeichen/Kodierungen enthalten)
* 100%ig sicher kann aber niemals etwas werden

GENAU. Deshalb habe ich meine Funktion auch so angelegt, dass auf Indikatoren für Binärdateien geprüft wird (und nicht auf Indikatoren für Textdateien). Und das Verfahren an sich kann immer nur eine ANNÄHERUNG sein. Außerhalb dieser Funktion wird in meinem Programm natürlich noch anderes wie etwa Datei-Endungen usw. geprüft.

redox 9. Mai 2015 22:38

AW: Datei auf Indikatoren für Binärdatei testen?
 
IMHO sollten mit #19 von himitsu und #20 von PeterPanino alle abklärungsbedürftigen Ansätze abgehandelt sein.

Für mich z.B. ist es nur *wahrscheinlich* ermittelbar, ob eine Datei "menschenlesbaren Text" enthält, nicht *absolut*.

"Menschenlesbarer Text" enthält immer ein Leerzeichen zwischen den Wörtern (in den mir bekannten Sprachen).

Just my two cents :oops:

PeterPanino 9. Mai 2015 23:02

AW: Datei auf Indikatoren für Binärdatei testen?
 
Übrigens: Ich benötige die Funktion dafür, um zu entscheiden, ob der Inhalt einer Datei in eine PDF-Datei als Text ausgegeben werden kann oder nicht. Deshalb ist für diesen Zweck allein maßgeblich, dass die Datei KEINE BINÄRDATEI ist.

p80286 9. Mai 2015 23:28

AW: Datei auf Indikatoren für Binärdatei testen?
 
Zitat:

Zitat von PeterPanino (Beitrag 1300883)
wird in meinem Programm natürlich noch anderes wie etwa Datei-Endungen usw. geprüft.

Nunja Datei-Endungen...
erfolgsversprechender sind da schon eher die "Magic Bytes".
Ich vermute, daß ein hoher Anteil an "e" und x0D0A auf eine Textdatei verweist, gegen eine Textdatei würden Push/Pop-Sequenzen mehrere NOPs und #00 sprechen.
Eine weitere Möglichkeit wäre es, Buchstabenkombinationen, die sprachspezifisch sind auf ihr Vorkommen zu prüfen.

Gruß
K-h

PeterPanino 10. Mai 2015 00:16

AW: Datei auf Indikatoren für Binärdatei testen?
 
Zitat:

Zitat von p80286 (Beitrag 1300896)
Ich vermute, daß ein hoher Anteil an "e" und x0D0A auf eine Textdatei verweist, gegen eine Textdatei würden Push/Pop-Sequenzen mehrere NOPs und #00 sprechen. Eine weitere Möglichkeit wäre es, Buchstabenkombinationen, die sprachspezifisch sind auf ihr Vorkommen zu prüfen.

Danke für deine Antwort.

Wie gesagt, ich möchte nur prüfen, ob es keine Binärdatei ist.

Könntest du mir bitte erklären, was du mit "Push/Pop-Sequenzen mehrere NOPs" meinst?

#00 Habe ich ja schon ausgeschlossen (immer mit dem Kriterium der annähernden Wahrscheinlichkeit).

redox 10. Mai 2015 00:54

AW: Datei auf Indikatoren für Binärdatei testen?
 
Zitat:

Zitat von PeterPanino (Beitrag 1300890)
Übrigens: Ich benötige die Funktion dafür, um zu entscheiden, ob der Inhalt einer Datei in eine PDF-Datei als Text ausgegeben werden kann oder nicht. Deshalb ist für diesen Zweck allein maßgeblich, dass die Datei KEINE BINÄRDATEI ist.

Denn sie wissen nicht, was sie tun :twisted:

Luckie 10. Mai 2015 01:23

AW: Datei auf Indikatoren für Binärdatei testen?
 
Ich kacke mal Korinthen. :stupid: Jede Datei ist eine Binärdatei, da sie letztendlich alle auf dem Datenträger nur aus Nullen und Einsen besteht. Letztendlich kommt es auf die Interpretation der Anwendung drauf an, wie die Nullen und Einsen dargestellt werden.

Zitat:

Ich benötige die Funktion dafür, um zu entscheiden, ob der Inhalt einer Datei in eine PDF-Datei als Text ausgegeben werden kann oder nicht.
Öhm, PDF ist PDF. :roll:

Perlsau 10. Mai 2015 01:25

AW: Datei auf Indikatoren für Binärdatei testen?
 
Zitat:

Zitat von PeterPanino (Beitrag 1300890)
Übrigens: Ich benötige die Funktion dafür, um zu entscheiden, ob der Inhalt einer Datei in eine PDF-Datei als Text ausgegeben werden kann oder nicht. Deshalb ist für diesen Zweck allein maßgeblich, dass die Datei KEINE BINÄRDATEI ist.

Ahh ... jetzt verstehe ich erst, welchem Zweck das Ganze dienen soll. Du kannst aber dennoch nicht jede Textdatei einfach so "in eine PDF-Datei als Text ausgeben", z.B. Word- und RTF-Dateien mit ihren mannigfaltigen Steuerzeichen oder Vektor-Dateien von Zeichenprogrammen wie CorelDraw, PostScript-Dateien usw. Das wäre für einen reinen Anwender auch nicht wirklich lesbar. Interessant hier ist der Artikel bei Wikipedia über Austauschformate, aber auch:

Austauschformat bei IT Wissen
Warum PDF kein Austauschformat ist

Der Hinweis, auf das Vorkommen von e oder E zu prüfen, da dieser Buchstabe in der deutschen Sprache überdurchschnittlich häufig vorkommt, hilft bei anderen Sprachen nicht unbedingt weiter, siehe dazu auch die Google-Ergebnisse zum Begriff. Am besten scheint mir der Hinweis auf regelmäßig vorkommende Leerzeichen dazu geeignet, eine Datei automatisiert als Text zu identifizieren. Allerdings sind CSV-Dateien (Comma Separated Values) auch Textdateien, die möglicherweise kaum Chr(32) bzw. $20 enthalten. Da es eine absolute Gewißheit, ob Textdatei oder nicht, wie hier bereits mehrfach betont, auf automatisierte Weise nicht geben kann, halte ich es nicht wirklich für abwegig, auf die Frage des Klosterschülers nach einer Prüfmethode für eine Internetverbindung hinzuweisen, die zum selben Ergebnis führt.

Wenn es nur um die deutsche Sprache geht, hilft vielleicht die Liste der häufigsten Wörter der deutschen Sprache, ebenfalls bei Wikipedia.

Was zur Lösung des Problems noch weiterhelfen würde, ist die bereits mehrfach gestellte, aber bislang unbeantwortete Frage, wie du eine Textdatei definierst: PostScript ist auch Text, Unit-Dateien enthalten lesbaren Text usw.

Wieso antwortest du nicht auf meine Fragen: "Was meinst du damit, ich würde einiges, insbesondere die Perspektive, mißverstehen? Welche Perspektive meinst du? Könntest du vielleicht etwas genauer bezeichnen, was ich deiner Ansicht nach mißverstehe? Wie sonst sollte ich mein Mißverständnis nachvollziehen und auflösen können?"

PeterPanino 10. Mai 2015 09:01

AW: Datei auf Indikatoren für Binärdatei testen?
 
Nochmals vielen Dank für all die sicherlich gut gemeinten Ratschläge zur Erkennbarkeit von Textdateien, aber trotzdem möchte ich nochmal auf den Titel dieses Themas und somit auf die Ausgangsfrage hinweisen: "Datei auf Indikatoren für Binärdatei testen?". Die Frage war also nicht "Datei auf Indikatoren für Textdatei testen?". Das Eine ist nicht das Gegenteil vom Anderen, wegen der prinzipiellen Restunsicherheit sowohl bei Ein- als auch Ausschlusskriterien. Wie bereits dargelegt, habe ich mich auf meinen Zweck bezogen für die AUSschließung von Binärdateien entschieden. Ich halte diese Methodik für nicht kompatibel mit der EINschließung von Textdateien. Empirisch gesehen scheint die Ausschlussmethode bessere Ergebnisse zu produzieren.

PeterPanino 10. Mai 2015 13:09

AW: Datei auf Indikatoren für Binärdatei testen?
 
Ich habe jetzt den Hinweis von @mjustin (Posting #8) berücksichtigt, dass UTF-32-enkodierte Dateien auch Doppel-NullBytes enthalten können und deshalb eine Prüfung auf UTF-32 BOM eingefügt (BE und LE), wenn ein Doppel-NullByte angetroffen wird, da ich optimistischerweise davon ausgehe, dass UTF-32-enkodierte Dateien einen BOM enthalten. Damit wird die Rest-Unsicherheit für den Ausschluss von Binärdateien verkleinert. Eine weitere Verkleinerung dieser Rest-Unsicherheit bei einem Doppel-NullByte-Vorkommen in einer Datei ohne UTF-32 BOM könnte man nur durch eine aufwendige statistische oder linguistische Analyse der in der Datei enthaltenen Bytes erreichen.

Delphi-Quellcode:
function IsTextFile(const AFile: string; const ABytesCount: Integer = 1000): Boolean;
// testet, ob die ersten ABytesCount Bytes einer Datei Indikatoren für eine Binär-Datei enthalten:
// wenn nicht, muss es wohl eine Textdatei sein?
// Siehe auch: http://qc.embarcadero.com/wc/qcmain.aspx?d=84071
const
  MaxAllowedForbiddenControlCharsCount = 1;
  BOM_UTF32_LSB: array [0..3] of Byte = ($FF,$FE,$00,$00);
  BOM_UTF32_MSB: array [0..3] of Byte = ($00,$00,$FE,$FF);
var
  Reader: TStreamReader;
  Ch: AnsiChar;
  c: Integer;
  PreviousCharWasNullByte: Boolean;
  ForbiddenControlCharsCount: Integer;

  function HasUTF32BOM(S: TStream): Boolean;
  var
    SavedPos: Int64;
    Buf: TBytes;
  begin
    SetLength(Buf, 4);
    SavedPos := S.Position;
    Result := False;
    try
      S.Seek(0, soBeginning);
      if S.Read(Buf, 4) = 4 then
      begin
        Result := ((Buf[0] = BOM_UTF32_LSB[0])
               and (Buf[1] = BOM_UTF32_LSB[1])
               and (Buf[2] = BOM_UTF32_LSB[2])
               and (Buf[3] = BOM_UTF32_LSB[3]))
               or
                  ((Buf[0] = BOM_UTF32_MSB[0])
               and (Buf[1] = BOM_UTF32_MSB[1])
               and (Buf[2] = BOM_UTF32_MSB[2])
               and (Buf[3] = BOM_UTF32_MSB[3]));
      end;
      CodeSite.Send('HasUTF32BOM', Result);
    finally
      S.Position := SavedPos;
    end;
  end;
begin
  Result := True;
  c := 0;
  PreviousCharWasNullByte := False;
  ForbiddenControlCharsCount := 0;

  Reader := TStreamReader.Create(TFileStream.Create(AFile, fmOpenRead), TEncoding.ANSI);
  try
    if Reader.EndOfStream then
    begin
      CodeSite.Send('Nothing to read');
      Result := False;
      EXIT;
    end;

    while Reader.Peek() >= 0 do
    begin
      Ch := AnsiChar(Reader.Read());

      if Ch = #0 then
      begin
        if PreviousCharWasNullByte then
        begin
          CodeSite.Send('Double Null Byte found');
          Result := HasUTF32BOM(Reader.BaseStream); // False;
          EXIT;
        end;
        PreviousCharWasNullByte := True;
      end
      else
      begin
        PreviousCharWasNullByte := False;

        if Ch in [#1..#8, #14..#31] then
        begin
          Inc(ForbiddenControlCharsCount);
          CodeSite.Send('This forbidden control char', HexDisplayPrefix + IntToHex(Ord(Ch), 2));
        end;
        if ForbiddenControlCharsCount > MaxAllowedForbiddenControlCharsCount then
        begin
          CodeSite.Send('More than ' + IntToStr(MaxAllowedForbiddenControlCharsCount) + ' forbidden control chars found');
          Result := False;
          EXIT;
        end;
      end;

      // Todo: andere Indikatoren?

      Inc(c);
      if c > ABytesCount then EXIT;
    end;
  finally
    CodeSite.Send('Bytes read', c);
    Reader.Close();
    Reader.BaseStream.Free;
    Reader.Free();
  end;
end;

procedure TForm1.btnTestClick(Sender: TObject);
var
  d: Int64;
begin
  d := GetTickCount;
  CodeSite.Send('Is Text File?', IsTextFile(edt1.Text));
  CodeSite.Send('Duration', GetTickCount - d);
end;
So bleibt als nächster Schritt nur noch die zusätzliche Prüfung auf UTF-16 BOM beim Antreffen der Mindestzahl von verbotenen ControlBytes.


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:18 Uhr.
Seite 3 von 5     123 45      

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