Wie kann ich feststellen, ob eine Datei in Python binär (kein Text) ist?
Ich suche eine große Anzahl von Dateien in Python und erhalte immer wieder Übereinstimmungen in Binärdateien. Dadurch sieht die Ausgabe unglaublich chaotisch aus.
Ich weiß, dass ich verwenden könnte grep -I
, aber ich mache mehr mit den Daten, als grep zulässt.
In der Vergangenheit hätte ich nur nach Zeichen gesucht, die größer sind als 0x7f
, aber utf8
und dergleichen, was dies auf modernen Systemen unmöglich macht. Im Idealfall wäre die Lösung schnell, aber jede Lösung reicht aus.
grep
mit der Binärdateien identifiziert werden, ähnelt der von Jorge Orpinel unten . Sofern Sie die-z
Option nicht festlegen , wird nur nach einem Nullzeichen ("\000"
) in der Datei gesucht. Mit-z
sucht es nach"\200"
. Interessierte und / oder Skeptiker können Zeile 1126 von überprüfengrep.c
. Entschuldigung, ich konnte keine Webseite mit dem Quellcode finden, aber Sie können sie natürlich von gnu.org oder über eine Distribution erhalten .git diff
GNU alsdiff
auch GNU dieselbe Strategie. Ich bin mir nicht sicher, ob es so weit verbreitet ist, weil es so viel schneller und einfacher als die Alternative ist, oder ob es nur an der relativen Seltenheit von UTF-16-Dateien auf Systemen liegt, auf denen diese Utils installiert sind.Antworten:
Sie können auch das Mimetypes- Modul verwenden:
Es ist ziemlich einfach, eine Liste von binären MIME-Typen zu erstellen. Zum Beispiel verteilt Apache mit einer mime.types-Datei, die Sie in eine Reihe von Listen, Binärdateien und Text, analysieren und dann überprüfen können, ob sich die MIME in Ihrem Text oder Ihrer Binärliste befindet.
quelle
mimetypes
den Inhalt einer Datei anstelle ihres Namens zu verwenden?file
als "UTF-8-Unicode-Text mit sehr langen Zeilen" gemeldet wird, aber mimetypes.gest_type () gibt zurück (None, None). Außerdem ist Apaches Mimetyp-Liste eine Whitelist / Teilmenge. Es ist keineswegs eine vollständige Liste der Mimetypen. Es kann nicht verwendet werden, um alle Dateien als Text oder Nicht-Text zu klassifizieren.Noch eine andere Methode, die auf dem Verhalten von Datei (1) basiert :
Beispiel:
quelle
bytearray([7,8,9,10,12,13,27]) + bytearray(range(0x20, 0x7f)) + bytearray(range(0x80, 0x100))
stattdessen verwenden. Siehe Python, Datei (1) - Warum werden die Zahlen [7,8,9,10,12,13,27] und der Bereich (0x20, 0x100) zur Bestimmung von Text gegenüber Binärdatei und github.com/file/file/0x7f
(DEL
) aktualisiert .11
oderVT
? In der Tabelle wird 11 als einfacher ASCII-Text betrachtet, und dies ist dervertical tab
.Wenn Sie Python3 mit utf-8 verwenden, ist dies unkompliziert. Öffnen Sie die Datei einfach im Textmodus und beenden Sie die Verarbeitung, wenn Sie eine erhalten
UnicodeDecodeError
. Python3 verwendet Unicode, wenn Dateien im Textmodus verarbeitet werden (und Bytearray im Binärmodus). Wenn Ihre Codierung keine beliebigen Dateien dekodieren kann, ist es sehr wahrscheinlich, dass Sie diese erhaltenUnicodeDecodeError
.Beispiel:
quelle
with open(filename, 'r', encoding='utf-8') as f
direkt verwenden?Wenn es hilft, beginnen viele, viele Binärtypen mit magischen Zahlen. Hier ist eine Liste der Dateisignaturen.
quelle
Versuche dies:
quelle
git diff
tatsächlich so und es erkennt UTF-16-Dateien als binär.diff
funktioniert auch so. Es gibt ähnliche Probleme mit UTF-16-Dateien.file
erkennt die gleichen Dateien wie UTF-16-Text korrekt. Ich habe dengrep
Code nicht ausgecheckt , aber er erkennt auch UTF-16-Dateien als binär.file(1)
die ohne Konvertierung nicht sicher gedruckt werden können. Daher ist diese Methode in diesem Fall geeignet.Hier ist ein Vorschlag, der den Befehl Unix- Datei verwendet :
Anwendungsbeispiel:
Es hat den Nachteil, dass es nicht auf Windows portierbar ist (es sei denn, Sie haben dort so etwas wie den
file
Befehl) und für jede Datei einen externen Prozess erzeugen muss, der möglicherweise nicht schmackhaft ist.quelle
file
als "Sendmail Frozen Configuration - Version M" beschrieben werden - und das Fehlen der Zeichenfolge "Text"file -i
Verwenden Sie die binaryornot- Bibliothek ( GitHub ).
Es ist sehr einfach und basiert auf dem Code in dieser Stackoverflow-Frage.
Sie können dies tatsächlich in 2 Codezeilen schreiben. Dieses Paket erspart Ihnen jedoch das Schreiben und gründliche Testen dieser 2 Codezeilen mit allen möglichen seltsamen Dateitypen, plattformübergreifend.
quelle
Normalerweise muss man raten.
Sie können die Erweiterungen als einen Hinweis betrachten, wenn die Dateien sie haben.
Sie können auch bekannte Binärformate erkennen und diese ignorieren.
Ansonsten sehen Sie, welchen Anteil nicht druckbarer ASCII-Bytes Sie haben, und raten Sie davon.
Sie können auch versuchen, UTF-8 zu dekodieren und festzustellen, ob dies zu einer sinnvollen Ausgabe führt.
quelle
Eine kürzere Lösung mit einer UTF-16-Warnung:
quelle
for line in file
Kann unbegrenzt viel Speicher verbrauchen, bisb'\n'
gefunden wird".read()"
Bytestring hier , dass die Renditen ist iterable (es ergibt einzelnen Bytes).Wir können Python selbst verwenden, um zu überprüfen, ob eine Datei binär ist, da dies fehlschlägt, wenn wir versuchen, eine Binärdatei im Textmodus zu öffnen
quelle
Wenn Sie nicht unter Windows arbeiten, können Sie den Dateityp mit Python Magic bestimmen. Dann können Sie überprüfen, ob es sich um einen Text- / MIME-Typ handelt.
quelle
Hier ist eine Funktion, die zuerst prüft, ob die Datei mit einer Stückliste beginnt und wenn nicht, nach einem Null-Byte innerhalb der anfänglichen 8192 Bytes sucht:
Technisch gesehen ist die Prüfung der UTF-8-Stückliste nicht erforderlich, da sie für alle praktischen Zwecke keine Null-Bytes enthalten sollte. Da es sich jedoch um eine sehr häufige Codierung handelt, ist es am Anfang schneller, nach der Stückliste zu suchen, als alle 8192 Bytes nach 0 zu durchsuchen.
quelle
Versuchen Sie es mit der aktuell gepflegten Python-Magie, die nicht das gleiche Modul in @Kami Kisiels Antwort ist. Dies unterstützt alle Plattformen einschließlich Windows, Sie benötigen jedoch die
libmagic
Binärdateien. Dies wird in der README erklärt.Im Gegensatz zum Mimetypes- Modul wird die Dateierweiterung nicht verwendet und stattdessen der Inhalt der Datei überprüft.
quelle
Ich bin hierher gekommen, um genau das Gleiche zu suchen - eine umfassende Lösung, die von der Standardbibliothek zur Erkennung von Binärdateien oder Text bereitgestellt wird. Nachdem Sie die vorgeschlagenen Optionen überprüft haben, scheint der Befehl nix file die beste Wahl zu sein (ich entwickle nur für Linux Boxen). Einige andere haben Lösungen mithilfe von Dateien veröffentlicht, aber meiner Meinung nach sind sie unnötig kompliziert. Deshalb habe ich mir Folgendes ausgedacht:
Es sollte selbstverständlich sein, aber Ihr Code, der diese Funktion aufruft, sollte sicherstellen, dass Sie eine Datei lesen können, bevor Sie sie testen. Andernfalls wird die Datei fälschlicherweise als binär erkannt.
quelle
Ich denke, dass die beste Lösung darin besteht, die Funktion rate_type zu verwenden. Es enthält eine Liste mit mehreren Mimetypen, und Sie können auch Ihre eigenen Typen angeben. Hier kommt das Skript, das ich gemacht habe, um mein Problem zu lösen:
Es befindet sich innerhalb einer Klasse, wie Sie anhand der Struktur des Codes sehen können. Sie können jedoch die Dinge, die Sie in Ihrer Anwendung implementieren möchten, so ziemlich ändern. Es ist ganz einfach zu bedienen. Die Methode getTextFiles gibt ein Listenobjekt mit allen Textdateien zurück, die sich in dem Verzeichnis befinden, das Sie in der Pfadvariablen übergeben.
quelle
auf * NIX:
Wenn Sie Zugriff auf den
file
Shell-Befehl haben, kann shlex dazu beitragen, das Unterprozessmodul benutzerfreundlicher zu machen:Sie können dies auch in eine for-Schleife einfügen, um die Ausgabe für alle Dateien im aktuellen Verzeichnis zu erhalten, indem Sie Folgendes verwenden:
oder für alle Unterverzeichnisse:
quelle
Die meisten Programme betrachten die Datei als binär (dh jede Datei, die nicht "zeilenorientiert" ist), wenn sie ein NULL-Zeichen enthält .
Hier ist Perls Version von
pp_fttext()
(pp_sys.c
), die in Python implementiert ist:Quelle: Perls in Python implementierte "Vermutung, ob die Datei Text oder Binär ist"
quelle
bist du in unix Wenn ja, dann versuchen Sie:
Die Shell-Rückgabewerte werden invertiert (0 ist in Ordnung. Wenn also "Text" gefunden wird, wird eine 0 zurückgegeben, und in Python ist dies ein falscher Ausdruck).
quelle
file
mit dem-b
Schalter; Es wird nur der Dateityp ohne Pfad gedruckt.is_binary_file = lambda filename: "text" in subprocess.check_output(["file", "-b", filename])
Einfacher ist es,
\x00
mithilfe desin
Operators zu überprüfen, ob die Datei aus NULL-Zeichen ( ) besteht , zum Beispiel:Siehe unten das vollständige Beispiel:
Beispielnutzung:
quelle
Dokumentation
quelle