UTF-8 byte [] thành Chuỗi


243

Giả sử tôi vừa sử dụng a BufferedInputStreamđể đọc các byte của tệp văn bản được mã hóa UTF-8 thành một mảng byte. Tôi biết rằng tôi có thể sử dụng thói quen sau đây để chuyển đổi các byte thành một chuỗi, nhưng có cách nào hiệu quả hơn / thông minh hơn để thực hiện việc này hơn là chỉ lặp qua các byte và chuyển đổi từng byte không?

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
Tại sao bạn không thể làm điều này String fileString = new String(_bytes,"UTF-8");?
CoolBeans

1
Ngoài ra, bạn có thể sử dụng BufferedReader để đọc thành một mảng char.
Andy Thomas


@CoolBeans Tôi có thể nếu tôi biết làm điều đó;) Cảm ơn bạn.
skeryl

Tùy thuộc vào kích thước tệp, tôi không chắc chắn tải toàn bộ byte[]trong bộ nhớ và chuyển đổi nó qua new String(_bytes,"UTF-8")(hoặc thậm chí bằng các đoạn có +=trên chuỗi) là hiệu quả nhất. Chaining InputStreams và Reader có thể hoạt động tốt hơn, đặc biệt là trên các tệp lớn.
Bruno

Câu trả lời:


498

Nhìn vào hàm tạo cho String

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

Và nếu bạn cảm thấy lười biếng, bạn có thể sử dụng thư viện IO Commons IO để chuyển trực tiếp InputStream thành Chuỗi:

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

13
Hoặc Guava's Charsets.UTF_8 nếu bạn đang ở trên JDK cũ hơn 1.7
siledh

6
Sử dụng Guava's Charsets.UTF_8 nếu bạn cũng sử dụng API Android dưới 19
Ben Clayton

Và nếu checkstyle nói: "Khởi tạo bất hợp pháp: Khởi tạo java.lang.String nên tránh.", Thì sao?
Attila Neparáczki

1
Bạn có thể thấy ở đây java.nio.charset.Charset.availableCharsets()bản đồ tất cả các bộ ký tự không chỉ các bộ ký tự trong StandardCharsets. Và nếu bạn muốn sử dụng một số bộ ký tự khác và vẫn muốn ngăn trình xây dựng Chuỗi ném, UnsupportedEncodingExceptionbạn có thể sử dụngjava.nio.charset.Charset.forName()
nyxz 15/2/2015

2
IOUtils.toString (inputStream, StandardCharsets.UTF_8) hiện không được chấp nhận.
Aung Myat Hein

41

Lớp Chuỗi Java có một hàm tạo dựng sẵn để chuyển đổi mảng byte thành chuỗi.

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

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

9

Để chuyển đổi dữ liệu utf-8, bạn không thể giả sử sự tương ứng 1-1 giữa các byte và ký tự. Thử cái này:

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

(Bah. Tôi thấy tôi có cách chậm để nhấn nút Đăng câu trả lời của bạn.)

Để đọc toàn bộ tệp dưới dạng Chuỗi, hãy thực hiện như sau:

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

Bạn có thể sử dụng hàm String(byte[] bytes) tạo cho điều đó. Xem liên kết này để biết chi tiết. EDIT Bạn cũng phải xem xét bộ ký tự mặc định của biểu mẫu của bạn theo tài liệu java:

Xây dựng một Chuỗi mới bằng cách giải mã mảng byte được chỉ định bằng bộ ký tự mặc định của nền tảng. Độ dài của Chuỗi mới là một hàm của bộ ký tự và do đó có thể không bằng độ dài của mảng byte. Hành vi của hàm tạo này khi các byte đã cho không hợp lệ trong bộ ký tự mặc định là không xác định. Lớp CharsetDecoder nên được sử dụng khi cần kiểm soát nhiều hơn quá trình giải mã.


1
Và nếu byte của bạn không có trong bộ ký tự mặc định của nền tảng, bạn có thể sử dụng phiên bản có Charsetđối số thứ hai để đảm bảo chuyển đổi là chính xác.
Mike Daniels

1
@MikeDaniels Thật vậy, tôi không muốn bao gồm tất cả các chi tiết. Chỉ cần chỉnh sửa câu trả lời của tôi
GETah


2

Biết rằng bạn đang xử lý một mảng byte UTF-8, chắc chắn bạn sẽ muốn sử dụng hàm tạo Chuỗi chấp nhận tên bộ ký tự . Nếu không, bạn có thể để mình mở cho một số lỗ hổng bảo mật dựa trên mã hóa bộ ký tự. Lưu ý rằng nó ném UnsupportedEncodingExceptionmà bạn sẽ phải xử lý. Một cái gì đó như thế này:

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

Đây là một hàm đơn giản hóa sẽ đọc theo byte và tạo một chuỗi. Nó giả định rằng bạn có thể đã biết mã hóa tệp trong đó (và nếu không thì mặc định).

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();
}

Mã được chỉnh sửa để làm mặc định là utf-8 để phù hợp với câu hỏi của OP.
scottt


0

Điều này cũng liên quan đến việc lặp lại, nhưng điều này tốt hơn nhiều so với việc nối các chuỗi vì chúng rất rất tốn kém.

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
Chúa ơi. String str = new String(byte[])sẽ làm tốt thôi
zengr

3
Điều này cải thiện hiệu quả, nhưng nó không giải mã dữ liệu utf8 đúng cách.
Ted Hopp

0

Tại sao không nhận được những gì bạn đang tìm kiếm từ việc di chuyển và đọc một chuỗi từ tệp thay vì một mảng byte? Cái gì đó như:

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

sau đó đọcLine từ trong cho đến khi hoàn thành.


Đôi khi, thật hữu ích để giữ các dấu phân cách dòng gốc. OP có thể muốn điều đó.
Bruno

0

Tôi dùng cách này

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


1
Điều này không chỉ định một bộ ký tự để bạn có được bộ ký tự mặc định của nền tảng có thể không phải là UTF-8.
greg-449
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.