Làm thế nào để tự động phát hiện mã hóa tập tin văn bản?


69

Có nhiều tệp văn bản đơn giản được mã hóa trong các bảng mã biến thể.

Tôi muốn chuyển đổi tất cả chúng thành UTF-8, nhưng trước khi chạy iconv, tôi cần biết mã hóa ban đầu của nó. Hầu hết các trình duyệt đều có Auto Detecttùy chọn mã hóa, tuy nhiên, tôi không thể kiểm tra từng tệp văn bản đó vì có quá nhiều.

Chỉ khi biết mã hóa ban đầu, sau đó tôi có thể chuyển đổi các văn bản bằng cách iconv -f DETECTED_CHARSET -t utf-8.

Có tiện ích nào để phát hiện mã hóa các tệp văn bản thuần túy không? Nó không phải hoàn hảo 100%, tôi không phiền nếu có 100 tệp bị chuyển nhầm thành 1.000.000 tệp.

Câu trả lời:


57

Hãy thử mô-đun chardet Python, có sẵn trên PyPi:

pip install chardet

Sau đó chạy chardetect myfile.txt.

Chardet dựa trên mã phát hiện được sử dụng bởi Mozilla, do đó, nó sẽ cho kết quả hợp lý, miễn là văn bản đầu vào đủ dài để phân tích thống kê. Đừng đọc tài liệu dự án .

Như đã đề cập trong các bình luận, nó khá chậm, nhưng một số bản phân phối cũng gửi phiên bản C ++ gốc như @Xavier đã tìm thấy trong https://superuser.com/a/609056 . Ngoài ra còn có một phiên bản Java ở đâu đó.


3
Vâng, và nó đã được đóng gói như python-chardettrong repo vũ trụ Ubuntu.
Xiè Jìléi

Nếu đó không phải là một phỏng đoán hoàn hảo, chardetvẫn sẽ đưa ra dự đoán chính xác nhất, như thế nào ./a.txt: GB2312 (confidence: 0.99). So với Enca vừa thất bại và báo cáo 'Mã hóa không được công nhận'. Tuy nhiên, thật đáng buồn, chardetchạy rất chậm.
Xiè Jìléi

1
@ 谢 继: Có nó chạy qua đêm hoặc một cái gì đó tương tự. Phát hiện bộ ký tự một quá trình phức tạp . Bạn cũng có thể dùng thử jChardet dựa trên Java hoặc ... bộ đệm ban đầu là một phần của Mozilla , nhưng chỉ có nguồn C ++, không có công cụ dòng lệnh.
grawity

2
Về tốc độ: chạy chardet <(head -c4000 filename.txt)nhanh hơn nhiều và thành công không kém cho trường hợp sử dụng của tôi. (trong trường hợp không rõ cú pháp bash này sẽ chỉ gửi 4000 byte đầu tiên tới bộ đệm)
ndemou

@ndemou Tôi có chardet==3.0.4, và tên thực thi của công cụ dòng lệnh thì chardetectkhông chardet.
Devy

32

Tôi sẽ sử dụng lệnh đơn giản này:

encoding=$(file -bi myfile.txt)

Hoặc nếu bạn chỉ muốn bộ ký tự thực tế (như utf-8):

encoding=$(file -b --mime-encoding myfile.txt)

4
Thật không may, filechỉ phát hiện các bảng mã với các thuộc tính cụ thể, chẳng hạn như UTF-8 hoặc UTF-16. Phần còn lại - ISO8859 cũ hoặc các phóng viên MS-DOS và Windows của họ - được liệt kê là "không xác định 8 bit" hoặc một cái gì đó tương tự, ngay cả đối với các tệp chardetphát hiện với độ tin cậy 99%.
grawity

6
tập tin cho tôi thấy iso-8859-1
cweiske

Nếu phần mở rộng đang nói dối thì sao?
james.garriss

2
@ james.garriss: phần mở rộng tập tin không liên quan gì đến mã hóa nội dung (văn bản) của nó.
MestreLion

29

Trên Linux dựa trên Debian, gói uchardet ( Debian / Ubuntu ) cung cấp một công cụ dòng lệnh. Xem bên dưới mô tả gói:

 universal charset detection library - cli utility
 .
 uchardet is a C language binding of the original C++ implementation
 of the universal charset detection library by Mozilla.
 .
 uchardet is a encoding detector library, which takes a sequence of
 bytes in an unknown character encoding without any additional
 information, and attempts to determine the encoding of the text.
 .
 The original code of universalchardet is available at
 http://lxr.mozilla.org/seamonkey/source/extensions/universalchardet
 .
 Techniques used by universalchardet are described at
 http://www.mozilla.org/projects/intl/UniversalCharsetDetection.html

