Javaで文字列をUTF8バイト配列との間で変換する方法


239

Javaでは、文字列があり、それをバイト配列としてエンコードしたい(UTF8またはその他のエンコード)。または、バイト配列(既知のエンコーディング)があり、それをJava文字列に変換したいと思います。これらの変換はどのように行うのですか?

回答:


355

Stringからbyte []に​​変換します:

String s = "some text here";
byte[] b = s.getBytes(StandardCharsets.UTF_8);

byte []からStringに変換します。

byte[] b = {(byte) 99, (byte)97, (byte)116};
String s = new String(b, StandardCharsets.US_ASCII);

もちろん、正しいエンコーディング名を使用する必要があります。私の例では、最も一般的な2つのエンコーディングであるUS-ASCIIとUTF-8を使用しました。


30
US-ASCIIは、現在、あまり一般的なエンコーディングではありません。Windows-1252とISO-8859-1(ASCIIのスーパーセット)ははるかに普及しています。
Michael Borgwardt

11
実際、それは私の仕事ではかなり一般的です。Windows-1252またはISO-8859-1として保存されている可能性がある、または「過去10年間保持していたレガシープログラムの出力」として保存されている可能性があるが、有効であることが保証されているバイトを含むバイトストリームをよく読み取るUS-ASCII文字。また、そのようなファイルを生成する必要があることもよくあります(ASCII以外の文字を処理できる場合とそうでない場合があるコードで使用するため)。基本的に、US-ASCIIは多くのソフトウェアの「最も大きな共通点」です。
mcherm

1
ただし、この方法では変換の問題は報告されません。これはあなたが望むものかもしれません。そうでない場合は、代わりにCharsetEncoderを使用することをお勧めします。
Michael Piefel、2011

7
@Pacerier は、Charsetのドキュメントが標準文字セットの1つとして「UTF-8」をリストしているためです。あなたのつづりも受け入れられると思いますが、私はドキュメントが言ったことに行きました。
mcherm 2012年

20
JDK7以降、StandardCharsets.UTF_8docs.oracle.com /javase/7/docs/api/java/nio/charset/
Rafael Membrives

95

以下は、すべての変換で文字セット検索を実行しないようにするソリューションです。

import java.nio.charset.Charset;

private final Charset UTF8_CHARSET = Charset.forName("UTF-8");

String decodeUTF8(byte[] bytes) {
    return new String(bytes, UTF8_CHARSET);
}

byte[] encodeUTF8(String string) {
    return string.getBytes(UTF8_CHARSET);
}

4
@mcherm:パフォーマンスの差が小さい場合でも、可能な場合は文字列形式よりもオブジェクト(Charset、URLなど)を使用することをお勧めします。
Bart van Heukelom、2010

7
注:「1.6以降」のpublic String(byte [] bytes、Charset charset)
leo

1
「すべての変換でCharsetルックアップを実行しない」について...いくつかの出典を引用してください。java.nio.charset.Charset はString.getBytesのに構築されていないため、String.getBytesよりもオーバーヘッドが大きくなりますか?
パセリエ2012

2
ドキュメントには、「この文字列を特定の文字セットでエンコードできない場合のこのメソッドの動作は指定されていません。エンコードプロセスをさらに制御する必要がある場合は、CharsetEncoderクラスを使用する必要があります。」
2013年

24
注:Java 1.7以降StandardCharsets.UTF_8、UTF-8文字セットにアクセスするための一定の方法を使用できます。
Kat 14

17
String original = "hello world";
byte[] utf8Bytes = original.getBytes("UTF-8");

ありがとう!私はそれを自分で書き直し、別の変換の方向を追加しました。
mcherm 2008

1
@sminkダッシュはオプションではありません。これは「UTF-8」を使用する必要があります
Mel Nicholson

14

String(byte []、String)コンストラクターとgetBytes(String)メソッドを介して直接変換できます。Javaは、Charsetクラスを介して使用可能な文字セットを公開します。JDKドキュメントは、サポートされているエンコーディングがリストされています

時間の90%では、そのような変換はストリームで実行されるため、Reader / Writerクラスを使用します。任意のバイトストリームでStringメソッドを使用してインクリメンタルにデコードするのではなく、マルチバイト文字に関連するバグを受け入れる必要があります。


詳しく説明できますか?アプリケーションがで文字列をエンコードおよびデコードする場合、UTF-8マルチバイト文字に関する問題は何ですか?
ラフィアン

@raffianすべての文字データを一度に変換しないと、問題が発生する可能性があります。例については、こちらをご覧ください。
McDowell

12

私のtomcat7実装はISO-8859-1として文字列を受け入れています。HTTPリクエストのコンテンツタイプにもかかわらず。次の解決策は、 'é'のような文字を正しく解釈するときに役立ちました。

byte[] b1 = szP1.getBytes("ISO-8859-1");
System.out.println(b1.toString());

String szUT8 = new String(b1, "UTF-8");
System.out.println(szUT8);

