Bagaimana cara mengetahui apakah sebuah file biner (non-teks) dengan python?
Saya mencari melalui sekumpulan besar file dengan python, dan terus mendapatkan kecocokan dalam file biner. Ini membuat hasilnya terlihat sangat berantakan.
Saya tahu saya bisa menggunakan grep -I
, tetapi saya melakukan lebih banyak dengan data daripada yang diizinkan oleh grep.
Di masa lalu, saya hanya akan mencari karakter yang lebih besar dari 0x7f
, tetapi utf8
dan sejenisnya, membuatnya tidak mungkin pada sistem modern. Idealnya, solusi akan cepat, tetapi solusi apa pun akan berhasil.
grep
digunakan sendiri untuk mengidentifikasi file biner mirip dengan yang diposting oleh Jorge Orpinel di bawah ini . Kecuali Anda menyetel-z
opsinya, itu hanya akan memindai karakter null ("\000"
) dalam file. Dengan-z
, itu memindai"\200"
. Mereka yang tertarik dan / atau skeptis dapat memeriksa baris 1126 darigrep.c
. Maaf, saya tidak bisa temukan halaman web dengan kode sumbernya, tapi tentu saja Anda bisa mendapatkannya dari gnu.org atau melalui distro .git diff
dan GNUdiff
juga menggunakan strategi yang sama. Saya tidak yakin apakah itu sangat lazim karena jauh lebih cepat dan lebih mudah daripada alternatifnya, atau apakah itu hanya karena kelangkaan relatif dari file UTF-16 pada sistem yang cenderung menginstal utilitas ini.Jawaban:
Anda juga dapat menggunakan modul mimetypes :
Cukup mudah untuk menyusun daftar jenis mime biner. Misalnya Apache mendistribusikan dengan file mime.types yang dapat Anda parse menjadi sekumpulan daftar, biner dan teks dan kemudian periksa untuk melihat apakah mime ada dalam teks atau daftar biner Anda.
sumber
mimetypes
menggunakan konten file daripada hanya namanya?file
melaporkan sebagai "UTF-8 Unicode text, with very long lines" tetapi mimetypes.gest_type () akan mengembalikan (None, None). Juga, daftar mimetype Apache adalah daftar putih / subset. Ini sama sekali bukan daftar lengkap mimetypes. Ini tidak dapat digunakan untuk mengklasifikasikan semua file sebagai teks atau non-teks.Metode lain berdasarkan perilaku file (1) :
Contoh:
sumber
bytearray([7,8,9,10,12,13,27]) + bytearray(range(0x20, 0x7f)) + bytearray(range(0x80, 0x100))
sebagai gantinya. Lihat Python, file (1) - Mengapa angka [7,8,9,10,12,13,27] dan range (0x20, 0x100) digunakan untuk menentukan teks vs file biner dan github.com/file/file/ blob /…0x7f
(DEL
).11
atauVT
? Dalam tabel 11 dianggap teks ASCII biasa, dan ini adalahvertical tab
.Jika Anda menggunakan python3 dengan utf-8 itu lurus ke depan, cukup buka file dalam mode teks dan hentikan pemrosesan jika Anda mendapatkan file
UnicodeDecodeError
. Python3 akan menggunakan unicode saat menangani file dalam mode teks (dan bytearray dalam mode biner) - jika encoding Anda tidak dapat mendekode file arbitrer, kemungkinan besar Anda akan mendapatkannyaUnicodeDecodeError
.Contoh:
sumber
with open(filename, 'r', encoding='utf-8') as f
secara langsung?Jika membantu, banyak jenis biner yang dimulai dengan angka ajaib. Berikut adalah daftar file signature.
sumber
Coba ini:
sumber
git diff
sebenarnya bekerja dengan cara ini , dan tentu saja, ia mendeteksi file UTF-16 sebagai biner.diff
juga bekerja seperti ini. Ini memiliki masalah yang sama dengan file UTF-16.file
mendeteksi file yang sama dengan teks UTF-16 dengan benar. Saya belum memeriksagrep
kode, tetapi juga mendeteksi file UTF-16 sebagai biner.file(1)
tidak aman untuk dicetak tanpa konversi jadi metode ini sesuai untuk kasus ini.Berikut saran yang menggunakan perintah file Unix :
Contoh penggunaan:
Ini memiliki kelemahan karena tidak portabel ke Windows (kecuali Anda memiliki sesuatu seperti
file
perintah di sana), dan harus menelurkan proses eksternal untuk setiap file, yang mungkin tidak sesuai.sumber
file
sebagai "Konfigurasi beku Sendmail - versi m" —melihat ketiadaan string "teks". Mungkin digunakanfile -i
?Gunakan perpustakaan binaryornot ( GitHub ).
Ini sangat sederhana dan berdasarkan kode yang ditemukan dalam pertanyaan stackoverflow ini.
Anda sebenarnya dapat menulis ini dalam 2 baris kode, namun paket ini menyelamatkan Anda dari keharusan menulis dan menguji 2 baris kode tersebut secara menyeluruh dengan semua jenis file yang aneh, lintas platform.
sumber
Biasanya Anda harus menebak-nebak.
Anda dapat melihat ekstensi sebagai satu petunjuk, jika file memilikinya.
Anda juga dapat mengenali format biner, dan mengabaikannya.
Jika tidak, lihat proporsi byte ASCII yang tidak dapat dicetak yang Anda miliki dan coba tebak.
Anda juga dapat mencoba mendekode dari UTF-8 dan melihat apakah itu menghasilkan keluaran yang masuk akal.
sumber
Solusi yang lebih singkat, dengan peringatan UTF-16:
sumber
for line in file
dapat menggunakan jumlah memori yang tidak terbatas hinggab'\n'
ditemukan".read()"
mengembalikan bytestring di sini yang dapat diulang (menghasilkan byte individu).Kita dapat menggunakan python itu sendiri untuk memeriksa apakah suatu file biner, karena gagal jika kita mencoba membuka file biner dalam mode teks
sumber
Jika Anda tidak menggunakan Windows, Anda dapat menggunakan Python Magic untuk menentukan jenis file. Kemudian Anda dapat memeriksa apakah itu jenis teks / pantomim.
sumber
Berikut adalah fungsi yang pertama kali memeriksa apakah file dimulai dengan BOM dan jika tidak mencari byte nol dalam 8192 byte awal:
Secara teknis pemeriksaan UTF-8 BOM tidak diperlukan karena tidak boleh berisi nol byte untuk semua tujuan praktis. Tetapi karena ini adalah pengkodean yang sangat umum, lebih cepat untuk memeriksa BOM di awal daripada memindai semua 8192 byte untuk 0.
sumber
Coba gunakan python-magic yang saat ini dipelihara yang bukan modul yang sama dalam jawaban @Kami Kisiel. Ini mendukung semua platform termasuk Windows namun Anda akan membutuhkan
libmagic
file biner. Ini dijelaskan di README.Tidak seperti modul mimetypes , modul ini tidak menggunakan ekstensi file dan sebagai gantinya memeriksa konten file.
sumber
Saya datang ke sini mencari hal yang persis sama - solusi komprehensif yang disediakan oleh perpustakaan standar untuk mendeteksi biner atau teks. Setelah meninjau opsi yang disarankan orang, perintah file nix tampaknya menjadi pilihan terbaik (Saya hanya mengembangkan untuk linux boxen). Beberapa orang lain memposting solusi menggunakan file tetapi mereka tidak perlu rumit menurut saya, jadi inilah yang saya dapatkan:
Tidak perlu dikatakan lagi, tetapi kode Anda yang memanggil fungsi ini harus memastikan Anda dapat membaca file sebelum mengujinya, jika tidak, ini akan salah mendeteksi file sebagai biner.
sumber
Saya rasa solusi terbaik adalah dengan menggunakan fungsi guess_type. Ini memegang daftar dengan beberapa mimetypes dan Anda juga dapat memasukkan tipe Anda sendiri. Inilah skrip yang saya lakukan untuk menyelesaikan masalah saya:
Itu ada di dalam Kelas, seperti yang Anda lihat berdasarkan struktur kode. Tapi Anda bisa cukup banyak mengubah hal-hal yang ingin Anda terapkan di dalam aplikasi Anda. Ini cukup mudah digunakan. Metode getTextFiles mengembalikan objek daftar dengan semua file teks yang berada di direktori yang Anda berikan di variabel jalur.
sumber
di * NIX:
Jika Anda memiliki akses ke perintah
file
shell, shlex dapat membantu membuat modul subproses lebih berguna:Atau, Anda juga bisa memasukkannya ke dalam for-loop untuk mendapatkan output untuk semua file di direktori saat ini menggunakan:
atau untuk semua subdir:
sumber
Sebagian besar program menganggap file tersebut biner (yaitu file apa pun yang tidak "berorientasi baris") jika berisi karakter NULL .
Berikut adalah versi perl dari
pp_fttext()
(pp_sys.c
) yang diimplementasikan dengan Python:Sumber: Perl's "guess if file is text or binary" diimplementasikan dengan Python
sumber
apakah kamu di unix? jika demikian, coba:
Nilai kembali shell dibalik (0 tidak apa-apa, jadi jika menemukan "teks" maka itu akan mengembalikan 0, dan dalam Python itu adalah ekspresi False).
sumber
file
dengan-b
sakelar; itu hanya akan mencetak jenis file tanpa jalur.is_binary_file = lambda filename: "text" in subprocess.check_output(["file", "-b", filename])
Cara yang lebih sederhana adalah dengan memeriksa apakah file tersebut berisi karakter NULL (
\x00
) dengan menggunakanin
operator, misalnya:Lihat di bawah contoh lengkapnya:
Penggunaan sampel:
sumber
Dokumentasi
sumber