2011-03-08 13 views
0

私は次のプログラムに遭遇し、予期せぬ結果を示しました。Javaの問題:バイト列から文字列を作成する

public class StringFromByte 
{ 
     public static void main(String[] args) 
     { 
      byte bytes[] = new byte[256]; 

      for(int i = 0; i < 256; i++) 
       bytes[i] = (byte)i; 

      String str = new String(bytes); 
      for(int i = 0, n = str.length(); i < n; i++) 
       System.out.print((int)str.charAt(i) + " "); 
     } 
} 

技術的には、このプログラムは0から255までの整数を順番に出力する必要があります。しかし、プログラムを実行すると、時にはこのシーケンス(0〜255)が表示されることがあります。その動作は不特定である。どうしたの?

+1

私は非決定論的な動作を説明することはできませんが、私は1つの問題が表示されます。 127以上のint値を1バイトにキャストすると、実際には負の値になり、intにキャストバックしたときに負の値が残るため、確定的であっても0〜255の値が返されません。これはランダムなバイトを文字列に投げ込むことに伴う発行されたエンコーディングには対処しません。 – rfeak

答えて

2

使用しているStringコンストラクタは、デフォルトの文字エンコーディングを使用します。いくつかのバイトをマルチバイト文字として解釈できます。

はこれを試してみてください:

  String str = new String(bytes, CharSet.forName("ISO-8859-1")); 

は、標準のCharSet名がリストされ、またCharSet API documentationを参照してください。

免責事項:私は通常、このコンストラクタをUTF-8に使用します。

+0

しかし、実行時にエンコーディングがどのように変化しますか? Umeshは「時々」秩序が変化すると述べています。実行中にエンコードの効果は変わらないはずですか? – peakit

+0

@peakit、すべての実行が同じプラットフォーム上で同じオプションで実行されているかどうかは不明でした。 –

0

まず、Java byteタイプが保持できる最大値は127です(バイトデータ型は8ビット符号付き2の補数です)。

+0

バイトキャストされたintを-127と127の間の整​​数に置き換えると、期待される結果が得られますか? –

1

その動作は不特定ではありません。

文字はバイトと同じではありませんが、これを書いた人はそれを知らないのです。ユニコードには約600万の文字がありますが、ユニークバイトは256バイトしかありません。これは、多くのユニコード文字が複数のバイトで表されることを意味します。

例のバイトの中には、文字に複数のバイトが必要であることが示されていますが、配列の「次の」バイトが有効なUTF-8文字に対応していないと推測しています。

UTF-8以外のバイトセットから適切に文字列をエンコードするには、use this constructorを使用します。 正しい文字セットを指定しなければならないので、Javaはバイトがどのように文字に収まるかを理解できます。

結果が異なる原因は、環境によるものです。各環境には、好みの文字セットを指定するデフォルトのLocaleがあります。使用しているコンストラクタは常にUTF-8文字セットを前提としているので、ソースバイトを間違った形に誤って変換することがあります。

0

bytecharに置き換えると、期待どおりに動作します。それはバイトの最大127のためです。

関連する問題