これは通常は悪い考えですが、あなたの場合は改行もエンコードするため機能しません。
UTF-16 では、書き込んだ改行を含め、すべての文字が 2 バイトにエンコードされます。ファイルを 1 行ずつ読み取るため、Python はファイルから次の改行バイトまでのすべてのデータを提供しますが、UTF-16 では、返されたデータに 2 バイトのうちの 1 つがまだ含まれている可能性があり、結果として不完全になります。 UTF-16 バイト ストリーム。
これを理解するには、UTF-16 エンコーディングをより詳細に理解する必要があります。16 ビット データを 8 ビットの 2 バイトとして書き込む場合、コンピューターは最初にファイルに書き込むバイトを決定する必要があります。この決定は 2 つの方法で行うことができ、エンディアンと呼ばれます。ガリバーのリリパットのように、コンピュータ システムはビッグ エンディアンまたはリトル エンディアンのいずれかを優先します。
したがって、UTF-16 データ ストリームは 2 つの順序のいずれかで書き込まれ、どちらが選択されたかを示すためにバイト オーダー マークまたは「BOM」が最初に書き込まれます。
'\n\x00'
したがって、改行はまたはとしてエンコードされ'\x00\n'
、ヌルバイト ( ) を読み取ると、\x00
デコードする UTF-16 データの一部か、UTF-8 データ (無視される場合) のいずれかになります。したがって、UTF-16 をビッグ エンディアンとしてエンコードするとうまくいきますが (ただし、ヌル バイトが浮遊します)、リトル エンディアンとしてエンコードするとうまくいきません。
基本的に、エンコードされたデータは厳密にバイナリ データとして扱われる必要があり、別の方法を使用してエンコードされたテキストのさまざまな部分を記述するか、改行が改行として厳密にエンコードされるエンコーディングのみを使用する必要があります。
長さのプレフィックスを使用し、最初にそれを読み取り、次にエンコードされたデータごとにファイルからそのバイト数を読み取ります。
>>> import struct
>>> f = open('test', 'wb')
>>> entry1 = 'this is a test\n'.encode('utf-16')
>>> struct.pack('!h', len(entry1)))
>>> f.write(entry1)
>>> entry2 = 'another test\n'.encode('utf-8')
>>> f.write(struct.pack('!h', len(entry2)))
>>> f.write(entry2)
>>> f.close()
struct
モジュールを使用して、固定長データを書き込みました。ファイルもバイナリとして記述していることに注意してください。
読む:
>>> f = open('test', 'rb')
>>> fieldsize = struct.calcsize('!h')
>>> length = struct.unpack('!h', f.read(fieldsize))[0]
>>> print f.read(length).decode('utf-16')
this is a test
>>> length = struct.unpack('!h', f.read(fieldsize))[0]
>>> print f.read(length).decode('utf-8')
another test
>>>
再び、ファイルはバイナリ モードで開かれます。
実際のアプリケーションでは、おそらくエントリごとにエンコーディング情報も含める必要があります。