如何检测字节数组中的字符串结尾到字符串转换?

时间:2011-11-04 09:48:08

标签: java string bytearray type-conversion

我从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);

有没有更好的方法来解决这个问题?

由于

6 个答案:

答案 0 :(得分:11)

可能为时已晚,但它可能对其他人有所帮助。您可以做的最简单的事情是new String(myBuffer).trim(),它可以为您提供您想要的内容。

答案 1 :(得分:7)

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字符。但是,您不能随意决定 - 您需要确保生成和使用此数据的所有内容都符合编码。

如果您控制协议,如果您可以在字符串之前引入长度前缀,那么它将更好 ,以指示编码形式中有多少字节。通过这种方式,您可以准确读取正确数量的数据(没有“过度读取”),并且您可以判断数据是否因某种原因被截断。

答案 2 :(得分:2)

Java中的字符串不会以0结尾,就像在其他一些语言中一样。 0将变为所谓的空字符,允许出现在字符串中。我建议你使用一些修剪方案,要么检测数组的第一个索引是0,并使用子数组来构造字符串(假设其余的后面都是0),或者只是构造字符串并调用{{ 1}}。这将删除前导和尾随空格,即ASCII代码为32或更低的任何字符。

如果您必须保留前导空格,后者将无效。只要它们是空字符,使用StringBuilder并在最后删除字符在这种情况下会更好。

答案 3 :(得分:2)

您始终可以从字节数组的末尾开始,然后向后搜索,直到达到第一个非零值。然后将其复制到一个新字节然后串起来。希望这会有所帮助:

    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的结果。

答案 4 :(得分:1)

在我看来,您忽略了read()方法返回的读取计数。可能没有发送尾随空字节,它们可能仍然从缓冲区的初始状态中遗留下来。

int count = in.read(buffer);
if (count < 0)
  ; // EOS: close the socket etc
else
  String s = new String(buffer, 0, count);

答案 5 :(得分:1)

不要深入研究原始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;
}