如何检测字节数组中的字符串结尾到字符串转换?
我从socket接收一个字节数组中的字符串,如下所示:
[128,5,6,3,45,0,0,0,0,0]
网络协议给出的大小是字符串的总长度(包括零),因此,在我的例子中10。
如果我只是这样做:
String myString = new String(myBuffer);
我在字符串5的末尾没有正确的字符。 转换似乎没有检测到字符串caracter(0)的结束。
要获得正确的大小和正确的字符串,我这样做:
int sizeLabelTmp = 0; //Iterate over the 10 bit to get the real size of the string for(int j = 0; j<(sizeLabel); j++) { byte charac = datasRec[j]; if(charac == 0) break; sizeLabelTmp ++; } // Create a temp byte array to make a correct conversion byte[] label = new byte[sizeLabelTmp]; for(int j = 0; j<(sizeLabelTmp); j++) { label[j] = datasRec[j]; } String myString = new String(label);
有没有更好的方法来处理这个问题?
谢谢
0不是“字符串结尾字符”。 这只是一个字节。 它是否只出现在字符串的末尾取决于您正在使用的编码(以及文本可以是什么)。 例如,如果使用UTF-16,则ASCII字符的每隔一个字节为0。
如果您确定第一个0表示字符串的结尾,您可以使用类似您给出的代码,但我会将其重写为:
int size = 0; while (size < data.length) { if (data[size] == 0) { break; } size++; } // Specify the appropriate encoding as the last argument String myString = new String(data, 0, size, "UTF-8");
我强烈建议您不要只使用平台默认编码 - 它不可移植,并且可能不允许所有Unicode字符。 但是,您不能随意决定 - 您需要确保生成和使用此数据的所有内容都符合编码。
如果您控制协议,那么如果您可以在字符串之前引入长度前缀,则表示编码forms中有多少字节会更好。 这样你就能够准确读取正确数量的数据(没有“过度阅读”),并且你能够判断数据是否因某种原因被截断。
可能为时已晚,但它可能对其他人有所帮助。 你可以做的最简单的事情是new String(myBuffer).trim()
,它可以为你提供你想要的东西。
您始终可以从字节数组的末尾开始,然后向后搜索,直到达到第一个非零值。 然后将其复制到一个新字节然后串起来。 希望这可以帮助:
byte[] foo = {28,6,3,45,0,0,0,0}; int i = foo.length - 1; while (foo[i] == 0) { i--; } byte[] bar = Arrays.copyOf(foo, i+1); String myString = new String(bar, "UTF-8"); System.out.println(myString.length());
会给你4的结果。
Java中的字符串不以0结尾,就像在其他一些语言中一样。 0将变为所谓的空字符,允许出现在字符串中。 我建议你使用一些修剪方案,它可以检测数组的第一个索引是0并使用一个子数组来构造字符串(假设其余的后面都是0),或者只是构造字符串并调用trim()
。 这将删除前导和尾随空格,即ASCII代码为32或更低的任何字符。
如果你有必须保留的前导空格,后者将不起作用。 只要它们是空字符,使用StringBuilder并删除末尾的字符在这种情况下效果会更好。
在我看来,你忽略了read()方法返回的读取计数。 可能没有发送尾随空字节,它们可能仍然从缓冲区的初始状态遗留下来。
int count = in.read(buffer); if (count < 0) ; // EOS: close the socket etc else String s = new String(buffer, 0, count);
不要深入研究原始OP提到的协议考虑因素,如何修剪尾随的零?
public static String bytesToString(byte[] data) { String dataOut = ""; for (int i = 0; i < data.length; i++) { if (data[i] != 0x00) dataOut += (char)data[i]; } return dataOut; }