3

行ごとに読む必要のある巨大なgzip圧縮されたテキストファイルがあります。私は次のように行きます:

for i, line in enumerate(codecs.getreader('utf-8')(gzip.open('file.gz'))):
  print i, line

ファイルの後半のある時点で、Pythonの出力がファイルから分岐します。これは、Pythonが改行と見なす奇妙な特殊文字が原因で行が途切れているためです。'vim'でファイルを開くと正しいのですが、疑わしい文字のフォーマットがおかしいです。これを修正するために私にできることはありますか?

utf-16、latin-1などの他のコーデックを試しました。私もコーデックなしで試しました。

'od'を使用してファイルを確認しました。案の定、あるべきではない\n文字があります。しかし、「間違った」ものは奇妙なキャラクターが前に付いています。ここにはいくつかのエンコーディングがあり、一部の文字は2バイトであると思いますが、正しく表示されない場合、末尾のバイトは\nです。

'od -h file'によると、問題のある文字は'1d1c'です。

交換した場合:

gzip.open('file.gz')

と:

os.popen('zcat file.gz')

それは正常に動作します(そして実際には、かなり高速です)。しかし、どこが間違っているのか知りたいのですが。

4

2 に答える 2

5

コーデックなしで再試行してください。以下は、コーデックを使用する場合の問題と、コーデックなしで問題がない場合の問題を再現しています。

import gzip 
import os 
import codecs 

data = gzip.open("file.gz", "wb") 
data.write('foo\x1d\x1cbar\nbaz') 
data.close() 

print list(codecs.getreader('utf-8')(gzip.open('file.gz'))) 
print list(os.popen('zcat file.gz')) 
print list(gzip.open('file.gz')) 

出力:

[u'foo\x1d', u'\x1c', u'bar\n', u'baz']
['foo\x1d\x1cbar\n', 'baz']
['foo\x1d\x1cbar\n', 'baz']
于 2010-05-02T04:20:28.013 に答える
1

私は(コメントで) "" "print repr(weird_special_characters)からの出力を表示してください。vimでファイルを開いたとき、何が正しいですか?""奇妙にフォーマットされた"よりも正確にしてください。"""しかし何もありません:- ((

どのファイルで見ていodますか?file.gz?? そこに認識できるものがあれば、それはgzipファイルではありません。改行は表示されません。0x0Aを含むバイナリバイトが表示されます。

元のファイルがutf-8でエンコードされている場合、他のコーデックで試してみる意味は何でしたか?

「zcatで問題なく動作する」とは、utf8デコードステップなしで認識可能なデータを取得したことを意味しますか?

コードを単純化して、一度に1ステップずつ実行することをお勧めします...たとえば、この質問に対する受け入れられた回答を参照してください。もう一度試して、実行した正確なコードを表示し、結果を説明するときにrepr()を使用してください。

更新DSは、\x1cと\x1dについて説明しようとしていることを推測したようです。

なぜそれがそのように起こるのかについてのいくつかのメモがあります:

ASCIIでは、改行時に\rと\nのみが考慮されます。

>>> import pprint
>>> text = ''.join('A' + chr(i) for i in range(32)) + 'BBB'
>>> print repr(text)
'A\x00A\x01A\x02A\x03A\x04A\x05A\x06A\x07A\x08A\tA\nA\x0bA\x0cA\rA\x0eA\x0fA\x10
A\x11A\x12A\x13A\x14A\x15A\x16A\x17A\x18A\x19A\x1aA\x1bA\x1cA\x1dA\x1eA\x1fBBB'
>>> pprint.pprint(text.splitlines(True))
['A\x00A\x01A\x02A\x03A\x04A\x05A\x06A\x07A\x08A\tA\n', # line break
 'A\x0bA\x0cA\r', # line break
 'A\x0eA\x0fA\x10A\x11A\x12A\x13A\x14A\x15A\x16A\x17A\x18A\x19A\x1aA\x1bA\x1cA\x
1dA\x1eA\x1fBBB']
>>>

ただし、Unicodeでは、文字\ x1D(FILE SEPARATOR)、\ x1E(GROUP SEPARATOR)、および\ x1E(RECORD SEPARATOR)も行末として修飾されます。

>>> text = u''.join('A' + unichr(i) for i in range(32)) + u'BBB'
>>> print repr(text)
u'A\x00A\x01A\x02A\x03A\x04A\x05A\x06A\x07A\x08A\tA\nA\x0bA\x0cA\rA\x0eA\x0fA\x10A\x11A\x12A\x13A\x14A\x15A\x16A\x17A\x18A\x19A\x1aA\x1bA\x1cA\x1dA\x1eA\x1fBBB'
>>> pprint.pprint(text.splitlines(True))
[u'A\x00A\x01A\x02A\x03A\x04A\x05A\x06A\x07A\x08A\tA\n', # line break
 u'A\x0bA\x0cA\r', # line break
 u'A\x0eA\x0fA\x10A\x11A\x12A\x13A\x14A\x15A\x16A\x17A\x18A\x19A\x1aA\x1bA\x1c', # line break
 u'A\x1d', # line break
 u'A\x1e', # line break
 u'A\x1fBBB']
>>>

これは、使用するコーデックが何であれ発生します。使用する必要のあるコーデック(ある場合)を理解する必要があります。また、元のファイルが実際にテキストファイルであり、バイナリファイルではないかどうかを確認する必要があります。テキストファイルの場合は、ファイル内の\x1cと\x1dの意味を考慮する必要があります。

于 2010-04-30T02:28:17.750 に答える