Mik Asked:2024-10-18 23:06:22 +0000 UTC2024-10-18 23:06:22 +0000 UTC 2024-10-18 23:06:22 +0000 UTC 如何计算我的字符串在 Java 中将占用字符集中的字节数? 772 我如何在 Java 中计算我的 String 占用了多少字节,例如在 中US_ASCII? C# 有它Encoding.GetByteCount,这就是我需要的,也就是说,我需要在 UI 中快速验证字节长度,并且我不想创建字节数组,但我想在不分配内存的情况下进行计数 java 1 个回答 Voted Best Answer Stanislav Volodarskiy 2024-10-19T04:56:16Z2024-10-19T04:56:16Z ByteCounter计算指定编码中字符串的字节数。内存是在对象创建时分配的。计算本身几乎不分配内存。 用过的CharsetEncoder.encode。输入缓冲区是一个字符,输出缓冲区是十个字节。如果encode它抱怨输出缓冲区溢出,则会分配一个新的缓冲区,大小是两倍。 NB encode永远不应该抱怨缓冲区溢出,十个字节对每个人来说应该足够了。对于 UTF-8,最长的字节序列是 4。您甚至不需要更多的表情符号。最大的编码单元是代理对,它总是适合四个字节。 示例中有两个实例ByteCounter。第一个忽略编码错误,就像String.getBytes.第二个可以检测错误并引发异常。 import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.CharacterCodingException; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; import java.nio.charset.CoderResult; import java.nio.charset.CodingErrorAction; import java.util.Scanner; public class Temp { public static void main(String[] args) { Charset cs = Charset.forName(args[0]); ByteCounter bc1 = new ByteCounter(cs.newEncoder() .onMalformedInput (CodingErrorAction.REPLACE) .onUnmappableCharacter(CodingErrorAction.REPLACE) ); ByteCounter bc2 = new ByteCounter(cs.newEncoder()); Scanner sc = new Scanner(System.in); while (sc.hasNextLine()) { String s = sc.nextLine(); System.out.print(s.getBytes(cs).length); System.out.print(" "); try { System.out.print(bc1.countBytes(s)); } catch (CharacterCodingException e) { System.out.print("N/A"); } System.out.print(" "); try { System.out.print(bc2.countBytes(s)); } catch (CharacterCodingException e) { System.out.print("N/A"); } System.out.print(" "); System.out.println(s); } } private static class ByteCounter { private final CharsetEncoder ce; private final CharBuffer in = CharBuffer.allocate(1); private ByteBuffer out = ByteBuffer.allocate(10); public ByteCounter(CharsetEncoder ce) { this.ce = ce; } public int countBytes(String s) throws CharacterCodingException { int bytes = 0; ce.reset(); for (int i = 0; i < s.length(); ++i) { char c = s.charAt(i); in.put(0, c); in.position(0); for (; ;) { out.position(0); CoderResult cr = ce.encode(in, out, false); if (cr.isError()) { cr.throwException(); } bytes += out.position(); if (!cr.isOverflow()) { break; } out = ByteBuffer.allocate(2 * out.capacity()); } } return bytes; } } } $ javac Temp.java $ java Temp US-ASCII << EOF Hello! Привет! こんにちは! 你好! EOF 6 6 6 Hello! 7 7 N/A Привет! 6 6 N/A こんにちは! 3 3 N/A 你好! $ java Temp UTF-8 << EOF Hello! Привет! こんにちは! 你好! EOF 6 6 6 Hello! 13 13 13 Привет! 18 18 18 こんにちは! 9 9 9 你好! PPS我答应用一个字节凑合,但我做不到。如果CharsetEncoder.encode报告溢出,则需要提供更大的缓冲区。他拒绝一次给出一个字节的编码字符串。因此制作了一个十字节的缓冲区,并添加了一种机制来在溢出时增加缓冲区。可以通过将初始缓冲区大小设置为 1 来测试。
ByteCounter计算指定编码中字符串的字节数。内存是在对象创建时分配的。计算本身几乎不分配内存。用过的
CharsetEncoder.encode。输入缓冲区是一个字符,输出缓冲区是十个字节。如果encode它抱怨输出缓冲区溢出,则会分配一个新的缓冲区,大小是两倍。NB
encode永远不应该抱怨缓冲区溢出,十个字节对每个人来说应该足够了。对于 UTF-8,最长的字节序列是 4。您甚至不需要更多的表情符号。最大的编码单元是代理对,它总是适合四个字节。示例中有两个实例
ByteCounter。第一个忽略编码错误,就像String.getBytes.第二个可以检测错误并引发异常。PPS我答应用一个字节凑合,但我做不到。如果
CharsetEncoder.encode报告溢出,则需要提供更大的缓冲区。他拒绝一次给出一个字节的编码字符串。因此制作了一个十字节的缓冲区,并添加了一种机制来在溢出时增加缓冲区。可以通过将初始缓冲区大小设置为 1 来测试。