텍스트 인코딩 결정 방법
인코딩된 텍스트를 받았는데 어떤 문자 집합이 사용되었는지 알 수 없습니다.Python을 사용하여 텍스트 파일의 인코딩을 결정하는 방법이 있습니까?C#을 취급하는 텍스트파일의 부호화/코드페이지는 어떻게 검출할 수 있습니까?
편집: 샤르데는 유지되지 않은 것처럼 보이지만 대부분의 답변이 적용됩니다.대체 방법은 https://pypi.org/project/charset-normalizer/를 참조하십시오.
부호화를 항상 올바르게 검출하는 것은 불가능합니다.
(Chardet FAQ에서):
그러나 일부 인코딩은 특정 언어에 최적화되어 있으며 언어는 랜덤하지 않습니다.일부 문자 시퀀스는 항상 나타나는 반면 다른 시퀀스는 의미가 없습니다.신문을 펴고 "txzqJv 2!dasd0a QqdKjvz"를 찾은 영어에 능통한 사람은 그것이 영어가 아님을 금방 알아차릴 것이다.컴퓨터 알고리즘은 많은 "일반적인" 텍스트를 학습함으로써 이러한 종류의 유창성을 시뮬레이션하고 텍스트의 언어에 대해 교양 있는 추측을 할 수 있습니다.
이 스터디를 사용하여 인코딩을 검출하는 샤르데 라이브러리가 있습니다.chardet은 Mozilla의 자동 검출 코드 포트입니다.
UnicodeDammit 를 사용할 수도 있습니다.다음 방법을 시도합니다.
- 문서 자체에서 발견된 인코딩입니다. 예를 들어 XML 선언 또는 (HTML 문서의 경우) http-equiv META 태그입니다.Beautiful Soup이 문서 내에서 이런 종류의 인코딩을 발견하면 문서를 처음부터 다시 구문 분석하여 새로운 인코딩을 시도합니다.유일한 예외는 인코딩을 명시적으로 지정하고 해당 인코딩이 실제로 작동한 경우입니다. 그러면 문서에서 발견된 인코딩은 무시됩니다.
- 파일의 처음 몇 바이트를 보고 스니핑된 인코딩입니다.이 단계에서 인코딩이 검출되면 UTF-* 인코딩, EBCDIC 또는 ASCII 중 하나가 됩니다.
- 샤르데 라이브러리가 스니핑하는 부호화(설치되어 있는 경우).
- UTF-8
- 윈도-1252
부호화를 해결하기 위한 또 다른 옵션은 libmagic(file 명령 뒤에 있는 코드)을 사용하는 것입니다.다양한 파이썬 바인딩을 사용할 수 있습니다.
파일 소스 트리에 존재하는 python 바인딩은 python-magic(또는 python3-magic) debian 패키지로 사용할 수 있습니다.파일의 부호화를 판별하려면 , 다음의 조작을 실시합니다.
import magic
blob = open('unknown-file', 'rb').read()
m = magic.open(magic.MAGIC_MIME_ENCODING)
m.load()
encoding = m.buffer(blob) # "utf-8" "us-ascii" etc
pypi에는 이름이 같지만 호환되지 않는 python-magic pip 패키지가 있습니다.libmagic
다음과 같은 으로 부호화를
import magic
blob = open('unknown-file', 'rb').read()
m = magic.Magic(mime_encoding=True)
encoding = m.from_buffer(blob)
몇 가지 인코딩 전략이 있습니다. 맛보기를 취소하십시오.
#!/bin/bash
#
tmpfile=$1
echo '-- info about file file ........'
file -i $tmpfile
enca -g $tmpfile
echo 'recoding ........'
#iconv -f iso-8859-2 -t utf-8 back_test.xml > $tmpfile
#enca -x utf-8 $tmpfile
#enca -g $tmpfile
recode CP1250..UTF-8 $tmpfile
루프 형식으로 파일을 열어 읽음으로써 인코딩을 확인할 수 있습니다.단, 먼저 파일사이즈를 확인해야 할 경우가 있습니다.
# PYTHON
encodings = ['utf-8', 'windows-1250', 'windows-1252'] # add more
for e in encodings:
try:
fh = codecs.open('file.txt', 'r', encoding=e)
fh.readlines()
fh.seek(0)
except UnicodeDecodeError:
print('got unicode error with %s , trying different encoding' % e)
else:
print('opening the file with encoding: %s ' % e)
break
a를 읽고 .chardet
예측,, " " "n_lines
파일이 클 경우 파일에서 가져옵니다.
chardet
수 확도얻(((((((((((((((((((:confidence
의 부호화 예측(그것을 어떻게 생각해냈는지 알 수 없다)이, 그 예측과 함께 반환된다.chardet.predict()
면면면면면면면면면면면면면
import chardet
from pathlib import Path
def predict_encoding(file_path: Path, n_lines: int=20) -> str:
'''Predict a file's encoding using chardet'''
# Open the file as binary data
with Path(file_path).open('rb') as f:
# Join binary lines for specified number of lines
rawdata = b''.join([f.readline() for _ in range(n_lines)])
return chardet.detect(rawdata)['encoding']
이것이 도움이 될 것이다.
from bs4 import UnicodeDammit
with open('automate_data/billboard.csv', 'rb') as file:
content = file.read()
suggestion = UnicodeDammit(content)
suggestion.original_encoding
#'iso-8859-1'
# Function: OpenRead(file)
# A text file can be encoded using:
# (1) The default operating system code page, Or
# (2) utf8 with a BOM header
#
# If a text file is encoded with utf8, and does not have a BOM header,
# the user can manually add a BOM header to the text file
# using a text editor such as notepad++, and rerun the python script,
# otherwise the file is read as a codepage file with the
# invalid codepage characters removed
import sys
if int(sys.version[0]) != 3:
print('Aborted: Python 3.x required')
sys.exit(1)
def bomType(file):
"""
returns file encoding string for open() function
EXAMPLE:
bom = bomtype(file)
open(file, encoding=bom, errors='ignore')
"""
f = open(file, 'rb')
b = f.read(4)
f.close()
if (b[0:3] == b'\xef\xbb\xbf'):
return "utf8"
# Python automatically detects endianess if utf-16 bom is present
# write endianess generally determined by endianess of CPU
if ((b[0:2] == b'\xfe\xff') or (b[0:2] == b'\xff\xfe')):
return "utf16"
if ((b[0:5] == b'\xfe\xff\x00\x00')
or (b[0:5] == b'\x00\x00\xff\xfe')):
return "utf32"
# If BOM is not provided, then assume its the codepage
# used by your operating system
return "cp1252"
# For the United States its: cp1252
def OpenRead(file):
bom = bomType(file)
return open(file, 'r', encoding=bom, errors='ignore')
#######################
# Testing it
#######################
fout = open("myfile1.txt", "w", encoding="cp1252")
fout.write("* hi there (cp1252)")
fout.close()
fout = open("myfile2.txt", "w", encoding="utf8")
fout.write("\u2022 hi there (utf8)")
fout.close()
# this case is still treated like codepage cp1252
# (User responsible for making sure that all utf8 files
# have a BOM header)
fout = open("badboy.txt", "wb")
fout.write(b"hi there. barf(\x81\x8D\x90\x9D)")
fout.close()
# Read Example file with Bom Detection
fin = OpenRead("myfile1.txt")
L = fin.readline()
print(L)
fin.close()
# Read Example file with Bom Detection
fin = OpenRead("myfile2.txt")
L =fin.readline()
print(L) #requires QtConsole to view, Cmd.exe is cp1252
fin.close()
# Read CP1252 with a few undefined chars without barfing
fin = OpenRead("badboy.txt")
L =fin.readline()
print(L)
fin.close()
# Check that bad characters are still in badboy codepage file
fin = open("badboy.txt", "rb")
fin.read(20)
fin.close()
자동 툴에 만족하지 않는 경우는, 모든 코덱을 시험해 보고, 어느 코덱이 적절한지를 수동으로 확인할 수 있습니다.
all_codecs = ['ascii', 'big5', 'big5hkscs', 'cp037', 'cp273', 'cp424', 'cp437',
'cp500', 'cp720', 'cp737', 'cp775', 'cp850', 'cp852', 'cp855', 'cp856', 'cp857',
'cp858', 'cp860', 'cp861', 'cp862', 'cp863', 'cp864', 'cp865', 'cp866', 'cp869',
'cp874', 'cp875', 'cp932', 'cp949', 'cp950', 'cp1006', 'cp1026', 'cp1125',
'cp1140', 'cp1250', 'cp1251', 'cp1252', 'cp1253', 'cp1254', 'cp1255', 'cp1256',
'cp1257', 'cp1258', 'euc_jp', 'euc_jis_2004', 'euc_jisx0213', 'euc_kr',
'gb2312', 'gbk', 'gb18030', 'hz', 'iso2022_jp', 'iso2022_jp_1', 'iso2022_jp_2',
'iso2022_jp_2004', 'iso2022_jp_3', 'iso2022_jp_ext', 'iso2022_kr', 'latin_1',
'iso8859_2', 'iso8859_3', 'iso8859_4', 'iso8859_5', 'iso8859_6', 'iso8859_7',
'iso8859_8', 'iso8859_9', 'iso8859_10', 'iso8859_11', 'iso8859_13',
'iso8859_14', 'iso8859_15', 'iso8859_16', 'johab', 'koi8_r', 'koi8_t', 'koi8_u',
'kz1048', 'mac_cyrillic', 'mac_greek', 'mac_iceland', 'mac_latin2', 'mac_roman',
'mac_turkish', 'ptcp154', 'shift_jis', 'shift_jis_2004', 'shift_jisx0213',
'utf_32', 'utf_32_be', 'utf_32_le', 'utf_16', 'utf_16_be', 'utf_16_le', 'utf_7',
'utf_8', 'utf_8_sig']
def find_codec(text):
for i in all_codecs:
for j in all_codecs:
try:
print(i, "to", j, text.encode(i).decode(j))
except:
pass
find_codec("The example string which includes ö, ü, or ÄŸ, ö")
이 스크립트는 최소 9409줄의 출력을 생성합니다.따라서 출력이 터미널 화면에 맞지 않는 경우 출력을 텍스트 파일에 써 보십시오.
일반적으로 텍스트 파일의 부호화를 결정하는 것은 원칙적으로 불가능하다.따라서 표준 Python 라이브러리는 없습니다.
텍스트 파일에 대한 보다 구체적인 지식(예: XML)이 있는 경우 라이브러리 기능이 있을 수 있습니다.
쉘을 할 수 .file
명령어를 입력합니다.이것은 Linux 머신 중 하나에서만 실행되는 스크립트로 사용하기 때문에 도움이 됩니다.
이것은 이상적인 솔루션이나 해답은 아니지만, 고객의 요구에 맞추어 수정할 수 있습니다.제 경우 파일이 UTF-8인지 아닌지만 확인하면 됩니다.
import subprocess
file_cmd = ['file', 'test.txt']
p = subprocess.Popen(file_cmd, stdout=subprocess.PIPE)
cmd_output = p.stdout.readlines()
# x will begin with the file type output as is observed using 'file' command
x = cmd_output[0].split(": ")[1]
return x.startswith('UTF-8')
파일의 내용을 알고 있는 경우는, 몇개의 인코딩으로 디코딩 해, 어느 것이 누락되어 있는지를 확인할 수 있습니다.일반적으로 텍스트 파일은 텍스트 파일이고 그것들은 멍청하기 때문에 방법이 없습니다;)
이 사이트에는 asciii, boms 및 utf8 no bom을 인식하기 위한 python 코드가 있습니다.https://unicodebook.readthedocs.io/guess_encoding.html파일을 바이트 배열(데이터)로 읽습니다.http://www.codecodex.com/wiki/Read_a_file_into_a_byte_array 를 참조해 주세요.여기 예가 있어요.나는 osx에 있다.
#!/usr/bin/python
import sys
def isUTF8(data):
try:
decoded = data.decode('UTF-8')
except UnicodeDecodeError:
return False
else:
for ch in decoded:
if 0xD800 <= ord(ch) <= 0xDFFF:
return False
return True
def get_bytes_from_file(filename):
return open(filename, "rb").read()
filename = sys.argv[1]
data = get_bytes_from_file(filename)
result = isUTF8(data)
print(result)
PS /Users/js> ./isutf8.py hi.txt
True
Linux 사용file -i
명령어
import subprocess
file = "path/to/file/file.txt"
encoding = subprocess.Popen("file -bi "+file, shell=True, stdout=subprocess.PIPE).stdout
encoding = re.sub(r"(\\n)[^a-z0-9\-]", "", str(encoding.read()).split("=")[1], flags=re.IGNORECASE)
print(encoding)
파일 전체를 메모리에 로드하지 않는 python-magic 패키지를 사용할 수 있습니다.
import magic
def detect(
file_path,
):
return magic.Magic(
mime_encoding=True,
).from_file(file_path)
출력은 다음과 같은 부호화 이름입니다.
- ISO-8859-1
- us-asciii의
- utf-8
샤르데 모듈을 사용할 수 있습니다.
import chardet
with open (filepath , "rb") as f:
data= f.read()
encode=chardet.UniversalDetector()
encode.close()
print(encode.result)
또는 linux에서 chardet3 명령어를 사용할 수 있지만 시간이 걸립니다.
chardet3 fileName
예:
chardet3 donnee/dir/donnee.csv
donnee/dir/donnee.csv: ISO-8859-1 with confidence 0.73
일부 텍스트 파일은 인코딩을 인식하지만 대부분은 인식되지 않습니다.인식:
- BOM이 있는 텍스트 파일
- XML 파일이 UTF-8로 인코딩되거나 그 인코딩이 프리암블로 지정됩니다.
- JSON 파일은 항상 UTF-8로 인코딩됩니다.
인식 안 함:
- CSV 파일
- 임의의 랜덤 텍스트파일
어떤 인코딩은 다용도입니다.즉, 임의의 바이트 시퀀스를 디코딩할 수 있고, 어떤 인코딩은 그렇지 않습니다.127을 초과하는 바이트는 어떤 문자에도 매핑되지 않으므로 US-ASCII는 범용성이 없습니다.UTF-8은 바이트 시퀀스가 유효하지 않기 때문에 범용성이 없습니다.
반대로 Latin-1, Windows-1252 등은 범용성이 있습니다(일부 바이트가 공식적으로 문자에 매핑되지 않은 경우에도 마찬가지).
>>> [b.to_bytes(1, 'big').decode("latin-1") for b in range(256)]
['\x00', ..., 'ÿ']
바이트 시퀀스로 인코딩된 임의의 텍스트파일을 지정하면 파일에 따라서는 부호화가 인식되지 않는 한 부호화를 판별할 수 없습니다.일부 부호화는 범용성이 있기 때문입니다.단, 범용성이 없는 인코딩은 제외할 수 있습니다.모든 범용 인코딩이 여전히 가능합니다.그chardet
모듈은 바이트 빈도를 사용하여 부호화된 텍스트에 가장 적합한 인코딩을 추측합니다.
이 모듈 또는 이와 유사한 모듈을 사용하지 않는 경우 다음과 같은 간단한 방법을 제시합니다.
- 파일이 부호화(BOM)를 인식하고 있는지 확인합니다.
- 범용성이 없는 인코딩을 체크하고 바이트를 디코딩할 수 있는 첫 번째 인코딩을 받아들인다(더 엄격하기 때문에 UTF-8 이전의 ASCII).
- 폴백 부호화를 선택합니다.
두 번째 단계는 샘플만 체크하는 경우 파일의 나머지 일부 바이트가 유효하지 않을 수 있으므로 약간 위험합니다.
코드:
def guess_encoding(data: bytes, fallback: str = "iso8859_15") -> str:
"""
A basic encoding detector.
"""
for bom, encoding in [
(codecs.BOM_UTF32_BE, "utf_32_be"),
(codecs.BOM_UTF32_LE, "utf_32_le"),
(codecs.BOM_UTF16_BE, "utf_16_be"),
(codecs.BOM_UTF16_LE, "utf_16_le"),
(codecs.BOM_UTF8, "utf_8_sig"),
]:
if data.startswith(bom):
return encoding
if all(b < 128 for b in data):
return "ascii" # you may want to use the fallback here if data is only a sample.
decoder = codecs.getincrementaldecoder("utf_8")()
try:
decoder.decode(data, final=False)
except UnicodeDecodeError:
return fallback
else:
return "utf_8" # not certain if data is only a sample
범용성이 없는 인코딩은 실패할 수 있습니다.그errors
의 파라미터decode
방법은 로 설정할 수 있습니다.'ignore'
,'replace'
또는'backslashreplace'
예외를 피하기 위해.
언급URL : https://stackoverflow.com/questions/436220/how-to-determine-the-encoding-of-text
'programing' 카테고리의 다른 글
Django DB를 SQLite에서 MySQL로 마이그레이션하는 가장 좋은 방법은 무엇입니까? (0) | 2023.02.02 |
---|---|
Vue 속성이 밑줄과 함께 유효하지 않습니다. (0) | 2023.01.13 |
VueJS / Vue Router - 목록 항목에서 상세 페이지 생성? (0) | 2023.01.13 |
인덱스된 부울 열과 Datetime 열에 대한 쿼리 성능 (0) | 2023.01.13 |
컴포넌트에 Import된 css 파일의 순서(vuejs) (0) | 2023.01.13 |