向套接字的输出流中写入字符串

3
我正在开发一个适应服务器-客户端架构的项目。在客户端和服务器之间传输的消息是字符串和字节数组的组合。我需要事先发送整个消息的大小。
对于字节数组,找到它的字节大小很容易。但是对于字符串来说就不那么简单了。显然,我可以将这些字符串转换为字节数组(考虑到编码方式)。但是,这些字符串可能很长,我不想为它们分配内存(例如getBytes()会分配一个新数组)。
我的问题是,以下哪种方法最节省内存?
1. 找到一个字符串的字节大小(使用UTF-8编码) 2. 将该大小写入输出流 3. 将该字符串写入输出流

尝试使用DataOutputStream。查看javadoc。 - andy
@andy 我能事先知道我要写入的字符串的大小吗? - mostruash
“长”有多长,你是否已经证明了复制所需的空间/时间是禁止的?使用CharsetEncoder可能是可行的(字节计数部分相对简单),但我认为在尝试证明最简单的方法不足以满足之前,值得尝试。 - Jon Skeet
@JonSkeet 我之前在一个涉及解析VCF文件(> 1GB,DNA遗传学相关)的项目上工作,不得不进行了大量的分析,我意识到垃圾收集器的操作有多么粗糙,所以从那时起我对Java有点偏执。 - mostruash
@mostruash:这就是关于选择战斗的内容。明确你的需求,实现尽可能简单的代码,进行测试,然后只有在必要时才使用更复杂的代码。 - Jon Skeet
3个回答

1

逐个字符迭代字符串。对每个位置调用codePointAt()以获取其Unicode码点。根据码点,可以推断出在UTF-8中编码时需要多少字节:

Codepoint range | UTF-8 bytes
-----------------------------
0     - 127     |  1
128   - 2047    |  2
2048  - 65535   |  3
65536 +         |  4

但在此之前,您应该先验证是否真的有必要这样做。很可能传递给套接字的字符串会被内部复制到字节数组中。


这就是为什么我一直在寻找一种方法,将字符串写入临时输入流并检查我写了多少字节,并将该临时流传递给套接字。如果所有这些都可以在不复制东西的情况下发生...你懂的。 - mostruash

1
如果大小不是关键问题,使用UTF16-BE编码字符串。在这种情况下,大小将为字符串长度*2。
在此模式下,您可以逐个编写Java字符,无需进行其他处理(Unicode高低代理等)。

0
你可以将消息分成数据包,这样你就可以为消息的某个部分进行计算和内存分配,然后迭代到另一个部分并重复此过程。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接