Möglicherweise möchten Sie einen String verwenden, um den Hauptteil einer HTTP-Antwort darzustellen, und die Größe verwenden, um den Header "Content-Length" festzulegen, der in Oktetten / Bytes und nicht in Zeichen angegeben wird. w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.13
iX3
4
Eine Datenbankspalte kann eine Längenbeschränkung in Bytes aufweisen, z. B. VARCHAR2 (4000 BYTE) in Oracle. Möglicherweise möchten Sie die Byteanzahl eines Strings in der gewünschten Codierung kennen, um zu wissen, ob der String passt.
Somu
@ iX3 Genau das gleiche wie ich versucht habe.
MC Emperor
1
Ich glaube, es gibt zwei mögliche Interpretationen dieser Frage, abhängig von der Absicht: Eine ist "Wie viel Speicher verwendet mein String?". Die Antwort darauf liefert @roozbeh unten (möglicherweise Modulo-VM-Feinheiten wie komprimiertes OOPS). Die andere lautet: "Wenn ich die Zeichenfolge in ein Byte [] konvertiere, wie viel Speicher würde dieses Byte-Array verwenden?". Dies ist die Frage, die von Andrzej Doyle beantwortet wird. Der Unterschied kann groß sein: "Hello World" in UTF8 ist 11 Bytes, aber der String (per @roozbeh) ist 50 Bytes (wenn meine Mathematik stimmt).
L. Blanc
Ich hätte hinzufügen sollen, dass die 11 Bytes nicht den Overhead des Byte [] -Objekts enthalten, das sie enthält, daher ist der Vergleich etwas irreführend.
L. Blanc
Antworten:
289
Eine Zeichenfolge ist eine Liste von Zeichen (dh Codepunkten). Die Anzahl der Bytes, die zur Darstellung der Zeichenfolge benötigt werden hängt vollständig davon ab, welche Codierung Sie verwenden, um sie in Bytes umzuwandeln .
Sie können den String jedoch in ein Byte-Array umwandeln und dann seine Größe wie folgt betrachten:
// 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"
Sie sehen also, dass selbst eine einfache "ASCII" -String in ihrer Darstellung eine unterschiedliche Anzahl von Bytes haben kann, je nachdem, welche Codierung verwendet wird. Verwenden Sie den gewünschten Zeichensatz für Ihren Fall als Argument dafür getBytes(). Und geraten Sie nicht in die Falle, anzunehmen, dass UTF-8 jedes Zeichen als einzelnes Byte darstellt, da dies auch nicht zutrifft:
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 "????")
(Beachten Sie, dass der Standardzeichensatz der Plattform verwendet wird, wenn Sie kein Zeichensatzargument angeben . Dies kann in einigen Kontexten nützlich sein. Im Allgemeinen sollten Sie jedoch die Abhängigkeit von den Standardeinstellungen vermeiden und beim Codieren / immer einen expliziten Zeichensatz verwenden Dekodierung ist erforderlich.)
Also nochmal, wenn ich getBytes () benutze. Es gibt mir die gleiche Länge wie x.Länge. Bin ich falsch, weil ich nicht sicher bin
Grün
4
@Green Ash Die Länge des Byte-Arrays - getBytes () - und x.length kann gleich sein, kann aber nicht garantiert werden. Es ist gleich, wenn alle Zeichen jeweils durch ein einzelnes Byte dargestellt werden. Dies gilt immer für Zeichencodierungen, die ein einzelnes Byte pro Zeichen (oder weniger) verwenden, z. B. ISO-8859-1. UTF-8 verwendet entweder 1 oder 2 Bytes, daher hängt es von den genauen Zeichen in der Zeichenfolge ab. Dann gibt es Zeichencodierungen, die immer zwei Bytes pro Zeichen verwenden.
Kris
Ich mag deine Antwort :), also könnten sie irgendwie gleich sein, aber nicht immer habe ich recht? ok dann ist es ok die methode ohne den parameter zu benutzen weil es mir einen fehler verursacht !!
Grün
@Green der Punkt ist, dass die Anzahl der Bytes nicht immer der Anzahl der Zeichen entspricht . Die Anzahl der Bytes hängt von der verwendeten Zeichenkodierung ab. Sie müssen wissen, welche Zeichenkodierung Sie verwenden werden, und dies berücksichtigen. Welchen Fehler bekommen Sie? Wenn Sie nur verwenden getBytes(), wird die Standardzeichenkodierung Ihres Systems verwendet.
Jesper
1
@KorayTugay Ja, mehr oder weniger. Sie könnten jedoch über die Reihenfolge von Ursache und Wirkung streiten. Ich würde mehr in dem Zustand geneigt sein , dass ein char ist immer 2 Bytes , weil es dich um einen primitiven Datentyp definierte 2 Bytes breit zu sein. (Und dass die UTF-16-Darstellung hauptsächlich eine Folge davon war und nicht umgekehrt.)
Andrzej Doyle
63
Wenn Sie mit 64-Bit-Referenzen arbeiten:
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
Mit anderen Worten:
sizeof(string)=36+ string.length()*2
Auf einer 32-Bit-VM oder einer 64-Bit-VM mit komprimierten OOPs (-XX: + UseCompressedOops) sind die Referenzen 4 Byte. Die Summe wäre also:
sizeof(string)=32+ string.length()*2
Dies berücksichtigt nicht die Verweise auf das Zeichenfolgenobjekt.
Ich nahm an, dass die Frage die Anzahl der im Speicher für ein String-Objekt zugewiesenen Bytes betraf. Wenn es um die Anzahl der Bytes geht, die zum Serialisieren des Strings erforderlich sind, hängt dies von der verwendeten Codierung ab.
Roozbeh
2
Quelle für Ihre Antwort? Danke
Mavis
1
Hinweis: sizeofsollte ein Vielfaches von 8 sein.
Dieter
19
Die pedantische Antwort (obwohl nicht unbedingt die nützlichste, je nachdem, was Sie mit dem Ergebnis machen möchten) lautet:
string.length()*2
Java-Zeichenfolgen werden physisch in der UTF-16BECodierung gespeichert , die 2 Bytes pro Codeeinheit verwendet und String.length()die Länge in UTF-16-Codeeinheiten misst. Dies entspricht also:
Roozbehs Antwort ist besser, weil sie auch die anderen Bytes berücksichtigt.
Lodewijk Bogaards
@finnw Sind Sie sicher, dass die Codierung UTF-16BE und nicht UTF-16 ist? Gemäß der String-Klasse Javadoc ( docs.oracle.com/javase/6/docs/api/java/lang/String.html ) steht "Ein String für einen String im UTF-16-Format ...".
aber entschuldigen Sie, wenn ich Ihren Code kompiliere, gibt es mir einen Fehler; Aufgrund des Parameters "UTF-8". Wenn ich einen leeren Parameter übergebe, erhalte ich die gleiche Länge wie x.length. Ich verstehe das Konzept falsch. Hilfe bitte
Grün
@ Green Ash, welche Java-Version hast du?
Buhake Sindi
@ Green Ash, welche Ausnahme bekommst du?
Buhake Sindi
2
um klar zu sein, ist dies die Ausgabe: test.java:11: nicht gemeldete Ausnahme java.io.UnsupportedEncodingException; muss abgefangen oder deklariert werden, um geworfen zu werden byte [] b = s.getBytes ("UTF-8"); ^ 1 Fehler Vorgang abgeschlossen.
Grün
3
@Green, versuchen Sie : s.getBytes(Charset.forName("UTF-8")).
James.garriss
10
Eine StringInstanz weist eine bestimmte Anzahl von Bytes im Speicher zu. Vielleicht schaust du dir so etwas ansizeof("Hello World") das die Anzahl der von der Datenstruktur selbst zugewiesenen Bytes zurückgibt?
In Java ist normalerweise keine sizeofFunktion erforderlich , da wir niemals Speicher zum Speichern einer Datenstruktur zuweisen. Wir können uns die String.javaDatei ansehen, um eine grobe Schätzung zu erhalten, und wir sehen einige 'int', einige Referenzen und a char[]. Das Java-Sprachspezifikation definiert, dass a charzwischen 0 und 65535 liegt, sodass zwei Bytes ausreichen, um ein einzelnes Zeichen im Speicher zu halten. Aber eine JVM muss nicht ein Zeichen in 2 Bytes speichern, sondern nur garantieren, dass die Implementierung vonchar Werte des definierten Bereichs enthalten kann.
Also sizeofmacht das in Java wirklich keinen Sinn. Unter der Annahme, dass wir einen großen String haben und einer charzwei Bytes zuweist, Stringbeträgt der Speicherbedarf eines Objekts mindestens 2 * str.length()Bytes.
Mit Bedacht = Verwenden Sie keinen Parameter ohne Zeichensatz.
Thilo
Warum? Ist dies ein Problem, wenn ich meine Umgebung so konfiguriere, dass sie mit UTF8-Codierung ausgeführt wird?
Zicky
1
getBytes erstellt und kopiert auch das Array von Bytes. Wenn Sie also lange Zeichenfolgen sprechen, kann dieser Vorgang teuer werden.
Ticktock
@ticktock, wenn du noch da bist, ja aber was ist die Alternative? Ich bin hierher gekommen und habe gehofft, dass eine Bibliotheksfunktion den benötigten Speicher zurückgibt, damit ich ihn zu einer größeren Zuordnung kombinieren kann.
SensorSmith
4
Versuche dies :
Bytes.toBytes(x).length
Angenommen, Sie haben x zuvor deklariert und initialisiert
Antworten:
Eine Zeichenfolge ist eine Liste von Zeichen (dh Codepunkten). Die Anzahl der Bytes, die zur Darstellung der Zeichenfolge benötigt werden hängt vollständig davon ab, welche Codierung Sie verwenden, um sie in Bytes umzuwandeln .
Sie können den String jedoch in ein Byte-Array umwandeln und dann seine Größe wie folgt betrachten:
Sie sehen also, dass selbst eine einfache "ASCII" -String in ihrer Darstellung eine unterschiedliche Anzahl von Bytes haben kann, je nachdem, welche Codierung verwendet wird. Verwenden Sie den gewünschten Zeichensatz für Ihren Fall als Argument dafür
getBytes()
. Und geraten Sie nicht in die Falle, anzunehmen, dass UTF-8 jedes Zeichen als einzelnes Byte darstellt, da dies auch nicht zutrifft:(Beachten Sie, dass der Standardzeichensatz der Plattform verwendet wird, wenn Sie kein Zeichensatzargument angeben . Dies kann in einigen Kontexten nützlich sein. Im Allgemeinen sollten Sie jedoch die Abhängigkeit von den Standardeinstellungen vermeiden und beim Codieren / immer einen expliziten Zeichensatz verwenden Dekodierung ist erforderlich.)
quelle
getBytes()
, wird die Standardzeichenkodierung Ihres Systems verwendet.Wenn Sie mit 64-Bit-Referenzen arbeiten:
Mit anderen Worten:
Auf einer 32-Bit-VM oder einer 64-Bit-VM mit komprimierten OOPs (-XX: + UseCompressedOops) sind die Referenzen 4 Byte. Die Summe wäre also:
Dies berücksichtigt nicht die Verweise auf das Zeichenfolgenobjekt.
quelle
sizeof
sollte ein Vielfaches von 8 sein.Die pedantische Antwort (obwohl nicht unbedingt die nützlichste, je nachdem, was Sie mit dem Ergebnis machen möchten) lautet:
Java-Zeichenfolgen werden physisch in der
UTF-16BE
Codierung gespeichert , die 2 Bytes pro Codeeinheit verwendet undString.length()
die Länge in UTF-16-Codeeinheiten misst. Dies entspricht also:Und dies zeigt Ihnen die Größe des internen
char
Arrays in Bytes .Hinweis:
"UTF-16"
Gibt ein anderes Ergebnis"UTF-16BE"
als die vorherige Codierung, fügt eine Stückliste ein und addiert 2 Bytes zur Länge des Arrays.quelle
Laut Wie konvertiert Strings zu und von UTF8 Byte - Arrays in Java :
quelle
s.getBytes(Charset.forName("UTF-8"))
.Eine
String
Instanz weist eine bestimmte Anzahl von Bytes im Speicher zu. Vielleicht schaust du dir so etwas ansizeof("Hello World")
das die Anzahl der von der Datenstruktur selbst zugewiesenen Bytes zurückgibt?In Java ist normalerweise keine
sizeof
Funktion erforderlich , da wir niemals Speicher zum Speichern einer Datenstruktur zuweisen. Wir können uns dieString.java
Datei ansehen, um eine grobe Schätzung zu erhalten, und wir sehen einige 'int', einige Referenzen und achar[]
. Das Java-Sprachspezifikation definiert, dass achar
zwischen 0 und 65535 liegt, sodass zwei Bytes ausreichen, um ein einzelnes Zeichen im Speicher zu halten. Aber eine JVM muss nicht ein Zeichen in 2 Bytes speichern, sondern nur garantieren, dass die Implementierung vonchar
Werte des definierten Bereichs enthalten kann.Also
sizeof
macht das in Java wirklich keinen Sinn. Unter der Annahme, dass wir einen großen String haben und einerchar
zwei Bytes zuweist,String
beträgt der Speicherbedarf eines Objekts mindestens2 * str.length()
Bytes.quelle
Es gibt eine Methode namens getBytes () . Benutze es weise .
quelle
Versuche dies :
Angenommen, Sie haben x zuvor deklariert und initialisiert
quelle
Bytes
Klasse nicht finden .Verwenden Sie:
quelle