1

我有一個基於GAE和Python的網站,我希望用戶能夠上傳文本文件進行處理。我的實現是基於從文檔(見http://code.google.com/appengine/docs/python/blobstore/overview.html)和我的文本文件上傳處理標準代碼基本上是這樣的:確定上傳到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,編碼的文本文件,這是你會得到什麼當使用Windows記事本並保存它所謂的「ANSI」編碼時。但是,如果你使用這個處理程序的文件已經用記事本的UTF-8編碼保存,並且包含一些西里爾文字符或者U變音符號,那麼你最終會得到一些亂碼。對於這樣的文件,將解碼('cp1252')更改爲解碼('utf_8')將會起作用。 (好吧,在開始時也有一個字節順序標記(BOM)的可能性,但這很容易被剝離。)

但是,您如何知道要使用哪種解碼?物料清單並不保證在那裏,除了詢問可能不知道的用戶外,我沒有看到任何其他方式知道。有確定編碼的可靠方法嗎?如果有其他方法解決它,我不一定非要使用blobstore。

然後是Windows記事本稱爲「Unicode」的編碼,這是一種UTF-16小端編碼。我無法找到解碼(包括「utf_16_le」),該解碼正確解碼用此編碼保存的文件。可以讀取其中一個文件嗎?

回答

1

在demalexx響應之後,我的上傳處理程序現在使用chardet(http://pypi.python.org/pypi/chardet)確定編碼,從我所知道的來看,它的工作非常好。 一路走來,我發現使用「在blob_reader中行」讀取上傳的文本文件是非常麻煩的。相反,如果你不介意一口氣讀取你的整個文件,那麼解決方案很簡單。 (注意剝去一個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) 

如果你想從你上傳的文件零碎讀,你在痛苦的世界。問題在於「對於blob_reader中的行」顯然會讀取到換行(\ x0a)字節的位置,這在讀取utf_16_le編碼文件時是災難性的,因爲它會將\ x0a \ x00序列切成兩半!

我不推薦它,但是這裏有一個上傳處理程序,它將成功處理由Windows 7記事本(即ANSI,UTF-8,Unicode和Unicode大端排序)中的所有編碼存儲的文件。正如你所看到的,剝離線路終端序列是很麻煩的。

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)) 

這無疑是脆弱的,我的測試僅限於這四種編碼,並且僅限於Windows 7記事本如何創建文件。請注意,在閱讀一行內容之前,我最多需要10000個字符以供chardet分析。這只是猜測它可能需要多少字節。這種笨拙的雙重閱讀是避免這種解決方案的另一個原因。

+0

如果您不介意將整個blob讀入內存,爲什麼首先使用blobstore上傳?爲什麼不直接上傳到你的處理程序? –

+0

另外,請對BlobReader提交錯誤報告。它目前不支持unicode,它應該是 - 如果在打開時指定了正確的編碼,它應該能夠正確地找到換行符。 –

+0

我會很樂意使用一個更簡單的系統 - 我只是不知道如何!我遵循我在文檔中發現的內容,並認爲我做得對。你能指出我的文檔描述你的建議,或張貼一些示例代碼?非常感激! (我將提交該錯誤。) – Dragonfly

相關問題