除了使用new String(bytearray)之外,还有其他方法可以将字节数组转换为字符串吗?确切的问题是我通过UDP连接在网络上传输了一个json格式的字符串。在另一端,我在固定大小的字节数组中接收它(因为我不知道数组的大小),并在字节数组之外创建一个新的字符串。如果我这样做,我分配的整个内存都是不必要的。
为了避免这种情况,我让字节数组将其转换为字符串,截断字符串直到最后一个有效字符,然后将其转换为字节数组并从中创建一个新的字符串。如果我这样做,它只会耗尽所需的内存,但垃圾收集频率会变得如此之高,因为它涉及更多的分配。做这件事最好的方法是什么?
发布于 2010-07-10 08:28:13
会不会像这样:
String s = new String( bytearray, 0, lenOfValidData, "US-ASCII");做你想做的(将字符集更改为任何合适的编码)?
更新:
根据您的评论,您可能希望尝试:
socket.receive(packet);
String strPacket = new String( packet.getData(), 0, packet.getLength(), "US-ASCII");
receiver.onReceive( strPacket);我对Java的数据报支持不够熟悉,不知道packet.getLength()返回的是数据报的截断长度还是原始长度(在截断以适合接收缓冲区之前)。像这样创建字符串可能更安全:
String strPacket = new String( packet.getData(),
0,
Math.min( packet.getLength(), packet.getData().length),
"US-ASCII");再说一次,这可能是不必要的。
发布于 2010-07-10 09:25:46
执行此操作的最简单、最可靠的方法是使用从UDP套接字读取的数据包的长度。DatagramSocket.receive(...)的javadoc这样说:
从此套接字接收数据报包。当此方法返回时,DatagramPacket的缓冲区将填充所接收的数据。数据报包还包含发送者的IP地址和发送者机器上的端口号。
此方法会一直阻塞,直到收到数据报为止。数据包对象的长度字段包含接收到的消息的长度。如果消息比数据包的长度长,则消息被截断。
如果您不能做到这一点,那么下面的代码将分配一个最小大小的字符串,而不会分配不必要的临时变量。
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个字符。
发布于 2010-07-10 08:36:21
您可以通过使用StringBuilder来避免创建第二个字符串。我假设您的数据接收过程如下所示:
,我宁愿保留它,以备下次您通过网络接收东西时使用
编辑
我听从了Tofubeer的建议,用StringBuilder代替了StringBuffer。
https://stackoverflow.com/questions/3217289
复制相似问题