자바에서 문자열의 바이트


179

Java에서 String이 있으면 x해당 문자열의 바이트 수를 어떻게 계산할 수 있습니까?


15
문자열을 사용하여 HTTP 응답의 본문을 나타내고 크기를 사용하여 문자가 아닌 옥텟 / 바이트로 지정된 "Content-Length"헤더를 설정할 수 있습니다. w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.13
iX3

4
데이터베이스 열은 바이트 단위의 길이 제한이있을 수 있습니다 (예 : Oracle의 VARCHAR2 (4000 BYTE)). 원하는 인코딩에서 문자열의 바이트 수를 알고 문자열이 적합한 지 알 수 있습니다.
Somu

@ iX3 내가하려고했던 것과 정확히 동일합니다.
MC 황제

1
의도에 따라이 질문에 대한 두 가지 가능한 해석이 있다고 생각합니다. 하나는 "내 문자열이 사용하는 메모리 양"입니다. 이에 대한 대답은 아래 @roozbeh에서 제공합니다 (압축 OOPS와 같은 모듈로 VM 미묘 함). 다른 하나는 "문자열을 byte []로 변환하면 그 바이트 배열이 얼마나 많은 메모리를 사용합니까?"입니다. 이것이 Andrzej Doyle이 대답 한 질문입니다. 차이는 클 수 있습니다. UTF8의 "Hello World"는 11 바이트이지만 문자열 (@roozbeh 당)은 50 바이트입니다 (수학이 옳다면).
L. Blanc

11 바이트에는 byte [] 객체의 오버 헤드가 포함되어 있지 않으므로 비교가 다소 잘못되었습니다.
L. Blanc

답변:


289

문자열은 문자 목록입니다 (예 : 코드 포인트). 문자열을 나타내는 데 사용되는 바이트 수는 문자열 을 바이트로 변환하는 데 사용하는 인코딩에 전적으로 달려 있습니다 .

즉, 문자열을 바이트 배열로 바꾸고 다음과 같이 크기를 볼 수 있습니다.

// The input string for this test
final String string = "Hello World";

// Check length, in characters
System.out.println(string.length()); // prints "11"

// Check encoded sizes
final byte[] utf8Bytes = string.getBytes("UTF-8");
System.out.println(utf8Bytes.length); // prints "11"

final byte[] utf16Bytes= string.getBytes("UTF-16");
System.out.println(utf16Bytes.length); // prints "24"

final byte[] utf32Bytes = string.getBytes("UTF-32");
System.out.println(utf32Bytes.length); // prints "44"

final byte[] isoBytes = string.getBytes("ISO-8859-1");
System.out.println(isoBytes.length); // prints "11"

final byte[] winBytes = string.getBytes("CP1252");
System.out.println(winBytes.length); // prints "11"

따라서 간단한 "ASCII"문자열조차 사용되는 인코딩에 따라 표현에 다른 바이트 수를 가질 수 있습니다. 귀하의 사례에 관심있는 문자 세트를에 대한 인수로 사용하십시오 getBytes(). UTF-8이 모든 문자를 단일 바이트로 표현한다고 가정하는 함정에 빠지지 마십시오 .

final String interesting = "\uF93D\uF936\uF949\uF942"; // Chinese ideograms

// Check length, in characters
System.out.println(interesting.length()); // prints "4"

// Check encoded sizes
final byte[] utf8Bytes = interesting.getBytes("UTF-8");
System.out.println(utf8Bytes.length); // prints "12"

final byte[] utf16Bytes= interesting.getBytes("UTF-16");
System.out.println(utf16Bytes.length); // prints "10"

final byte[] utf32Bytes = interesting.getBytes("UTF-32");
System.out.println(utf32Bytes.length); // prints "16"

final byte[] isoBytes = interesting.getBytes("ISO-8859-1");
System.out.println(isoBytes.length); // prints "4" (probably encoded "????")

