3

Windows マシンで生成された集計データのテキスト ファイルの処理に問題があります。私はRuby 1.8で作業しています。次の例では、ファイルの 2 行目を処理するときにエラー ("\000" (Iconv::InvalidCharacter)) が発生します。最初の行は正しく変換されます。

require 'iconv'
conv = Iconv.new("UTF-8//IGNORE","UTF-16")
infile = File.open(tabfile, "r")
while (line = infile.gets)
  line = conv.iconv(line.strip)  # FAILS HERE
  puts line
  # DO MORE STUFF HERE
end

奇妙なことに、ファイルの最初の行を問題なく読み取って変換します。Iconv コンストラクターに //IGNORE フラグがあります。これは、この種のエラーを抑制するためのものだと思いました。

しばらくサークルに入っています。アドバイスをいただければ幸いです。

ありがとう!

編集: Hobbs ソリューションはこれを修正します。ありがとうございました。コードを次のように変更するだけです。

require 'iconv'
conv = Iconv.new("UTF-8//IGNORE","UTF-16")
infile = File.open(tabfile, "r")
while (line = infile.gets("\x0a\x00"))
  line = conv.iconv(line.strip)  # NO LONGER FAILS HERE
  # DOES MORE STUFF HERE
end

ここで必要なのは、どの get セパレーターを使用するかを自動的に決定する方法を見つけることだけです。

4

2 に答える 2

6

エラー メッセージはかなりあいまいですが、UTF-16 のすべての文字が 2 (場合によっては 4) バイトであるため、1 行に奇数のバイト数が見つかったという事実については不満だと思います。そして、その理由はあなたの使用にあると思いますgets-ファイル内の行はUTF-16le改行で区切られていますが、これ0x0a 0x00gets分割されています(そしてstrip削除されています)0x0aのみです。

例として、ファイルに次のものが含まれているとします。

ab
cd

UTF-16le でエンコードされています。それは

0x61 0x00 0x62 0x00 0x0a 0x00 0x63 0x00 0x64 0x00 0x0a 0x00
    a         b         \n        c         d         \n

gets最初の まで読み取ります0x0a。これstripは削除されるため、読み取られる最初の行は0x61 0x00 0x62 0x00であり、iconv はこれを喜んで受け入れ、UTF-8 に0x61 0x62"ab" としてエンコードします。gets次に、次の まで読み取ります0x0a。これstripは再び削除されます。そのため、2 回目lineは取得0x00 0x63 0x00 0x64 0x00され、すべてが台無しになります。1 バイト同期がずれており、変換するバイト数が奇数でありiconv、何と互換性がないために爆発します。あなたはそれをするように頼みました。

実際に動作するファイルのエンコーディング/デコーディング レイヤーがない場合、gets区切り文字を"\n"( "\x0a")から に変更し、エンコーディング クリーンではないため の"\x0a\x00"使用をすべて放棄し、代わりにを使用して、余分な行を追加しないようにする必要があると思います-終了します(すでに取得しているものを変換するため)。stripprintputs

Windows ファイルを操作している場合、UTF-16le の Windows CRLF は"\x0d\x00\x0a\x00".

于 2011-05-30T04:10:36.373 に答える
0

上記の答えは良いです。ファイル全体を 1 行ずつ処理する前に UTF-8 に変換することもできますが、大きなファイルではストリーミング動作が悪化する可能性があります。

于 2011-05-31T02:51:40.790 に答える