3
Cảm ơn! Từ trang chủ của dự án, tôi thấy rõ ràng có CLI đi kèm. Nó cũng có sẵn trên OS X khi cài đặt uchardetqua Homebrew.
Stefan Schmidt

1
Lúc đầu tôi hơi bối rối vì tài liệu ISO 8859-1 được xác định sai là Windows-1252 nhưng trong phạm vi có thể in được Windows-1252 là một siêu dữ liệu của ISO 8859-1 nên việc chuyển đổi với iconvhoạt động tốt.
Stefan Schmidt

16

Đối với Linux, có enca và đối với Solaris, bạn có thể sử dụng auto_ef .


Enca dường như quá khắt khe đối với tôi: enca -d -L zh ./a.txtthất bại với tin nhắn ./a.txt: Unrecognized encoding Failure reason: No clear winner.Như @grawity đã đề cập, chardetcòn lỏng lẻo hơn, tuy nhiên nó vẫn quá chậm.
Xiè Jìléi

10
Enca hoàn toàn thất bại trong bài kiểm tra "thực sự làm gì đó".
Michael Wolf

1
uchardet đã thất bại (phát hiện CP1252 thay vì CP1250 thực tế), nhưng enca hoạt động tốt. (ví dụ đơn lẻ, khó khái quát hóa ...)
Palo


2

Quay trở lại chardet (python 2.?) Cuộc gọi này có thể là đủ:

python -c 'import chardet,sys; print chardet.detect(sys.stdin.read())' < file
{'confidence': 0.98999999999999999, 'encoding': 'utf-8'}

Mặc dù nó không hoàn hảo ....

echo "öasd" | iconv -t ISO-8859-1 | python -c 'import chardet,sys; print chardet.detect(sys.stdin.read())'
{'confidence': 0.5, 'encoding': 'windows-1252'}

2

Đối với những người thường xuyên sử dụng Emacs, họ có thể thấy hữu ích sau đây (cho phép kiểm tra và xác thực thủ công việc truyền tải).

Hơn nữa, tôi thường thấy rằng tính năng tự động phát hiện char-set của Emacs hiệu quả hơn nhiều so với các công cụ phát hiện tự động char-set khác (chẳng hạn như chardet).

(setq paths (mapcar 'file-truename '(
 "path/to/file1"
 "path/to/file2"
 "path/to/file3"
)))

(dolist (path paths)
  (find-file path)
  (set-buffer-file-coding-system 'utf-8-unix)
  )

Sau đó, một cuộc gọi đơn giản đến Emacs với tập lệnh này làm đối số (xem tùy chọn "-l") thực hiện công việc.



0

isutf8(từ moreutilsgói) đã làm công việc


2
Làm sao? Câu trả lời này không thực sự hữu ích.
Moses

1
Nó không chính xác đã được hỏi, nhưng là một công cụ hữu ích. Nếu tệp hợp lệ UTF-8, trạng thái thoát bằng không. Nếu tệp không hợp lệ UTF-8 hoặc có một số lỗi, trạng thái thoát là khác không.
tấn

0

Ngoài ra trong trường hợp bạn tập tin -i cung cấp cho bạn không biết

Bạn có thể sử dụng lệnh php này có thể đoán bộ ký tự như dưới đây:

Trong php bạn có thể kiểm tra như dưới đây:

Chỉ định danh sách mã hóa rõ ràng:

php -r "echo 'probably : ' . mb_detect_encoding(file_get_contents('myfile.txt'), 'UTF-8, ASCII, JIS, EUC-JP, SJIS, iso-8859-1') . PHP_EOL;"

Chính xác hơn " mb_list_encodings ":

php -r "echo 'probably : ' . mb_detect_encoding(file_get_contents('myfile.txt'), mb_list_encodings()) . PHP_EOL;"

Ở đây trong ví dụ đầu tiên, bạn có thể thấy rằng tôi đặt một danh sách mã hóa (phát hiện thứ tự danh sách) có thể khớp. Để có kết quả chính xác hơn, bạn có thể sử dụng tất cả các mã hóa có thể thông qua: mb_list_encodings ()

Lưu ý các hàm mb_ ​​* yêu cầu php-mbopes

apt-get install php-mbstring 

Xem câu trả lời: https://stackoverflow.com/a/57010566/3382822

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.