On peut souhaiter utiliser une chaîne pour représenter le corps d'une réponse HTTP et utiliser la taille pour définir l'en-tête "Content-Length", qui est spécifié en octets / octets et non en caractères. w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.13
iX3
4
Une colonne de base de données peut avoir une restriction de longueur en octets, par exemple VARCHAR2 (4000 BYTE) dans Oracle. On peut souhaiter connaître le nombre d'octets d'une chaîne dans le codage souhaité pour savoir si la chaîne conviendrait.
Somu le
@ iX3 Exactement la même chose que j'essayais de faire.
MC Emperor
1
Je crois qu'il y a deux interprétations possibles de cette question, selon l'intention: L'une est "combien de mémoire ma chaîne utilise-t-elle?". La réponse à cela est fournie par @roozbeh ci-dessous (peut-être des subtilités modulo VM telles que OOPS compressé). L'autre est, "si je convertis la chaîne en octet [], combien de mémoire ce tableau d'octets utiliserait-il?". Telle est la question à laquelle répond Andrzej Doyle. La différence peut être importante: "Hello World" en UTF8 est de 11 octets, mais la chaîne (par @roozbeh) est de 50 octets (si mes calculs sont corrects).
L. Blanc
J'aurais dû ajouter que les 11 octets n'incluent pas la surcharge de l'objet byte [] qui les contient, donc la comparaison est quelque peu trompeuse.
L. Blanc
Réponses:
289
Une chaîne est une liste de caractères (c'est-à-dire des points de code). Le nombre d'octets pris pour représenter la chaîne dépend entièrement du codage que vous utilisez pour la transformer en octets .
Cela dit, vous pouvez transformer la chaîne en un tableau d'octets, puis examiner sa taille comme suit:
// 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"
Ainsi vous voyez, même une simple chaîne "ASCII" peut avoir un nombre d'octets différent dans sa représentation, selon le codage utilisé. Utilisez le jeu de caractères qui vous intéresse pour votre cas, comme argument getBytes(). Et ne tombez pas dans le piège de supposer que UTF-8 représente chaque caractère comme un seul octet, car ce n'est pas vrai non plus:
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 "????")
(Notez que si vous ne fournissez pas d'argument de jeu de caractères, le jeu de caractères par défaut de la plate-forme est utilisé. Cela peut être utile dans certains contextes, mais en général, vous devez éviter de dépendre des valeurs par défaut et toujours utiliser un jeu de caractères explicite lors de l'encodage / le décodage est nécessaire.)
donc encore une fois si j'utilise getBytes (). cela me donnera la même longueur que x.length je me trompe parce que je ne suis pas sûr
Vert
4
@Green Ash La longueur du tableau d'octets - getBytes () - et x.length PEUVENT être égales mais ce n'est pas garanti. Il sera égal si tous les caractères sont représentés chacun par un seul octet. Cela sera toujours vrai pour les encodages de caractères qui utilisent un seul octet par caractère (ou moins), comme ISO-8859-1. UTF-8 utilise 1 ou 2 octets, donc cela dépend des caractères exacts de la chaîne. Ensuite, il existe des encodages de caractères qui utilisent toujours deux octets par caractère.
Kris
j'aime ta réponse :), donc ils pourraient en quelque sorte être les mêmes, mais pas toujours j'ai raison? ok alors est-il correct d'utiliser la méthode sans le paramètre car cela me cause une erreur !!
Vert
@ Vert le point est que le nombre d' octets n'est pas toujours le même que le nombre de caractères . Le nombre d' octets dépend du codage de caractères utilisé. Vous devrez savoir quel encodage de caractères vous allez utiliser et en tenir compte. Quelle erreur obtenez vous? Si vous ne faites que l'utiliser, getBytes()il utilisera le codage de caractères par défaut de votre système.
Jesper
1
@KorayTugay Oui, plus ou moins. Vous pourriez cependant discuter de l'ordre de cause à effet. Je serais plus enclin à déclarer qu'un caractère est toujours de 2 octets car il s'agit d'un type de données primitif défini pour être de 2 octets de large. (Et que la représentation UTF-16 était principalement une conséquence de cela, plutôt que l'inverse.)
Andrzej Doyle
63
Si vous utilisez des références 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 d'autres termes:
sizeof(string)=36+ string.length()*2
Sur une machine virtuelle 32 bits ou une machine virtuelle 64 bits avec des POO compressés (-XX: + UseCompressedOops), les références sont de 4 octets. Le total serait donc:
sizeof(string)=32+ string.length()*2
Cela ne prend pas en compte les références à l'objet string.
Je supposais que la question portait sur le nombre d'octets alloués en mémoire pour un objet String. Si la question porte sur le nombre d'octets requis pour sérialiser la chaîne, comme d'autres l'ont souligné, cela dépend du codage utilisé.
roozbeh
2
Source pour votre réponse? Merci
mavis
1
Remarque: sizeofdoit être multiple de 8.
dieter
19
La réponse pédante (mais pas nécessairement la plus utile, selon ce que vous voulez faire du résultat) est:
string.length()*2
Les chaînes Java sont physiquement stockées dans l' UTF-16BEencodage, qui utilise 2 octets par unité de code, et String.length()mesure la longueur en unités de code UTF-16, donc cela équivaut à:
Et cela vous indiquera la taille du chartableau interne , en octets .
Remarque: "UTF-16"donnera un résultat différent de celui "UTF-16BE"que l'ancien encodage insérera une nomenclature , ajoutant 2 octets à la longueur du tableau.
mais excusez-moi quand je compile votre code, cela me donne une erreur; à cause du paramètre "UTF-8" .où quand je passe un paramètre vide, il me donne la même longueur que x.length. J'ai mal compris le concept. aide s'il vous plaît
Vert
@Green Ash, quelle version de Java avez-vous?
Buhake Sindi
@Green Ash, quelle exception obtenez-vous?
Buhake Sindi
2
pour être clair, voici la sortie: test.java:11: exception non signalée java.io.UnsupportedEncodingException; doit être intercepté ou déclaré pour être levé byte [] b = s.getBytes ("UTF-8"); ^ 1 erreur Processus terminé.
Une Stringinstance alloue une certaine quantité d'octets en mémoire. Peut-être cherchez-vous quelque chose comme sizeof("Hello World")qui retournerait le nombre d'octets alloués par la structure de données elle-même?
En Java, il n'y a généralement pas besoin de sizeoffonction, car nous n'allouons jamais de mémoire pour stocker une structure de données. Nous pouvons jeter un oeil au String.javafichier pour une estimation approximative, et nous voyons des 'int', des références et un char[]. La spécification du langage Java définit que a charva de 0 à 65535, donc deux octets suffisent pour garder un seul caractère en mémoire. Mais une JVM n'a pas besoin de stocker un caractère sur 2 octets, elle doit seulement garantir que l'implémentation de charpeut contenir les valeurs de la plage de définition.
Cela sizeofn'a donc vraiment aucun sens en Java. Mais, en supposant que nous avons une grande chaîne et que l'on charalloue deux octets, alors l'empreinte mémoire d'un Stringobjet est au moins 2 * str.length()en octets.
Sagement = n'utilisez pas celui sans paramètre de jeu de caractères.
Thilo
Pourquoi? Est-ce un problème si je configure mon environnement pour qu'il s'exécute avec le codage UTF8?
ziggy le
1
getBytes créera et copiera également le tableau d'octets, donc si vous parlez de longues chaînes, cette opération pourrait être coûteuse.
ticktock
@ticktock, si vous êtes toujours là, oui mais quelle est l'alternative? Je suis arrivé ici en espérant qu'une fonction de bibliothèque renvoie le stockage nécessaire afin de pouvoir le combiner dans une allocation plus grande.
SensorSmith
4
Essaye ça :
Bytes.toBytes(x).length
En supposant que vous ayez déclaré et initialisé x avant
Réponses:
Une chaîne est une liste de caractères (c'est-à-dire des points de code). Le nombre d'octets pris pour représenter la chaîne dépend entièrement du codage que vous utilisez pour la transformer en octets .
Cela dit, vous pouvez transformer la chaîne en un tableau d'octets, puis examiner sa taille comme suit:
Ainsi vous voyez, même une simple chaîne "ASCII" peut avoir un nombre d'octets différent dans sa représentation, selon le codage utilisé. Utilisez le jeu de caractères qui vous intéresse pour votre cas, comme argument
getBytes()
. Et ne tombez pas dans le piège de supposer que UTF-8 représente chaque caractère comme un seul octet, car ce n'est pas vrai non plus:(Notez que si vous ne fournissez pas d'argument de jeu de caractères, le jeu de caractères par défaut de la plate-forme est utilisé. Cela peut être utile dans certains contextes, mais en général, vous devez éviter de dépendre des valeurs par défaut et toujours utiliser un jeu de caractères explicite lors de l'encodage / le décodage est nécessaire.)
la source
getBytes()
il utilisera le codage de caractères par défaut de votre système.Si vous utilisez des références 64 bits:
En d'autres termes:
Sur une machine virtuelle 32 bits ou une machine virtuelle 64 bits avec des POO compressés (-XX: + UseCompressedOops), les références sont de 4 octets. Le total serait donc:
Cela ne prend pas en compte les références à l'objet string.
la source
sizeof
doit être multiple de 8.La réponse pédante (mais pas nécessairement la plus utile, selon ce que vous voulez faire du résultat) est:
Les chaînes Java sont physiquement stockées dans l'
UTF-16BE
encodage, qui utilise 2 octets par unité de code, etString.length()
mesure la longueur en unités de code UTF-16, donc cela équivaut à:Et cela vous indiquera la taille du
char
tableau interne , en octets .Remarque:
"UTF-16"
donnera un résultat différent de celui"UTF-16BE"
que l'ancien encodage insérera une nomenclature , ajoutant 2 octets à la longueur du tableau.la source
Selon Comment convertir des chaînes vers et depuis des tableaux d'octets UTF8 en Java :
la source
s.getBytes(Charset.forName("UTF-8"))
.Une
String
instance alloue une certaine quantité d'octets en mémoire. Peut-être cherchez-vous quelque chose commesizeof("Hello World")
qui retournerait le nombre d'octets alloués par la structure de données elle-même?En Java, il n'y a généralement pas besoin de
sizeof
fonction, car nous n'allouons jamais de mémoire pour stocker une structure de données. Nous pouvons jeter un oeil auString.java
fichier pour une estimation approximative, et nous voyons des 'int', des références et unchar[]
. La spécification du langage Java définit que achar
va de 0 à 65535, donc deux octets suffisent pour garder un seul caractère en mémoire. Mais une JVM n'a pas besoin de stocker un caractère sur 2 octets, elle doit seulement garantir que l'implémentation dechar
peut contenir les valeurs de la plage de définition.Cela
sizeof
n'a donc vraiment aucun sens en Java. Mais, en supposant que nous avons une grande chaîne et que l'onchar
alloue deux octets, alors l'empreinte mémoire d'unString
objet est au moins2 * str.length()
en octets.la source
Il existe une méthode appelée getBytes () . Fais-en bon usage .
la source
Essaye ça :
En supposant que vous ayez déclaré et initialisé x avant
la source
Bytes
classe.Pour éviter d'essayer d'attraper, utilisez:
la source