UTF-8 byte []からStringへ


243

BufferedInputStreamUTF-8でエンコードされたテキストファイルのバイトをバイト配列に読み込むためにa を使用したとしましょう。私は次のルーチンを使用してバイトを文字列に変換できることを知っていますが、バイトを反復してそれぞれを変換するよりも効率的でスマートな方法がありますか?

public String openFileToString(byte[] _bytes)
{
    String file_string = "";

    for(int i = 0; i < _bytes.length; i++)
    {
        file_string += (char)_bytes[i];
    }

    return file_string;    
}

17
なぜこれができないのです String fileString = new String(_bytes,"UTF-8");か?
CoolBeans 2011

1
または、BufferedReaderを使用してchar配列に読み込むこともできます。
アンディトーマス


@CoolBeans私がそうすることを知っていれば、私はできました;)ありがとうございます。
スケリル

ファイルサイズによっては、全体byte[]をメモリにロードし、それを介してnew String(_bytes,"UTF-8")(または+=文字列のチャンクによって)変換するのが最も効率的かどうかはわかりません。特に大きなファイルでは、InputStreamsとReadersをチェーンするとうまく機能する場合があります。
ブルーノ

回答:


498

Stringのコンストラクターを見てください。

String str = new String(bytes, StandardCharsets.UTF_8);

そして、もしあなたが怠惰に感じているなら、Apache Commons IOライブラリを使用して、InputStreamを直接Stringに変換することができます:

String str = IOUtils.toString(inputStream, StandardCharsets.UTF_8);

13
または、1.7より古いJDKを使用している場合はGuavaのCharsets.UTF_8
siledh

6
19以下のAndroid APIを使用している場合は、GuavaのCharsets.UTF_8を使用してください
Ben Clayton

そして、checkstyleが「不正なインスタンス化:java.lang.Stringのインスタンス化は避けられるべきだ」と言った場合、何をしますか?
AttilaNeparáczki2014年

1
ここではjava.nio.charset.Charset.availableCharsets()、の文字セットだけでなく、すべての文字セットをマップで確認できますStandardCharsets。そして、他の文字セットを使用したいが、StringコンストラクタがスローされないようにしたいUnsupportedEncodingException場合は、次のように使用できますjava.nio.charset.Charset.forName()
nyxz

2
IOUtils.toString(inputStream、StandardCharsets.UTF_8)は非推奨になりました。
Aung Myat Hein 2016

41

Java Stringクラスには、バイト配列を文字列に変換するための組み込みコンストラクタがあります。

byte[] byteArray = new byte[] {87, 79, 87, 46, 46, 46};

String value = new String(byteArray, "UTF-8");

9

utf-8データを変換するために、バイトと文字間の1-1の対応を想定することはできません。これを試して:

String file_string = new String(bytes, "UTF-8");

(ええと、私は[回答を投稿]ボタンを押すのが遅い方法だと思います。)

ファイル全体を文字列として読み取るには、次のようにします。

public String openFileToString(String fileName) throws IOException
{
    InputStream is = new BufferedInputStream(new FileInputStream(fileName));

    try {
        InputStreamReader rdr = new InputStreamReader(is, "UTF-8");
        StringBuilder contents = new StringBuilder();
        char[] buff = new char[4096];
        int len = rdr.read(buff);
        while (len >= 0) {
            contents.append(buff, 0, len);
        }
        return buff.toString();
    } finally {
        try {
            is.close();
        } catch (Exception e) {
            // log error in closing the file
        }
    }
}

4

String(byte[] bytes) そのためのコンストラクタを使用できます。詳細については、このリンクを参照してください。 編集また、Java docに従って、プレートフォームのデフォルトの文字セットを考慮する必要があります。

プラットフォームのデフォルトの文字セットを使用して、指定されたバイト配列をデコードすることにより、新しいStringを構築します。新しい文字列の長さは文字セットの関数であるため、バイト配列の長さとは異なる場合があります。指定されたバイトがデフォルトの文字セットで有効でない場合のこのコンストラクタの動作は指定されていません。CharsetDecoderクラスは、デコードプロセスをさらに制御する必要がある場合に使用する必要があります。


1
また、バイトがプラットフォームのデフォルトの文字セットにない場合は、2番目のCharset引数を持つバージョンを使用して、変換が正しいことを確認できます。
Mike Daniels、2011

1
@MikeDaniels確かに、私はすべての詳細を含めたくありませんでした。私の答えを編集した
ばかり


2

UTF-8バイト配列を扱っていることがわかっているので、文字セット名を受け入れるStringコンストラクターを使用することは間違いありません。そうしないと、文字セットエンコーディングベースのセキュリティの脆弱性にさらされてしまう可能性があります。UnsupportedEncodingException処理する必要があるものをスローすることに注意してください。このようなもの:

public String openFileToString(String fileName) {
    String file_string;
    try {
        file_string = new String(_bytes, "UTF-8");
    } catch (UnsupportedEncodingException e) {
        // this should never happen because "UTF-8" is hard-coded.
        throw new IllegalStateException(e);
    }
    return file_string;
}

2

バイトで読み取って文字列を作成する単純化された関数を次に示します。これは、おそらくファイルのエンコーディングがわかっていることを前提としています(それ以外の場合はデフォルトです)。

static final int BUFF_SIZE = 2048;
static final String DEFAULT_ENCODING = "utf-8";

public static String readFileToString(String filePath, String encoding) throws IOException {

    if (encoding == null || encoding.length() == 0)
        encoding = DEFAULT_ENCODING;

    StringBuffer content = new StringBuffer();

    FileInputStream fis = new FileInputStream(new File(filePath));
    byte[] buffer = new byte[BUFF_SIZE];

    int bytesRead = 0;
    while ((bytesRead = fis.read(buffer)) != -1)
        content.append(new String(buffer, 0, bytesRead, encoding));

    fis.close();        
    return content.toString();
}

OPの質問に一致するようにデフォルトがutf-8になるように編集されたコード。
スコット2014年


0

これには反復も含まれますが、非常にコストがかかるため、文字列を連結するよりもはるかに優れています。

public String openFileToString(String fileName)
{
    StringBuilder s = new StringBuilder(_bytes.length);

    for(int i = 0; i < _bytes.length; i++)
    {
        s.append((char)_bytes[i]);
    }

    return s.toString();    
}

8
愛する主よ。String str = new String(byte[])うまくいきます。
zengr

3
これにより効率は向上しますが、utf8データは正しくデコードされません。
Ted Hopp、2011

0

get goから探しているものを取得して、バイトの配列の代わりにファイルから文字列を読み取ってみませんか?何かのようなもの:

BufferedReader in = new BufferedReader(new InputStreamReader( new FileInputStream( "foo.txt"), Charset.forName( "UTF-8"));

その後、それが完了するまでreadLineを実行します。


場合によっては、元の行区切り文字を保持しておくと便利です。OPはそれを望むかもしれません。
Bruno

0

私はこのように使用します

String strIn = new String(_bytes, 0, numBytes);


1
これは文字セットを指定しないため、UTF-8ではない可能性があるプラットフォームのデフォルト文字セットを取得します。
greg-449 2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.