web-dev-qa-db-ja.com

バイト配列を文字列に変換する(Java)

Google App EngineでWebアプリケーションを作成しています。基本的に、ブロブストアに.htmlファイルとして保存されるHTMLコードを編集できます。

FetchDataを使用して、ファイル内のすべての文字のbyte[]を返します。ユーザーがhtmlコードを編集できるように、htmlに印刷しようとしています。すべてがうまくいきます!

ここに私の唯一の問題があります:

文字列に変換するときに、バイト配列に問題があります。スマート引用符といくつかのキャラクターがファンキーに見えます。 (?や日本語の記号など)具体的には、問題を引き起こしている負の値を持っているのは数バイトです。

スマート引用符は、バイト配列で-108および-109として返されます。これはなぜですか?正しい文字エンコーディングを表示するために負のバイトをデコードするにはどうすればよいですか?

85
Josh

バイト配列には、特別なエンコーディング(知っておくべき)の文字が含まれています。文字列に変換する方法は次のとおりです。

String decoded = new String(bytes, "UTF-8");  // example for one encoding type

ちなみに、Javaデータ型byteが署名されているという理由だけで、生のバイトが負の小数として表示される場合があり、それは-128から127の範囲をカバーします。


-109 = 0x93: Control Code "Set Transmit State"

値(-109)は、UNICODEの印刷不可能な制御文字です。したがって、UTF-8はその文字ストリームの正しいエンコードではありません。

「Windows-1252」の0x93は探している「スマートクォート」なので、そのエンコーディングのJava名は「Cp1252」です。次の行はテストコードを提供します。

System.out.println(new String(new byte[]{-109}, "Cp1252")); 
141
Andreas_D

Java 7以降

StandardCharsets からString定数として希望のエンコードをCharsetコンストラクターに渡すこともできます。これは、他の回答で提案されているように、エンコードをStringとして渡すよりも安全です。

たとえば、UTF-8エンコードの場合

String bytesAsString = new String(bytes, StandardCharsets.UTF_8);
25
davnicwil

これを試すことができます。

String s = new String(bytearray);
11
public class Main {

    /**
     * Example method for converting a byte to a String.
     */
    public void convertByteToString() {

        byte b = 65;

        //Using the static toString method of the Byte class
        System.out.println(Byte.toString(b));

        //Using simple concatenation with an empty String
        System.out.println(b + "");

        //Creating a byte array and passing it to the String constructor
        System.out.println(new String(new byte[] {b}));

    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        new Main().convertByteToString();
    }
}

出力

65
65
A
5
Adi Sembiring
public static String readFile(String fn)   throws IOException 
{
    File f = new File(fn);

    byte[] buffer = new byte[(int)f.length()];
    FileInputStream is = new FileInputStream(fn);
    is.read(buffer);
    is.close();

    return  new String(buffer, "UTF-8"); // use desired encoding
}
5
craig

Arrays.toString(byte_array);をお勧めします

それはあなたの目的に依存します。たとえば、次のようなデバッグ時に表示される形式とまったく同じバイト配列を保存したかったのです:[1, 2, 3]バイトを文字形式に変換せずにまったく同じ値を保存する場合は、Arrays.toString (byte_array)がこれを行います。ただし、バイトではなく文字を保存する場合は、String s = new String(byte_array)を使用する必要があります。この場合、sは、文字の形式で[1, 2, 3]と同等です。

4
Questioner

Andreas_Dからの以前の回答は良いです。出力を表示する場所にフォントと文字エンコードがあり、一部の文字がサポートされていない可能性があることを追加します。

問題がJavaであるか、ディスプレイであるかを判断するには、次のようにします。

    for(int i=0;i<str.length();i++) {
        char ch = str.charAt(i);
        System.out.println(i+" : "+ch+" "+Integer.toHexString(ch)+((ch=='\ufffd') ? " Unknown character" : ""));
    }

Javaは、不明な文字の公式文字を0xfffdに理解できない文字をマッピングします。 「?」が表示された場合出力では0xfffdにマッピングされていませんが、問題はJavaではなくディスプレイフォントまたはエンコードです。

3
Simon G.