2011-12-11 1 views
2

유니 코드 또는 안시 (MS의 메모장 사용)로 저장할 수있는 파일 읽기를 지원하는 스크립트를 작성해야합니다.파이썬에서 ansi 또는 유니 코드로 저장할 수있는 파일을 읽는 방법은 무엇입니까?

인코딩 형식이 파일에 표시되지 않습니다. 두 인코딩 형식을 모두 지원하려면 어떻게해야합니까? (고급 형식을 알고있는 상태에서 파일을 읽는 일반적인 방법).

+0

어떤 Python 버전을 사용하고 있습니까? 2.x와 3.x는 유니 코드를 다르게 처리합니다. – FakeRainBrigand

+0

유니 코드의 경우 UTF-16 파일에서 ByteOrderMark (BOM)을 사용하여 실제로 유니 코드이고 바이트 순서를 알 수 있습니다. 일반 "ansi"(ascii, 나는 추정합니까?) 그런 표식으로. –

+0

Python 2.7을 사용하고 있습니다. – YSY

답변

11

MS 메모장 4 인코딩의 선택이 서투른 혼란 용어로 표현 사용자에게 제공한다. "유니 코드 빅 엔디안"은 빅 엔디안으로 작성된 UTF-16입니다. 두 가지 UTF-16 경우 모두 적절한 BOM이 작성된다는 의미입니다. 이러한 파일을 디코딩하려면 utf-16을 사용하십시오.

"UTF-8"은 UTF-8입니다. 메모장은 명시 적으로 "UTF-8 BOM"을 씁니다. 이러한 파일을 디코딩하려면 utf-8-sig을 사용하십시오.

"ANSI"는 충격입니다. "이 컴퓨터에 기본 레거시 인코딩이 무엇이든지"에 대한 MS 용어입니다. 그런 다음, 파일이이 읽고있는 컴퓨터에 생성 된 경우

cp874 Thai 
cp932 Japanese 
cp936 Unified Chinese (P.R. China, Singapore) 
cp949 Korean 
cp950 Traditional Chinese (Taiwan, Hong Kong, Macao(?)) 
cp1250 Central and Eastern Europe 
cp1251 Cyrillic (Belarusian, Bulgarian, Macedonian, Russian, Serbian, Ukrainian) 
cp1252 Western European languages 
cp1253 Greek 
cp1254 Turkish 
cp1255 Hebrew 
cp1256 Arabic script 
cp1257 Baltic languages 
cp1258 Vietnamese 
cp???? languages/scripts of India 

: 여기

은 그들이 사용하는 윈도우 내가 아는 인코딩 및 언어/스크립트의 목록입니다 "ANSI"인코딩을 locale.getpreferredencoding()으로 얻을 수 있습니다. 그렇지 않은 경우 UTF-16이 아닌 경우 사용할 인코딩을 지정할 수 있습니다. 그럴 수는 없다.

codecs.open()을 사용하여 Windows에서 파일을 읽을 때주의하십시오. 참고 : 바이너리 모드가 지정되지 않은 경우에도 파일은 항상 바이너리 모드로 열립니다. 이것은 8 비트 값을 사용하는 인코딩으로 인한 데이터 손실을 방지하기 위해 수행됩니다. 즉, '\ n "은 읽기와 쓰기로 이루어집니다." ""이것은 회선이 \r\n으로 끝나고 그걸 제거해야한다는 것을 의미합니다.메모장에서 다음과 같이 4 명 인코딩을 선택하여 저장

샘플 텍스트 파일을 찾습니다 :

것은 모두 함께 퍼팅

import locale 

def guess_notepad_encoding(filepath, default_ansi_encoding=None): 
    with open(filepath, 'rb') as f: 
     data = f.read(3) 
    if data[:2] in ('\xff\xfe', '\xfe\xff'): 
     return 'utf-16' 
    if data == u''.encode('utf-8-sig'): 
     return 'utf-8-sig' 
    # presumably "ANSI" 
    return default_ansi_encoding or locale.getpreferredencoding() 

