Es posible que desee usar una cadena para representar el cuerpo de una respuesta HTTP y usar el tamaño para establecer el encabezado "Content-Length", que se especifica en octetos / bytes, no en caracteres. w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.13
iX3
44
Una columna de base de datos puede tener restricción de longitud en bytes, por ejemplo, VARCHAR2 (4000 BYTE) en Oracle. Es posible que desee saber el recuento de bytes de una cadena en la codificación deseada para saber si la cadena encajaría.
Somu
@ iX3 Exactamente lo mismo que estaba tratando de hacer.
MC Emperor
1
Creo que hay dos posibles interpretaciones de esta pregunta, dependiendo de la intención: una es "¿cuánta memoria usa mi String?". La respuesta a eso la proporciona @roozbeh a continuación (tal vez sutilezas de módulo VM como OOPS comprimido). La otra es, "si convierto la cadena a un byte [], ¿cuánta memoria usaría esa matriz de bytes?". Esta es la pregunta que responde Andrzej Doyle. La diferencia puede ser grande: "Hello World" en UTF8 es de 11 bytes, pero la Cadena (por @roozbeh) es de 50 bytes (si mis cálculos son correctos).
L. Blanc
Debería haber agregado que los 11 bytes no incluyen la sobrecarga del objeto byte [] que los contiene, por lo que la comparación es algo engañosa.
L. Blanc
Respuestas:
289
Una cadena es una lista de caracteres (es decir, puntos de código). La cantidad de bytes que se toman para representar la cadena depende completamente de la codificación que use para convertirla en bytes .
Dicho esto, puede convertir la cadena en una matriz de bytes y luego ver su tamaño de la siguiente manera:
// The input string for this testfinalString string ="Hello World";// Check length, in charactersSystem.out.println(string.length());// prints "11"// Check encoded sizesfinalbyte[] utf8Bytes = string.getBytes("UTF-8");System.out.println(utf8Bytes.length);// prints "11"finalbyte[] utf16Bytes= string.getBytes("UTF-16");System.out.println(utf16Bytes.length);// prints "24"finalbyte[] utf32Bytes = string.getBytes("UTF-32");System.out.println(utf32Bytes.length);// prints "44"finalbyte[] isoBytes = string.getBytes("ISO-8859-1");System.out.println(isoBytes.length);// prints "11"finalbyte[] winBytes = string.getBytes("CP1252");System.out.println(winBytes.length);// prints "11"
Como puede ver, incluso una cadena simple "ASCII" puede tener un número diferente de bytes en su representación, dependiendo de la codificación utilizada. Utilice el conjunto de caracteres que le interese para su caso, como argumento para getBytes(). Y no caigas en la trampa de asumir que UTF-8 representa a cada personaje como un solo byte, ya que eso tampoco es cierto:
finalString interesting ="\uF93D\uF936\uF949\uF942";// Chinese ideograms// Check length, in charactersSystem.out.println(interesting.length());// prints "4"// Check encoded sizesfinalbyte[] utf8Bytes = interesting.getBytes("UTF-8");System.out.println(utf8Bytes.length);// prints "12"finalbyte[] utf16Bytes= interesting.getBytes("UTF-16");System.out.println(utf16Bytes.length);// prints "10"finalbyte[] utf32Bytes = interesting.getBytes("UTF-32");System.out.println(utf32Bytes.length);// prints "16"finalbyte[] isoBytes = interesting.getBytes("ISO-8859-1");System.out.println(isoBytes.length);// prints "4" (probably encoded "????")finalbyte[] winBytes = interesting.getBytes("CP1252");System.out.println(winBytes.length);// prints "4" (probably encoded "????")
(Tenga en cuenta que si no proporciona un argumento de juego de caracteres, se usa el juego de caracteres predeterminado de la plataforma . Esto puede ser útil en algunos contextos, pero en general debe evitar depender de los valores predeterminados y siempre usar un juego de caracteres explícito al codificar / Se requiere decodificación.)
así que de nuevo si uso getBytes (). me dará la misma longitud que x.length estoy equivocado porque no estoy seguro
Verde
44
@Green Ash La longitud de la matriz de bytes - getBytes () - y x.length PUEDEN ser igual pero no se garantiza que lo sea. Será igual si todos los caracteres están representados por un solo byte cada uno. Esto siempre será válido para las codificaciones de caracteres que usan un solo byte por carácter (o menos), como ISO-8859-1. UTF-8 usa 1 o 2 bytes, por lo que depende de los caracteres exactos en la cadena. Luego están las codificaciones de caracteres que siempre usan dos bytes por carácter.
Kris
me gusta tu respuesta :), por lo que de alguna manera podrían ser las mismas, pero no siempre estoy en lo cierto. ok, entonces está bien usar el método sin el parámetro porque me causa un error !!
Verde
@Verde el punto es que el número de bytes no siempre es igual al número de caracteres . El número de bytes depende de la codificación de caracteres que se utiliza. Tendrá que saber qué codificación de caracteres utilizará y tenerlo en cuenta. ¿Qué error estás recibiendo? Si solo lo usa getBytes(), usará la codificación de caracteres predeterminada de su sistema.
Jesper
1
@KorayTugay Sí, más o menos. Sin embargo, podría discutir sobre el orden de causa y efecto. Me inclinaría más a decir que un carácter siempre tiene 2 bytes porque es un tipo de datos primitivo definido para tener 2 bytes de ancho. (Y que la representación de UTF-16 fue principalmente una consecuencia de esto, y no al revés.)
Andrzej Doyle
63
Si está ejecutando con referencias de 64 bits:
sizeof(string)=8+// object header used by the VM8+// 64-bit reference to char array (value)8+ string.length()*2+// character array itself (object header + 16-bit chars)4+// offset integer4+// count integer4+// cached hash code
En otras palabras:
sizeof(string)=36+ string.length()*2
En una máquina virtual de 32 bits o una máquina virtual de 64 bits con OOP comprimidos (-XX: + UseCompressedOops), las referencias son de 4 bytes. Entonces el total sería:
sizeof(string)=32+ string.length()*2
Esto no tiene en cuenta las referencias al objeto de cadena.
Asumí que la pregunta era sobre el número de bytes asignados en la memoria para un objeto String. Si la pregunta es sobre el número de bytes necesarios para serializar la Cadena, como han señalado otros, depende de la codificación utilizada.
roozbeh
2
Fuente de su respuesta? Gracias
mavis
1
Nota: sizeofdebe ser múltiplo de 8.
Dieter
19
La respuesta pedante (aunque no necesariamente la más útil, dependiendo de lo que quieras hacer con el resultado) es:
string.length()*2
Las cadenas de Java se almacenan físicamente en la UTF-16BEcodificación, que utiliza 2 bytes por unidad de código, y String.length()mide la longitud en unidades de código UTF-16, por lo que esto es equivalente a:
Y esto le dirá el tamaño de la charmatriz interna , en bytes .
Nota: "UTF-16"dará un resultado diferente "UTF-16BE"ya que la codificación anterior insertará una lista de materiales , agregando 2 bytes a la longitud de la matriz.
La respuesta de Roozbeh es mejor, porque también tiene en cuenta los otros bytes.
Lodewijk Bogaards
@finnw ¿Está seguro de que la codificación es UTF-16BE y no UTF-16? De acuerdo con la clase String Javadoc ( docs.oracle.com/javase/6/docs/api/java/lang/String.html ), "Una cadena representa una cadena en el formato UTF-16 ...".
pero discúlpeme cuando compilo su código, me da un error; debido al parámetro "UTF-8". Cuando paso un parámetro vacío, me da la misma longitud que x.length. No entiendo el concepto. ayuda por favor
Verde
@ Green Ash, ¿qué versión de Java tienes?
Buhake Sindi
@ Green Ash, ¿qué excepción estás recibiendo?
Buhake Sindi
2
para que quede claro, esta es la salida: test.java:11: excepción no notificada java.io.UnsupportedEncodingException; debe ser capturado o declarado para ser lanzado byte [] b = s.getBytes ("UTF-8"); ^ 1 error Proceso completado.
Una Stringinstancia asigna una cierta cantidad de bytes en la memoria. ¿Quizás esté viendo algo como sizeof("Hello World")lo que devolvería el número de bytes asignados por la estructura de datos en sí?
En Java, generalmente no hay necesidad de una sizeoffunción, porque nunca asignamos memoria para almacenar una estructura de datos. Podemos echar un vistazo al String.javaarchivo para una estimación aproximada, y vemos algunos 'int', algunas referencias y a char[]. La especificación del lenguaje Java define que un charrango va de 0 a 65535, por lo que dos bytes son suficientes para mantener un único carácter en la memoria. Pero una JVM no tiene que almacenar un carácter en 2 bytes, solo tiene que garantizar que la implementación de charpuede contener valores del rango definido.
Entonces sizeofrealmente no tiene ningún sentido en Java. Pero, suponiendo que tenemos una cadena grande y una charasigna dos bytes, la huella de memoria de un Stringobjeto es al menos 2 * str.length()en bytes.
Sabiamente = no uses el que no tenga un parámetro de juego de caracteres.
Thilo
¿Por qué? ¿Es este un problema si configuro mi entorno para que se ejecute con codificación UTF8?
ziggy
1
getBytes también creará y copiará la matriz de bytes, por lo que si está hablando de cadenas largas, esta operación podría ser costosa.
ticktock
@ticktock, si todavía estás cerca, sí, pero ¿cuál es la alternativa? Llegué esperando que una función de biblioteca devolviera el almacenamiento necesario para poder combinarlo en una asignación más grande.
Respuestas:
Una cadena es una lista de caracteres (es decir, puntos de código). La cantidad de bytes que se toman para representar la cadena depende completamente de la codificación que use para convertirla en bytes .
Dicho esto, puede convertir la cadena en una matriz de bytes y luego ver su tamaño de la siguiente manera:
Como puede ver, incluso una cadena simple "ASCII" puede tener un número diferente de bytes en su representación, dependiendo de la codificación utilizada. Utilice el conjunto de caracteres que le interese para su caso, como argumento para
getBytes()
. Y no caigas en la trampa de asumir que UTF-8 representa a cada personaje como un solo byte, ya que eso tampoco es cierto:(Tenga en cuenta que si no proporciona un argumento de juego de caracteres, se usa el juego de caracteres predeterminado de la plataforma . Esto puede ser útil en algunos contextos, pero en general debe evitar depender de los valores predeterminados y siempre usar un juego de caracteres explícito al codificar / Se requiere decodificación.)
fuente
getBytes()
, usará la codificación de caracteres predeterminada de su sistema.Si está ejecutando con referencias de 64 bits:
En otras palabras:
En una máquina virtual de 32 bits o una máquina virtual de 64 bits con OOP comprimidos (-XX: + UseCompressedOops), las referencias son de 4 bytes. Entonces el total sería:
Esto no tiene en cuenta las referencias al objeto de cadena.
fuente
sizeof
debe ser múltiplo de 8.La respuesta pedante (aunque no necesariamente la más útil, dependiendo de lo que quieras hacer con el resultado) es:
Las cadenas de Java se almacenan físicamente en la
UTF-16BE
codificación, que utiliza 2 bytes por unidad de código, yString.length()
mide la longitud en unidades de código UTF-16, por lo que esto es equivalente a:Y esto le dirá el tamaño de la
char
matriz interna , en bytes .Nota:
"UTF-16"
dará un resultado diferente"UTF-16BE"
ya que la codificación anterior insertará una lista de materiales , agregando 2 bytes a la longitud de la matriz.fuente
De acuerdo con Cómo convertir cadenas hacia y desde matrices de bytes UTF8 en Java :
fuente
s.getBytes(Charset.forName("UTF-8"))
.Una
String
instancia asigna una cierta cantidad de bytes en la memoria. ¿Quizás esté viendo algo comosizeof("Hello World")
lo que devolvería el número de bytes asignados por la estructura de datos en sí?En Java, generalmente no hay necesidad de una
sizeof
función, porque nunca asignamos memoria para almacenar una estructura de datos. Podemos echar un vistazo alString.java
archivo para una estimación aproximada, y vemos algunos 'int', algunas referencias y achar[]
. La especificación del lenguaje Java define que unchar
rango va de 0 a 65535, por lo que dos bytes son suficientes para mantener un único carácter en la memoria. Pero una JVM no tiene que almacenar un carácter en 2 bytes, solo tiene que garantizar que la implementación dechar
puede contener valores del rango definido.Entonces
sizeof
realmente no tiene ningún sentido en Java. Pero, suponiendo que tenemos una cadena grande y unachar
asigna dos bytes, la huella de memoria de unString
objeto es al menos2 * str.length()
en bytes.fuente
Hay un método llamado getBytes () . Úsalo con sabiduría .
fuente
Prueba esto :
Asumiendo que declaraste e inicializaste x antes
fuente
Bytes
clase.Para evitar intentar atrapar, use:
fuente