final byte[] winBytes = interesting.getBytes("CP1252");
System.out.println(winBytes.length); // prints "4" (probably encoded "????")

(문자 집합 인수를 제공하지 않으면 플랫폼의 기본 문자 집합 이 사용됩니다. 일부 상황에서는 유용 할 수 있지만 일반적으로 기본값에 의존하지 말고 인코딩 / 디코딩이 필요합니다.)


1
다시 getBytes ()를 사용하면 다시 x.length와 같은 길이를 줄 것입니다. 확실하지 않기 때문에 잘못되었습니다
Green

4
@Green Ash 바이트 배열의 길이 (getBytes ())와 x.length는 같을 수 있지만 보장 할 수는 없습니다. 모든 문자가 각각 단일 바이트로 표시되면 동일합니다. ISO-8859-1과 같이 문자 당 하나의 바이트 (또는 그 이하)를 사용하는 문자 인코딩의 경우 항상 적용됩니다. UTF-8은 1 또는 2 바이트를 사용하므로 문자열의 정확한 문자에 따라 다릅니다. 그런 다음 문자 당 항상 2 바이트를 사용하는 문자 인코딩이 있습니다.
Kris

나는 당신의 대답을 좋아합니다 :), 그래서 그들은 어떻게 든 같을 수도 있지만 항상 옳지는 않습니까? 그렇다면 매개 변수없이 메서드를 사용하면 오류가 발생하기 때문에 괜찮습니다!
Green

@Green 요점은 바이트 수 는 항상 문자 수와 같지 않다는 것 입니다. 바이트 수는 사용되는 문자 인코딩에 따라 다릅니다. 사용할 문자 인코딩을 알고이를 고려해야합니다. 어떤 오류가 발생합니까? 방금 사용 getBytes()하면 시스템의 기본 문자 인코딩이 사용됩니다.
Jesper

1
@KorayTugay 그렇습니다. 그래도 원인과 결과의 순서에 대해 논쟁 할 수 있습니다. char이 2 바이트 너비로 정의 된 기본 데이터 유형이기 때문에 char이 항상 2 바이트임을 진술하는 경향이 더 큽니다 . (그리고 UTF-16 표현은 다른 방식이 아니라 주로 이것의 결과였습니다.)
Andrzej Doyle

63

64 비트 참조로 실행중인 경우 :

sizeof(string) = 
8 + // object header used by the VM
8 + // 64-bit reference to char array (value)
8 + string.length() * 2 + // character array itself (object header + 16-bit chars)
4 + // offset integer
4 + // count integer
4 + // cached hash code

다시 말해:

sizeof(string) = 36 + string.length() * 2

압축 된 OOP (-XX : + UseCompressedOops)가있는 32 비트 VM 또는 64 비트 VM에서 참조는 4 바이트입니다. 따라서 총계는 다음과 같습니다.

sizeof(string) = 32 + string.length() * 2

문자열 객체에 대한 참조는 고려하지 않습니다.


6
질문은 String 객체의 메모리에 할당 된 바이트 수에 관한 것입니다. 다른 사람들이 지적했듯이 String을 직렬화하는 데 필요한 바이트 수에 관한 질문 인 경우 사용되는 인코딩에 따라 다릅니다.
roozbeh

2
귀하의 답변에 대한 출처? 감사합니다
mavis

1
참고 : sizeof8의 배수 여야합니다 .
dieter

19

pedantic 답변 (결과로 무엇을 하려는지에 따라 가장 유용한 것은 아니지만)는 다음과 같습니다.

string.length() * 2

Java 문자열은 UTF-16BE코드 단위로 2 바이트를 사용하는 인코딩에 실제로 저장되며 String.length()UTF-16 코드 단위로 길이를 측정하므로 다음과 같습니다.

final byte[] utf16Bytes= string.getBytes("UTF-16BE");
System.out.println(utf16Bytes.length);

그리고 이것은 내부 char배열 의 크기를 바이트 단위로 알려줍니다 .

