1

저는 GAE 및 Python을 기반으로하는 웹 사이트를 보유하고 있으며 처리를 위해 사용자가 텍스트 파일을 업로드 할 수 있기를 바랍니다.Google App Engine에 업로드 된 파일의 인코딩 결정

class Uploader(blobstore_handlers.BlobstoreUploadHandler): 
    def post(self): 
     upload_files = self.get_uploads('file') 
     blob_info = upload_files[0] 
     blob_reader = blobstore.BlobReader(blob_info.key()) 
     for line in blob_reader: 
      line = line.rstrip().decode('cp1252') 
      do_something(line) 
     blob_reader.close() 

이 코드 페이지 1252로 인코딩 된 텍스트 파일에 대해 잘 작동 당신이 무엇을 얻을이다 : 내 구현은 워드 프로세서 (http://code.google.com/appengine/docs/python/blobstore/overview.html 참조) 내 텍스트 파일 업로드 핸들러에서 표준 코드를 기반으로 본질적으로 다음과 같습니다 Windows 메모장을 사용하고 "ANSI"인코딩으로 저장하면됩니다. 그러나이 핸들러를 메모장의 UTF-8 인코딩으로 저장 한 파일과 함께 사용하고 키릴 문자 또는 u- 움라우트가 포함되어 있으면 결국 횡설수설로 끝날 것입니다. 이러한 파일의 경우 디코드 ('cp1252')를 디코딩 ('utf_8')하면 트릭이 수행됩니다. (음, 처음에는 바이트 순서 표시 (BOM) 가능성이 있지만 쉽게 제거됩니다.)

그러나 사용하는 디코딩은 어떻게 알 수 있습니까? BOM은 거기에있을 것이라고 보장 할 수 없으며 사용자에게 물어 보는 것 외에 다른 방법을 알지 못합니다. 누가 알지도 모르는 사람입니다. 인코딩을 결정하기위한 신뢰할 수있는 방법이 있습니까? 다른 방법으로도 해결할 수 있다면 블롭 스토어를 사용할 필요는 없습니다.

그리고 Windows 메모장에서 UTF-16 little endian 인코딩 인 "유니 코드"라고하는 인코딩이 있습니다. 이 인코딩으로 저장된 파일을 올바르게 디코딩하는 디코딩 ("utf_16_le"포함)을 찾을 수 없습니다. 이 파일들 중 하나를 읽을 수 있습니까?

답변

3

이 내용이 도움이 될 수도 있습니다. Python: Is there a way to determine the encoding of text file?.

+0

내가 사전 게시 검색 중에 어떻게 이것을 놓쳤는지 모르겠지만, 어쨌든 나는 chardet에 대해 알고있어 감사합니다. 나는 배운 것을 가져 왔고 나의 질문에 대한 내 대답을 게시했다. 이것은 같은 문제에 직면 한 다른 사람들에게 도움이 될 것이다. – Dragonfly

1

demalexx의 응답에 따라, 내 업로드 처리기가 chardet (http://pypi.python.org/pypi/chardet)을 사용하여 인코딩을 결정합니다. 이는 내가 알 수있는 것으로부터 매우 잘 작동합니다. "blob_reader for line"을 사용하여 업로드 된 텍스트 파일을 읽는 것이 매우 번거롭다는 것을 발견했습니다. 대신, 한 파일에서 전체 파일을 읽지 않아도된다면 쉽게 해결할 수 있습니다. (원정 하나의 BOM 시퀀스의 제거, 그리고 CR/LF에서 라인의 분할을합니다.)

class Uploader(blobstore_handlers.BlobstoreUploadHandler): 
    def post(self): 
     upload_files = self.get_uploads('file') 
     blob_info = upload_files[0] 
     text = blobstore.BlobReader(blob_info.key()).read() 
     encoding = chardet.detect(text)['encoding'] 
     if encoding is not None: 
      for line in text.decode(encoding).lstrip(u'\ufeff').split(u'\x0d\x0a'): 
       do_something(line) 

당신이 업로드 한 파일에서 조금씩 읽고 싶다면, 당신은 고통의 세계에 대한에있어. 문제는 "for line in blob_reader"가 줄 바꿈 (\ x0a) 바이트가있는 곳을 읽는 것입니다. utf_16_le 인코딩 파일을 읽을 때 \ x0a \ x00 시퀀스가 ​​반으로 자르기 때문에 재앙입니다!

필자는 권장하지 않지만 한 번에 한 줄씩 Windows 7 메모장 (즉, ANSI, UTF-8, 유니 코드 및 유니 코드 빅 엔디안)의 모든 인코딩에 의해 저장된 파일을 성공적으로 처리하는 업로드 처리기를 사용합니다 . 보시다시피, 라인 종료 시퀀스를 제거하는 것은 번거로운 일입니다.

class Uploader(blobstore_handlers.BlobstoreUploadHandler): 
    def post(self): 
     upload_files = self.get_uploads('file') 
     blob_info = upload_files[0] 
     blob_reader = blobstore.BlobReader(blob_info.key()) 
     encoding = chardet.detect(blob_reader.read(10000))['encoding'] 
     if encoding is not None: 
      blob_reader.seek(0) 
      for line in blob_reader: 
       if line[:2] in ['\xff\xfe','\xfe\xff']: 
        start = 2 
       elif line[:3] == '\xef\xbb\xbf': 
        start = 3 
       else: 
        start = 0 
       if encoding == 'UTF-16BE': 
        if line[-4:] == '\x00\x0d\x00\x0a': 
         line = line[start:-4] 
        elif start > 0: 
         line = line[start:] 
       elif encoding == 'UTF-16LE': 
        if line[start] == '\x00': 
         start += 1 
        if line[-3:] == '\x0d\x00\x0a': 
         line = line[start:-3] 
        elif start > 0: 
         line = line[start:] 
       elif line[-2:] == '\x0d\x0a': 
        line = line[start:-2] 
       elif start > 0: 
        line = line[start:] 
       do_something(line.decode(encoding)) 

이것은 의심 할 여지없이 부서지기 쉬운, 그리고 내 시험은, 오직 윈도우 7 메모장 파일을 생성하는 방법에 대한 그 4 인코딩으로 제한되어있다. 한 번에 한 행을 읽기 전에 chardet이 분석 할 수 있도록 최대 10000자를 잡아 둡니다. 이는 필요한 바이트 수에 대한 추측 일뿐입니다. 이 서투른 더블 읽기는이 해결책을 피하기위한 또 다른 이유입니다.

+0

전체 BLOB를 메모리로 읽어도 상관 없으면 BLOBSTORE 업로드를 처음 사용하는 이유는 무엇입니까? 처리기에 직접 업로드하는 것이 가장 좋은 이유는 무엇입니까? –

+0

또한 BlobReader에 버그를 신고하십시오.그것은 현재 유니 코드 인식이 아니며 반드시 열려 있어야합니다. 올바른 인코딩을 지정하면 올바르게 개행을 찾을 수 있어야합니다. –

+0

더 간단한 시스템을 사용해도 행복 할 것입니다. 나는 문서에서 찾은 것을 따라 갔고 내가 올바르게하고 있다고 생각했다. 당신이 제안하는 방식을 설명하는 문서를 가르쳐 주시겠습니까, 아니면 샘플 코드를 게시 할 수 있습니까? 매우 감사! (그 버그를 신고 할게요.) – Dragonfly

관련 문제