2012-03-22 68 views
7

Hola chicos: me sorprendió al descubrir que el siguiente códigoJava: tamaño de byte de cadena de caracteres Char versus.

System.out.println("Character size:"+Character.SIZE/8); 
System.out.println("String size:"+"a".getBytes().length); 

Muestra esto:

Tamaño de caracteres: 2

tamaño de la secuencia: 1

lo haría Supongamos que una cadena de caracteres única debe ocupar el mismo (o más) bytes que un solo carácter.

En particular im pregunto ---

Si tengo un bean Java con varios campos en él, cómo su tamaño aumentará dependiendo de la naturaleza de los campos (Carácter, cadena, booleano, vectorial, etc. ..) Supongo que todos los objetos de Java tienen una huella (probablemente mínima) y que una de las más pequeñas de estas huellas sería un solo carácter. Entonces ... Para probar esa suposición básica comencé con el código anterior, y los resultados de las declaraciones impresas parecen contradictorios.

Cualquier idea sobre la forma en que java almacena/serializa caracteres frente a cadenas de forma predeterminada sería muy útil ... gracias.

+5

La longitud de una cadena es el número de caracteres que contiene. Un personaje puede codificarse en más de un byte. – Oded

+4

La cadena probablemente está codificada en UTF-8, por lo que la "a" toma solo un byte. –

+4

[El mínimo absoluto de cada desarrollador de software Absolutamente, definitivamente debe saber acerca de Unicode y juegos de caracteres (Sin excusas!)] (Http://www.joelonsoftware.com/articles/Unicode.html) – Oded

Respuesta

10

getBytes() genera String con la codificación predeterminada (lo más probable es ISO-8859-1) mientras que el carácter de caracteres interno siempre tiene 2 bytes. Internamente, Java usa matrices siempre con carácter de 2 bytes, si desea obtener más información sobre la codificación, lea el enlace de Oded en los comentarios de la pregunta.

+3

Como referencia, 'getBytes()' en realidad no te dice el consumo real de memoria de 'String'. –

+0

No creo que esta afirmación tuya sea correcta: "Internamente Java usa matrices siempre con un carácter de 2 bytes". Puede ver este enlace: http://javarevisited.blogspot.com.tr/2012/01/get-set-default-character-encoding.html Para mí, Java usó UTF-8 como codificación predeterminada en el código. –

+0

@KorayTugay Probablemente esté mezclando la representación de memoria interna de Unicode en Java (sí, todas las implementaciones de CharSequence como String aún usan caracteres de 2 bytes en formato UTF-16) y que Java importa o exporta representaciones internas (archivos, redes) en codificaciones de bytes específicos. Si todavía crees que tu versión de Java (que es ...?) Usa internamente UTF-8, ¿cómo lo has probado? Por cierto, el problema de getBytes() es que la función es muy antigua, ya estaba allí en la versión 1.1 cuando UTF-8 aún no era compatible, por lo que no se puede predecir que usa UTF-8. –

-1

El TAMAÑO de un personaje es el espacio de almacenamiento necesario para un char, que es de 16 bits. La longitud de una cadena (también la longitud de la matriz char subyacente o matriz de bytes) es la cantidad de caracteres (o bytes), no un tamaño en bits.

Es por eso que tuvo que hacer para la división por 8 para el tamaño, pero no para la longitud. La longitud debe multiplicarse por dos.

También tenga en cuenta que obtendrá otras longitudes para la matriz de bytes si especifica una codificación diferente. En este caso, se realizó una transformación a una codificación de tamaño único o variable al hacer getBytes().

Ver: http://docs.oracle.com/javase/6/docs/api/java/lang/String.html#getBytes(java.nio.charset.Charset)

+0

No, usó 'getBytes()', así que lo que obtiene es en realidad el número de bytes (lo cual no es sorprendente también). –

+0

Sí, esta respuesta está un poco fuera de tema y caracteriza erróneamente la pregunta ... Sugiero una actualización. – jayunit100

2

me gustaría decir lo que pienso, me corrija si estoy equivocado, pero usted está encontrando la longitud de la cuerda que está correctamente se muestra como 1 y cuando usted tiene solamente 1 carácter en la cuerda. la longitud muestra la longitud, no el tamaño. longitud y tamaño son dos cosas diferentes.

cheque esta Link .. usted está encontrando el número de bytes ocupados en el camino equivocado

0

así, usted tiene que 1 carácter en la matriz de caracteres tiene el tamaño de 2 bytes y que su cadena contiene es 1 carácter , no es que tenga un tamaño de 1 byte.

El objeto String en Java se compone de:

private final char value[]; 
private final int offset; 
private final int count; 
private int hash; 

sólo esto se debe asegurar que de todas formas el objeto String es más grande que char matriz. Si desea obtener más información sobre el tamaño del objeto, también puede leer sobre los encabezados de los objetos y el factor de multiplicidad para las matrices de caracteres. Por ejemplo here o here.

+0

esto no tiene sentido, ¿puedes tratar de mejorar la gramática ... etc.? – jayunit100

0

Quiero añadir algo de código primero y luego un poco de explicación:

import java.nio.charset.Charset; 

public class Main { 

    public static void main(String[] args) { 
     System.out.println("Character size: " + Character.SIZE/8); 
     final byte[] bytes = "a".getBytes(Charset.forName("UTF-16")); 
     System.out.println("String size: " + bytes.length); 
     sprintByteAsHex(bytes[0]); 
     sprintByteAsHex(bytes[1]); 
     sprintByteAsHex(bytes[2]); 
     sprintByteAsHex(bytes[3]); 
    } 

    static void sprintByteAsHex(byte b) { 
     System.out.print((Integer.toHexString((b & 0xFF)))); 
    } 
} 

Y la salida será:

Character size: 2 
String size: 4 
feff061 

Así que lo que en realidad se está perdiendo es decir, usted no está proporcionando cualquier parámetro para el método getBytes. Probablemente obtenga los bytes para la representación UTF-8 del carácter 'a'.

Bueno, pero ¿por qué obtuvimos 4 bytes cuando pedimos UTF-16? Ok, Java usa UTF-16 internamente, entonces deberíamos haber obtenido 2 bytes ¿verdad?

Si examina la salida:

feff061 

Java en realidad nos devuelve una lista de materiales: https://en.wikipedia.org/wiki/Byte_order_mark.

Los primeros 2 bytes: feff son necesarios para indicar que los siguientes bytes serán UTF-16 Big Endian. Por favor, mira la página de Wikipedia para más información.

Los 2 bytes restantes: 0061 es la representación de 2 bytes del carácter "a" que tiene. Puede verificarse desde: http://www.fileformat.info/info/unicode/char/0061/index.htm

Así que sí, un carácter en Java tiene 2 bytes, pero cuando solicite bytes sin una codificación específica, no siempre obtendrá 2 bytes, ya que las diferentes codificaciones requerirán una cantidad diferente de bytes para varios caracteres.

Cuestiones relacionadas