Java에서 문자열을 UTF8 바이트 배열과 변환하는 방법


239

Java에는 String이 있으며 바이트 배열 (UTF8 또는 다른 인코딩)로 인코딩하려고합니다. 또는 바이트 배열 (일부 알려진 인코딩)이 있으며 Java 문자열로 변환하려고합니다. 이러한 전환은 어떻게합니까?

답변:


355

문자열에서 바이트 []로 변환 :

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

물론 올바른 인코딩 이름을 사용해야합니다. 필자의 예제는 가장 일반적인 두 가지 인코딩 인 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

7
@Pacerier 문자 세트에 대한 문서 가 표준 문자 세트 중 하나로 "UTF-8"을 나열 하기 때문 입니다. 나는 당신의 철자법도 받아 들여 졌다고 믿지만 나는 문서의 말과 함께 갔다.
mcherm

20
JDK7

95

다음은 모든 전환에 대해 Charset 조회를 수행하지 않는 솔루션입니다.

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 : 성능 차이가 작더라도 가능하면 문자열 형식보다 객체 (문자셋, URL 등)를 사용하는 것이 좋습니다.
Bart van Heukelom

7
참고 : "1.6부터"public String (byte [] bytes, Charset charset)
leo

1
"모든 전환에 대해 Charset 조회를 수행하지 마십시오"와 관련하여 소스를 인용 해주세요. java.nio.charset.Charset 이 String.getBytes 위에 빌드되지 않았 으므로 String.getBytes보다 오버 헤드가 더 많습니까?
Pacerier

2
docs do 상태 : "이 문자열을 지정된 문자 집합으로 인코딩 할 수없는 경우이 메서드의 동작은 지정되지 않았습니다. 인코딩 프로세스에 대한 추가 제어가 필요한 경우 CharsetEncoder 클래스를 사용해야합니다."
paiego 2016 년

24
참고 : Java 1.7부터 StandardCharsets.UTF_8UTF-8 문자 세트에 지속적으로 액세스 할 수 있습니다 .
Kat

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

감사! 다른 전환 방향을 추가하여 직접 작성했습니다.
mcherm

1
@smink 대시는 선택 사항이 아닙니다. 이것은 "UTF-8"을 사용해야합니다
Mel Nicholson

14

String (byte [], String) 생성자 및 getBytes (String) 메소드 를 통해 직접 변환 할 수 있습니다 . Java는 Charset 클래스 를 통해 사용 가능한 문자 세트를 제공합니다 . JDK 문서 에는 지원되는 인코딩이 나열되어 있습니다.

시간의 90 %, 이러한 변환은 스트림에서 수행되므로 Reader / Writer 클래스를 사용합니다 . 임의의 바이트 스트림에서 String 메소드를 사용하여 점진적으로 디코딩하지는 않습니다. 멀티 바이트 문자와 관련된 버그가 발생할 수 있습니다.


정교하게 할 수 있습니까? 내 응용 프로그램이에서 문자열을 인코딩 및 디코딩하는 경우 UTF-8멀티 바이트 문자와 관련된 문제는 무엇입니까?
raffian

@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부터 and 같은 문자 세트 이름에 상수를 사용할 수 있습니다 StandardCharSets.ISO_8859_1.
Basil Bourque 2016 년

위에서 언급 한 첫 번째 솔루션에서 절대적으로 잘 작동하여 하루를 절약했습니다.
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
Commons Lang이 아닌 Commons Codec 의이 StringUtils에 유의하십시오 .
Arend v. Reinersdorff

예, 약간의 문제가 있습니다! Gradle, Maven 사용자 : "commons-codec : commons-codec : 1.10" (작성시) 예를 들어 이것은 Apache POI와의 종속성으로 번들로 제공됩니다. 아파치 커먼즈를 제외하고는 구출을 위해!
마이크 설치류

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 개 유니 코드 문자의 것을 확신 할 수 있습니다 다음이 코드 것 또한 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);

String Entity는 'query'를 utf-8로 변환합니까, 아니면 엔티티를 연결할 때 기억합니까?
SyntaxRules

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
첫째, 변환이 아닙니다 : 인쇄 할 수없는 바이트를 제거하는 것입니다. 둘째, 기본 OS의 기본 인코딩은 실제로 인쇄 가능한 문자의 ASCII를 기반으로한다고 가정합니다 (예 : EBCDIC를 사용하는 IBM 메인 프레임에서는 작동하지 않음).
Isaac Isaac
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.