참고 : 이전 인코딩이 배열 길이에 2 바이트를 추가 하여 BOM 을 삽입 할 때와 "UTF-16"다른 결과가 제공 됩니다."UTF-16BE"


Roozbeh의 대답은 다른 바이트도 고려하기 때문에 더 좋습니다.
Lodewijk Bogaards

@finnw 인코딩이 UTF-16이 아닌 UTF-16BE인지 확인 하시겠습니까? String 클래스 Javadoc ( docs.oracle.com/javase/6/docs/api/java/lang/String.html )에 따르면 "문자열은 UTF-16 형식의 문자열을 나타냅니다 ..."
entpnerd

17

Java에서 문자열을 UTF8 바이트 배열로 변환하는 방법에 따르면 :

String s = "some text here";
byte[] b = s.getBytes("UTF-8");
System.out.println(b.length);

그러나 코드를 컴파일 할 때 실례합니다. 오류가 발생합니다. 빈 매개 변수를 전달하면 x.length와 동일한 길이를 제공합니다. 나는 개념을 오해한다. 도와주세요
Green

@Green Ash, 어떤 Java 버전이 있습니까?
Buhake Sindi

@ 그린 애쉬, 어떤 예외가 있습니까?
Buhake Sindi

2
분명히 이것은 출력입니다. test.java:11 :보고되지 않은 예외 java.io.UnsupportedEncodingException; 던져 질 수 있도록 잡히거나 선언되어야한다 byte [] b = s.getBytes ( "UTF-8"); ^ 1 오류 프로세스가 완료되었습니다.
Green

3
@Green, 시도 : s.getBytes(Charset.forName("UTF-8")).
james.garriss

10

String인스턴스 메모리 바이트의 특정 량을 할당한다. 아마도 sizeof("Hello World")데이터 구조 자체에 의해 할당 된 바이트 수를 반환하는 것을 찾고 있습니까?

Java에서는 sizeof데이터 구조를 저장하기 위해 메모리를 할당하지 않으므로 일반적으로 함수 가 필요 하지 않습니다. String.java대략적인 추정을 위해 파일을 살펴볼 수 있으며 'int', 일부 참조 및 a를 볼 수 char[]있습니다. Java 언어 사양 을 정의는 것으로 char0 ~ 65535 범위는, 그래서 2 바이트 메모리에 하나의 문자를 유지하기에 충분합니다. 그러나 JVM은 하나의 문자를 2 바이트로 저장할 필요가 없으며, 구현시 char정의 범위의 값을 보유 할 수 있음을 보장해야합니다 .

따라서 sizeof실제로 Java에서는 의미가 없습니다. 그러나 우리가 큰 문자열과 하나를 가지고 있다고 가정하면char 2 바이트를 할당String 객체 의 메모리 공간은 적어도 2 * str.length()바이트입니다.


7

getBytes () 라는 메소드가 있습니다 . 현명하게 사용하십시오.


17
현명하게 = 문자 집합 매개 변수가없는 것을 사용하지 마십시오.
Thilo

왜? UTF8 인코딩으로 실행되도록 환경을 구성하면 이것이 문제입니까?
ziggy

1
getBytes는 또한 바이트 배열을 생성하고 복사하므로 긴 문자열을 말하면이 작업에 많은 비용이들 수 있습니다.
ticktock

@ticktock, 여전히 주변에 있다면, 그래도 대안은 무엇입니까? 필요한 스토리지를 반환하기 위해 라이브러리 함수가 필요하므로 큰 할당으로 결합 할 수 있습니다.
SensorSmith

4

이 시도 :

Bytes.toBytes(x).length

x를 선언하고 초기화했다고 가정


3
이 표준 Java 라이브러리의 일부입니까? Bytes수업을 찾을 수 없습니다 .
Kröw

0

캐치 시도를 피하려면 다음을 사용하십시오.

String s = "some text here";
byte[] b = s.getBytes(StandardCharsets.UTF_8);
System.out.println(b.length);
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.