UTF-8 바이트 []에서 문자열로


243

BufferedInputStreamUTF-8로 인코딩 된 텍스트 파일의 바이트를 바이트 배열로 읽는 데 방금 사용했다고 가정 해 봅시다 . 다음 루틴을 사용하여 바이트를 문자열로 변환 할 수 있지만 바이트를 반복하고 각 바이트를 변환하는 것보다 더 효율적이고 똑똑한 방법이 있습니까?

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

1
또는 BufferedReader를 사용하여 char 배열을 읽을 수 있습니다.
Andy Thomas


@CoolBeans 내가 할 수 있다면;) 감사합니다.
skeryl

파일 크기에 따라 전체 byte[]메모리를 로드하고 new String(_bytes,"UTF-8")(또는 +=문자열 에 청크를 통해) 변환하는 것이 가장 효율적 인지 확실하지 않습니다 . 입력 파일과 리더 연결은 특히 큰 파일에서 더 잘 작동 할 수 있습니다.
Bruno

답변:


498

String 의 생성자를보십시오

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

그리고 게으른 느낌이 든다면 Apache Commons IO 라이브러리를 사용하여 InputStream을 String으로 직접 변환 할 수 있습니다.

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

13
또는 구아바의 Charsets.UTF_8 ( JDK 1.7 이상인 경우)
siledh

6
19 이하의 Android API를 사용하는 경우 Guava의 Charsets.UTF_8을 사용하십시오
Ben Clayton

그리고 체크 스타일에 "잘못된 인스턴스화 : java.lang.String의 인스턴스화를 피해야합니다"라고 표시되어 있다면 무엇입니까?
Attila Neparáczki

1
여기에서 java.nio.charset.Charset.availableCharsets()의 캐릭터 셋뿐만 아니라 모든 캐릭터 셋을지도 에서 볼 수 있습니다 StandardCharsets. 그리고 당신은 다른 문자 집합을 사용하려면 여전히 던지기에서 문자열 생성자를 방지하려면 UnsupportedEncodingException당신이 사용할 수 있습니다java.nio.charset.Charset.forName()
nyxz

2
IOUtils.toString (inputStream, StandardCharsets.UTF_8)은 더 이상 사용되지 않습니다.
Aung Myat Hein

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");

(Bah. 답변 게시 버튼을 누르는 속도가 느리다는 것을 알았습니다.)

전체 파일을 문자열로 읽으려면 다음과 같이하십시오.

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에 따라 plateform의 기본 문자 세트를 고려해야합니다.

플랫폼의 기본 문자셋을 사용하여 지정된 바이트 배열을 디코딩하여 새 문자열을 구성합니다. 새 문자열의 길이는 문자 집합의 함수이므로 바이트 배열의 길이와 같지 않을 수 있습니다. 지정된 바이트가 디폴트 캐릭터 세트로 유효하지 않은 경우의이 생성자 동작은 지정되지 않습니다. 디코딩 프로세스에 대한 추가 제어가 필요한 경우 CharsetDecoder 클래스를 사용해야합니다.


1
바이트가 플랫폼의 기본 문자 집합에없는 경우 두 번째 Charset인수가 있는 버전을 사용 하여 변환이 올바른지 확인할 수 있습니다.
Mike Daniels

1
@MikeDaniels 실제로, 나는 모든 세부 사항을 포함하고 싶지 않았습니다. 방금 답변을 수정했습니다
GETah


2

UTF-8 바이트 배열을 처리한다는 것을 알고 있으므로 charset name을 허용하는 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로 설정하도록 코드를 편집했습니다.
scottt

1

String에는 byte [] 및 charsetname을 매개 변수로 사용하는 생성자가 있습니다. :)


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

0

get에서 원하는 것을 가져 와서 바이트 배열 대신 파일에서 문자열을 읽으십시오. 다음과 같은 것 :

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

그런 다음 끝날 때까지 라인을 읽습니다.


때로는 원래 줄 구분 기호를 유지하는 것이 유용합니다. OP가 원할 수도 있습니다.
Bruno

0

나는 이런 식으로 사용

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


1
이것은 문자 세트를 지정하지 않으므로 UTF-8이 아닌 플랫폼 기본 문자 세트를 얻습니다.
greg-449
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.