首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Java中不使用new运算符将字节数组转换为字符串

问在Java中不使用new运算符将字节数组转换为字符串
EN

Stack Overflow用户
提问于 2010-07-10 08:22:02
回答 4查看 5.8K关注 0票数 4

除了使用new String(bytearray)之外,还有其他方法可以将字节数组转换为字符串吗?确切的问题是我通过UDP连接在网络上传输了一个json格式的字符串。在另一端,我在固定大小的字节数组中接收它(因为我不知道数组的大小),并在字节数组之外创建一个新的字符串。如果我这样做,我分配的整个内存都是不必要的。

为了避免这种情况,我让字节数组将其转换为字符串,截断字符串直到最后一个有效字符,然后将其转换为字节数组并从中创建一个新的字符串。如果我这样做,它只会耗尽所需的内存,但垃圾收集频率会变得如此之高,因为它涉及更多的分配。做这件事最好的方法是什么?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2010-07-10 08:28:13

会不会像这样:

代码语言:javascript
复制
String s = new String( bytearray, 0, lenOfValidData, "US-ASCII");

做你想做的(将字符集更改为任何合适的编码)?

更新:

根据您的评论,您可能希望尝试:

代码语言:javascript
复制
socket.receive(packet);
String strPacket = new String( packet.getData(), 0, packet.getLength(), "US-ASCII");
receiver.onReceive( strPacket);

我对Java的数据报支持不够熟悉,不知道packet.getLength()返回的是数据报的截断长度还是原始长度(在截断以适合接收缓冲区之前)。像这样创建字符串可能更安全:

代码语言:javascript
复制
String strPacket = new String( packet.getData(), 
                               0, 
                               Math.min( packet.getLength(), packet.getData().length),
                               "US-ASCII");

再说一次,这可能是不必要的。

票数 2
EN

Stack Overflow用户

发布于 2010-07-10 09:25:46

执行此操作的最简单、最可靠的方法是使用从UDP套接字读取的数据包的长度。DatagramSocket.receive(...)的javadoc这样说:

从此套接字接收数据报包。当此方法返回时,DatagramPacket的缓冲区将填充所接收的数据。数据报包还包含发送者的IP地址和发送者机器上的端口号。

此方法会一直阻塞,直到收到数据报为止。数据包对象的长度字段包含接收到的消息的长度。如果消息比数据包的长度长,则消息被截断。

如果您不能做到这一点,那么下面的代码将分配一个最小大小的字符串,而不会分配不必要的临时变量。

代码语言:javascript
复制
  byte[] buff = ... // read from socket.

  // Find byte offset of first 'non-character' in buff
  int i;
  for (i = 0; i < buff.length && /* buff[i] represents a character */; i++) { /**/ }

  // Allocate String
  String res = new String(buff, 0, i, charsetName);

请注意,确定非字符集的标准是字符集和特定于应用程序的。但是可能测试一个零字节就足够了。

编辑

javadoc所说的“新字符串的长度是字符集的函数,因此可能不等于子数组的长度”到底是什么意思。

它指出的事实是,对于某些字符编码(例如UTF-8、UTF-16、JIS等),某些字符由两个或更多个字节表示。因此,例如,10个字节的UTF-8可能表示少于10个字符。

票数 2
EN

Stack Overflow用户

发布于 2010-07-10 08:36:21

您可以通过使用StringBuilder来避免创建第二个字符串。我假设您的数据接收过程如下所示:

  1. 在客户端获取(固定大小)字节数组。
  2. 创建一个StringBuilder对象。
  3. 只要读取有效字符并将其附加到StringBuilder对象,就会在数组上循环。
  4. 字节数组现在可以被丢弃。(为了避免不必要的内存allocations.)

,我宁愿保留它,以备下次您通过网络接收东西时使用

编辑

我听从了Tofubeer的建议,用StringBuilder代替了StringBuffer。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3217289

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档