if __name__ == "__main__": 
    import sys, glob, codecs 
    defenc = sys.argv[1] 
    for fpath in glob.glob(sys.argv[2]): 
     print 
     print (fpath, defenc) 
     with open(fpath, 'rb') as f: 
      print "raw:", repr(f.read()) 
     enc = guess_notepad_encoding(fpath, defenc) 
     print "guessed encoding:", enc 
     with codecs.open(fpath, 'r', enc) as f: 
      for lino, line in enumerate(f, 1): 
       print lino, repr(line) 
       print lino, repr(line.rstrip('\r\n')) 

: 여기

The quick brown fox jumped over the lazy dogs. 
àáâãäå 

일부 데모 코드 명령을 사용하여 Windows "명령 프롬프트"창에서 실행할 때 출력은 다음과 같습니다. \python27\python read_notepad.py "" t1-*.txt

,451,515,
('t1-ansi.txt', '') 
raw: 'The quick brown fox jumped over the lazy dogs.\r\n\xe0\xe1\xe2\xe3\xe4\xe5 
\r\n' 
guessed encoding: cp1252 
1 u'The quick brown fox jumped over the lazy dogs.\r\n' 
1 u'The quick brown fox jumped over the lazy dogs.' 
2 u'\xe0\xe1\xe2\xe3\xe4\xe5\r\n' 
2 u'\xe0\xe1\xe2\xe3\xe4\xe5' 

('t1-u8.txt', '') 
raw: '\xef\xbb\xbfThe quick brown fox jumped over the lazy dogs.\r\n\xc3\xa0\xc3 
\xa1\xc3\xa2\xc3\xa3\xc3\xa4\xc3\xa5\r\n' 
guessed encoding: utf-8-sig 
1 u'The quick brown fox jumped over the lazy dogs.\r\n' 
1 u'The quick brown fox jumped over the lazy dogs.' 
2 u'\xe0\xe1\xe2\xe3\xe4\xe5\r\n' 
2 u'\xe0\xe1\xe2\xe3\xe4\xe5' 

('t1-uc.txt', '') 
raw: '\xff\xfeT\x00h\x00e\x00 \x00q\x00u\x00i\x00c\x00k\x00 \x00b\x00r\x00o\x00w 
\x00n\x00 \x00f\x00o\x00x\x00 \x00j\x00u\x00m\x00p\x00e\x00d\x00 \x00o\x00v\x00e 
\x00r\x00 \x00t\x00h\x00e\x00 \x00l\x00a\x00z\x00y\x00 \x00d\x00o\x00g\x00s\x00. 
\x00\r\x00\n\x00\xe0\x00\xe1\x00\xe2\x00\xe3\x00\xe4\x00\xe5\x00\r\x00\n\x00' 
guessed encoding: utf-16 
1 u'The quick brown fox jumped over the lazy dogs.\r\n' 
1 u'The quick brown fox jumped over the lazy dogs.' 
2 u'\xe0\xe1\xe2\xe3\xe4\xe5\r\n' 
2 u'\xe0\xe1\xe2\xe3\xe4\xe5' 

('t1-ucb.txt', '') 
raw: '\xfe\xff\x00T\x00h\x00e\x00 \x00q\x00u\x00i\x00c\x00k\x00 \x00b\x00r\x00o\ 
x00w\x00n\x00 \x00f\x00o\x00x\x00 \x00j\x00u\x00m\x00p\x00e\x00d\x00 \x00o\x00v\ 
x00e\x00r\x00 \x00t\x00h\x00e\x00 \x00l\x00a\x00z\x00y\x00 \x00d\x00o\x00g\x00s\ 
x00.\x00\r\x00\n\x00\xe0\x00\xe1\x00\xe2\x00\xe3\x00\xe4\x00\xe5\x00\r\x00\n' 
guessed encoding: utf-16 
1 u'The quick brown fox jumped over the lazy dogs.\r\n' 
1 u'The quick brown fox jumped over the lazy dogs.' 
2 u'\xe0\xe1\xe2\xe3\xe4\xe5\r\n' 
2 u'\xe0\xe1\xe2\xe3\xe4\xe5' 

