UTF-8 byte [] ke String

243

Misalkan saya baru saja menggunakan a BufferedInputStreamuntuk membaca byte dari file teks yang dikodekan UTF-8 ke dalam array byte. Saya tahu bahwa saya dapat menggunakan rutin berikut untuk mengkonversi byte ke string, tetapi apakah ada cara yang lebih efisien / lebih pintar untuk melakukan ini daripada hanya iterasi melalui byte dan mengkonversi masing-masing?

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

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

    return file_string;    
}
Skeryl
sumber
17
Kenapa kamu tidak bisa melakukan ini saja String fileString = new String(_bytes,"UTF-8");?
CoolBeans
1
Atau, Anda bisa menggunakan BufferedReader untuk membaca ke dalam array char.
Andy Thomas
@ CoolBeans saya bisa jika saya tahu melakukan itu;) Terima kasih.
skeryl
Bergantung pada ukuran file, saya tidak yakin memuat keseluruhan byte[]dalam memori dan mengubahnya melalui new String(_bytes,"UTF-8")(atau bahkan dengan potongan +=pada string) adalah yang paling efisien. Chaining InputStreams dan Readers mungkin bekerja lebih baik, terutama pada file besar.
Bruno

Jawaban:

498

Lihatlah konstruktor untuk String

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

Dan jika Anda merasa malas, Anda dapat menggunakan pustaka Apache Commons IO untuk mengonversi InputStream menjadi sebuah String secara langsung:

String str = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
Jason Nichols
sumber
13
Atau Charsets Guava.UTF_8 jika Anda menggunakan JDK lebih dari 1,7
siledh
6
Gunakan Guava's Charsets.UTF_8 jika Anda juga menggunakan Android API di bawah 19
Ben Clayton
Dan jika checkstyle mengatakan: "Instansiasi Ilegal: Instansiasi java.lang.String harus dihindari.", Lalu apa?
Attila Neparáczki
1
Anda dapat melihat di sini java.nio.charset.Charset.availableCharsets()peta semua rangkaian karakter, bukan hanya rangkaian karakter di StandardCharsets. Dan jika Anda ingin menggunakan beberapa charset lain dan masih ingin mencegah konstruktor String dari melempar UnsupportedEncodingExceptionAnda dapat menggunakanjava.nio.charset.Charset.forName()
nyxz
2
IOUtils.toString (inputStream, StandardCharsets.UTF_8) sudah tidak digunakan lagi sekarang.
Aung Myat Hein
41

Kelas Java String memiliki built-in-constructor untuk mengkonversi array byte ke string.

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

String value = new String(byteArray, "UTF-8");
Kashif Khan
sumber
9

Untuk mengonversi data utf-8, Anda tidak dapat mengasumsikan korespondensi 1-1 antara byte dan karakter. Coba ini:

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

(Bah. Saya mengerti, saya cara memperlambat dalam menekan tombol Post Your Answer.)

Untuk membaca seluruh file sebagai String, lakukan sesuatu seperti ini:

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
        }
    }
}
Ted Hopp
sumber
4

Anda dapat menggunakan String(byte[] bytes) konstruktor untuk itu. Lihat tautan ini untuk detailnya. EDIT Anda juga harus mempertimbangkan charset default plateform Anda sesuai java doc:

Bangun String baru dengan mendekode array byte yang ditentukan menggunakan charset default platform. Panjang String baru adalah fungsi charset, dan karenanya mungkin tidak sama dengan panjang array byte. Perilaku konstruktor ini ketika byte yang diberikan tidak valid dalam charset default tidak ditentukan. Kelas CharsetDecoder harus digunakan ketika kontrol lebih besar atas proses decoding diperlukan.

GETah
sumber
1
Dan jika byte Anda tidak ada di charset default platform, Anda dapat menggunakan versi yang memiliki Charsetargumen kedua untuk memastikan konversi sudah benar.
Mike Daniels
1
@MikeDaniels Memang, saya tidak ingin memasukkan semua detail. Baru saja mengedit jawaban saya
GETah
2

Anda dapat menggunakan metode yang dijelaskan dalam pertanyaan ini (terutama karena Anda memulai dengan InputStream): Baca / konversi InputStream ke String

Secara khusus, jika Anda tidak ingin bergantung pada pustaka eksternal, Anda dapat mencoba jawaban ini , yang membaca InputStreamvia an InputStreamReaderke char[]buffer dan menambahkannya ke a StringBuilder.

Bruno
sumber
2

Mengetahui bahwa Anda berurusan dengan array byte UTF-8, Anda pasti ingin menggunakan konstruktor String yang menerima nama charset . Kalau tidak, Anda dapat membiarkan diri Anda terbuka untuk beberapa kerentanan keamanan berbasis pengkodean charset. Perhatikan bahwa ia melempar UnsupportedEncodingExceptionyang harus Anda tangani. Sesuatu seperti ini:

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;
}
Asaf
sumber
2

Inilah fungsi yang disederhanakan yang akan membaca dalam byte dan membuat string. Ini mengasumsikan Anda mungkin sudah tahu di mana penyandian file (dan jika tidak, default).

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();
}
scottt
sumber
Kode diedit untuk menjadikan default utf-8 agar cocok dengan pertanyaan OP.
scottt
1

String memiliki konstruktor yang menggunakan byte [] dan charsetname sebagai parameter :)

cek jiwa
sumber
0

Ini juga melibatkan iterasi, tetapi ini jauh lebih baik daripada merangkai string karena mereka sangat sangat mahal.

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();    
}
pembual
sumber
8
Tuanku sayang. String str = new String(byte[])akan baik-baik saja.
zengr
3
Ini meningkatkan efisiensi, tetapi tidak mendekode data utf8 dengan benar.
Ted Hopp
0

Mengapa tidak mendapatkan apa yang Anda cari dari memulai dan membaca string dari file alih-alih array byte? Sesuatu seperti:

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

lalu bacaLine dari dalam sampai selesai.

digitaljoel
sumber
Terkadang, berguna untuk menjaga pembatas garis asli. OP mungkin menginginkan itu.
Bruno
0

Saya menggunakan cara ini

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

Anatoliy Pelepetz
sumber
1
Ini tidak menentukan set karakter sehingga Anda mendapatkan set karakter default platform yang mungkin bukan UTF-8.
greg-449