【问题标题】:Writing a string to the ouputstream of a socket将字符串写入套接字的输出流
【发布时间】:2013-05-01 14:54:20
【问题描述】:

我正在开发一个适应服务器-客户端架构的项目。在客户端和服务器之间传输的消息是字符串和字节数组的组合。我需要事先发送整条消息的大小。

查找字节数组的字节大小很简单,但是对于字符串则不然。显然,我可以将这些字符串转换为字节数组(考虑到编码)。但是,这些字符串可能很长,我不想为它们的副本分配内存(例如 getBytes() 分配一个新数组)。

我的问题是,执行以下操作最节省内存的方式是什么?

  1. 查找字符串的字节大小(使用 UTF-8 编码)
  2. 将该大小写入输出流
  3. 将字符串写入输出流

【问题讨论】:

  • 试试 DataOutputStream。看javadoc
  • @andy 我会事先知道我要写的字符串的大小吗?
  • “长”有多长,你是否真的证明了复制所需的空间/时间令人望而却步?使用CharsetEncoder (字节计数部分相当简单)可能是可行的,但我认为在你做任何更复杂的事情之前,有必要尝试证明最简单的方法是不够的。
  • @JonSkeet 我之前正在从事一个涉及解析 VCF 文件(> 1GB,DNA 遗传学的东西)的项目,并且必须做很多分析,我意识到垃圾收集器是多么草率所以从那时起我就对 Java 有点偏执了。
  • @mostruash:关键在于选择你的战斗。定义你的需求,实现最简单的代码,测试它,然后使用更复杂的代码如果你需要。

标签: java string sockets outputstream


【解决方案1】:

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

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

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

【讨论】:

  • 这就是为什么我一直在寻找一种方法将字符串写入某个临时输入流并检查我写入了多少字节,然后将该临时流传递给套接字。如果所有这些都能在不复制内容的情况下发生......你明白了。
【解决方案2】:

如果大小不是关键问题,请对字符串使用 UTF16-BE 编码。在这种情况下,大小将是字符串长度 * 2。

在这种模式下,您可以一个一个地写入 Java 字符,而无需进行额外的处理(Unicode 高低代理等)。

【讨论】:

    【解决方案3】:

    您始终可以将消息“分解”成数据包,因此您可以对消息的某些部分进行计算和内存分配,然后迭代到另一部分并再次执行此操作。

    【讨论】:

      猜你喜欢
      • 2015-01-01
      • 2011-05-03
      • 1970-01-01
      • 2015-11-29
      • 2011-03-29
      • 2018-12-11
      • 2017-06-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多