상황이 알고 있어야합니다 :

(1) "MBCS는"전혀 내용 파일의을 디코딩 아무런 관련이없는 파일 시스템 의사 인코딩입니다. 기본 인코딩이 cp1252 인 시스템에서는 latin1 (aarrgghh !!)과 같습니다. 아래를 참조

>>> all_bytes = "".join(map(chr, range(256))) 
>>> u1 = all_bytes.decode('cp1252', 'replace') 
>>> u2 = all_bytes.decode('mbcs', 'replace') 
>>> u1 == u2 
False 
>>> [(i, u1[i], u2[i]) for i in xrange(256) if u1[i] != u2[i]] 
[(129, u'\ufffd', u'\x81'), (141, u'\ufffd', u'\x8d'), (143, u'\ufffd', u'\x8f') 
, (144, u'\ufffd', u'\x90'), (157, u'\ufffd', u'\x9d')] 
>>> 

(2) chardet는 비 라틴 스크립트를 기반으로 인코딩을 감지 매우 좋은 (중국어/일본어/한국어, 키릴 문자, 히브리어, 그리스어)하지만 서양 (라틴어 기반의 인코딩 훨씬 좋은/중부/동부 유럽, 터키어, 베트남어) 아랍어를 전혀 아는 것이 아닙니다.

3

메모장은 유니 코드 파일을 바이트 순서 표시로 저장합니다. 이 파일의 첫 번째 바이트가된다는 것을 의미합니다 : - UTF-8

  • FF FE를 -

    • EF BB BF (실제로 UTF-16 리틀 엔디안 모양) "유니 코드"
    • FE FF는 - "유니 코드 빅 엔디안은"확실 메모장 알고있는 경우

    다른 텍스트 편집기가 나 같은 동작을하지 않을 수 있지만, 사용되는 수 (UTF-16 빅 엔디안 모양) 이렇게하면 인코딩을 자동 선택하기위한 적절한 경험을 얻을 수 있습니다. 그러나 이러한 모든 시퀀스는 ANSI 인코딩에서도 유효하므로이 경험적 방법으로 실수를 저지르는 것이 가능합니다. 올바른 인코딩이 사용된다는 것을 보증하는 것은 불가능합니다. UTF-16 기록 리틀 엔디안이다

    "유니"

  • +0

    +1은 BOM을 찾아 인코딩을 탐지하려고 시도하는 것이 단지 경험적이라고 지적합니다. 이 방법으로 인코딩을 추측하는 것은 유니 코드위원회에서 권장하지 않습니다. BOM은 알려진 인코딩 내에서 바이트 정렬을 나타 내기위한 것입니다. UTF-32, UTF-16 및 UTF-8을 구별하는 것조차 권장하지 않습니다. – bames53

    +1

    @ bames53. 귀하의 의견은 유니 코드 [바이트 주문 마크 FAQ] (http://www.unicode.org/faq/utf_bom.html#BOM) - 특히 "Q : BOM은 어디에 유용합니까?"섹션의 조언과 반대되는 것으로 보입니다. . 물론 _any_ 인코딩 서명은 항상 파일의 진정한 인코딩에 대해 거짓말을합니다. 그러나 가장 실제적인 목적을 위해 BOM은 합리적으로 신뢰할만한 지표입니다. – ekhumoro

    +0

    @ bames53 : 의도 된 BOM은 부적합합니다. 문제는 메모장의 알려진 동작과 파일이 실제로 메모장에서 만들어 졌음을 감안할 때 그러한 파일을 읽는 가장 좋은 전략은 무엇인가하는 점입니다. 그러한 전략이 경험적 방법을 포함한다는 사실은 말할 것도없이 빠져 나간다. –

    관련 문제