文字列をUS-ASCIIとして解釈しようとすると、バイト情報が正しく解釈されませんでした。

b1 = szP1.getBytes("US-ASCII");
System.out.println(b1.toString());

8
参考までに、Java 7以降では、StandardCharSets.UTF_8およびなどの文字セット名に定数を使用できますStandardCharSets.ISO_8859_1
バジルブルク2014年

上記の最初の解決策のために、まったく問題なく作業できました。
Hassan Jamil

7

別の方法として、Apache CommonsのStringUtilsを使用できます。

 byte[] bytes = {(byte) 1};
 String convertedString = StringUtils.newStringUtf8(bytes);

または

 String myString = "example";
 byte[] convertedBytes = StringUtils.getBytesUtf8(myString);

非標準の文字セットがある場合、それに応じてgetBytesUnchecked()またはnewString()を使用できます。


4
このStringUtilsは、Commons Langではなく、Commons Codecからのものです。
アーレンドv。ライナースドルフ2016

はい、ちょっとした落とし穴!Gradle、Mavenユーザーの場合:"commons-codec:commons-codec:1.10"(執筆時)。これは、たとえばApache POIとの依存関係としてもバンドルされています。いつものように、Apache Commonsとは別に、救出に!
マイクげっ歯類

2

一連のバイトを通常の文字列メッセージにデコードするために、私は最終的に次のコードでUTF-8エンコーディングで動作するようにしました。

/* Convert a list of UTF-8 numbers to a normal String
 * Usefull for decoding a jms message that is delivered as a sequence of bytes instead of plain text
 */
public String convertUtf8NumbersToString(String[] numbers){
    int length = numbers.length;
    byte[] data = new byte[length];

    for(int i = 0; i< length; i++){
        data[i] = Byte.parseByte(numbers[i]);
    }
    return new String(data, Charset.forName("UTF-8"));
}

1

7ビットASCIIまたはISO-8859-1(驚くほど一般的な形式)を使用している場合は、新しいjava.lang.Stringを作成する必要はありません。。バイトをcharにキャストする方がはるかにパフォーマンスが高くなります。

完全に機能する例:

for (byte b : new byte[] { 43, 45, (byte) 215, (byte) 247 }) {
    char c = (char) b;
    System.out.print(c);
}

あなたがしている場合ではない使用して拡張文字 Ä、AE、A、C、I、Êのようなのみ送信値は最初の128個のUnicode文字であることを確認することができますが、このコードはUTF-8および拡張ASCIIのために動作します(cp-1252など)。


1

コメントはできませんが、新しいスレッドを開始したくありません。しかし、これは機能していません。簡単な往復:

byte[] b = new byte[]{ 0, 0, 0, -127 };  // 0x00000081
String s = new String(b,StandardCharsets.UTF_8); // UTF8 = 0x0000, 0x0000,  0x0000, 0xfffd
b = s.getBytes(StandardCharsets.UTF_8); // [0, 0, 0, -17, -65, -67] 0x000000efbfbd != 0x00000081

エンコードの前後にb []と同じ配列が必要です(そうでない場合、これは最初の回答を参照しています)。


0
//query is your json   

 DefaultHttpClient httpClient = new DefaultHttpClient();
 HttpPost postRequest = new HttpPost("http://my.site/test/v1/product/search?qy=");

 StringEntity input = new StringEntity(query, "UTF-8");
 input.setContentType("application/json");
 postRequest.setEntity(input);   
 HttpResponse response=response = httpClient.execute(postRequest);

文字列エンティティは「クエリ」をutf-8に変換しますか、それともエンティティをアタッチするときに覚えていますか?
SyntaxRules 2013年

0
Charset UTF8_CHARSET = Charset.forName("UTF-8");
String strISO = "{\"name\":\"א\"}";
System.out.println(strISO);
byte[] b = strISO.getBytes();
for (byte c: b) {
    System.out.print("[" + c + "]");
}
String str = new String(b, UTF8_CHARSET);
System.out.println(str);

0
Reader reader = new BufferedReader(
    new InputStreamReader(
        new ByteArrayInputStream(
            string.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8));

-9

ひどく遅くなりましたが、この問題が発生しました。これは私の修正です。

private static String removeNonUtf8CompliantCharacters( final String inString ) {
    if (null == inString ) return null;
    byte[] byteArr = inString.getBytes();
    for ( int i=0; i < byteArr.length; i++ ) {
        byte ch= byteArr[i]; 
        // remove any characters outside the valid UTF-8 range as well as all control characters
        // except tabs and new lines
        if ( !( (ch > 31 && ch < 253 ) || ch == '\t' || ch == '\n' || ch == '\r') ) {
            byteArr[i]=' ';
        }
    }
    return new String( byteArr );
}

2
まず、それは変換ではありません。それは、印刷不可能なバイトの削除です。第2に、基盤となるOSのデフォルトのエンコーディングが実際には印刷可能な文字のASCIIに基づいていると想定しています(たとえば、EBCDICを使用するIBMメインフレームでは機能しません)。
アイザック
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.