Как определить конец строки в байтовом массиве для преобразования строки? - PullRequest
5 голосов
/ 04 ноября 2011

Я получаю из сокета строку в байтовом массиве, которая выглядит следующим образом:

[128,5,6,3,45,0,0,0,0,0]

Размер, указанный в сетевом протоколе, представляет собой общую длину строки (включая нули), поэтому в моем примере 10.

Если я просто сделаю:

String myString = new String(myBuffer); 

У меня в конце строки 5 неверный символ. Похоже, что преобразование не определяет конец символа строки (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 ]

11 голосов
/ 03 января 2013

Может быть, уже слишком поздно, но это может помочь другим.Самое простое, что вы можете сделать, это new String(myBuffer).trim(), который дает вам именно то, что вы хотите.

7 голосов
/ 04 ноября 2011

0 не является «символом конца строки».Это просто байт.Независимо от того, идет ли он только в конце строки, зависит от того, какую кодировку вы используете (и какой текст может быть).Например, если вы использовали UTF-16, каждый второй байт будет равен 0 для символов ASCII.

Если вы уверены , что первый 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");

Я настоятельно рекомендую не просто использоватьКодировка платформы по умолчанию - она ​​не переносимая и может не допускать использования всех символов Юникода.Однако вы не можете просто принять произвольное решение - вам нужно убедиться, что все, что производит и потребляет эти данные, согласуется с кодировкой.

Если вы управляете протоколом, это будет много лучше, если бы вы могли ввести префикс длины перед строкой, чтобы указать, сколько байтов находится в закодированной форме.Таким образом, вы сможете прочитать точно правильный объем данных (без «перечитывания») и сможете определить, были ли данные усечены по какой-то причине.

2 голосов
/ 04 ноября 2011

Вы всегда можете начать с конца байтового массива и идти назад, пока не дойдете до первого ненулевого значения. Затем просто скопируйте это в новый байт и затем String. Надеюсь, это поможет:

    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.

2 голосов
/ 04 ноября 2011

Строки в Java не заканчиваются на 0, как в некоторых других языках. 0 превратится в так называемый нулевой символ, который может появляться в строке. Я предлагаю вам использовать некоторую схему обрезки, которая либо обнаруживает первый индекс массива, равный 0, и использует подмассив для создания строки (при условии, что все остальное будет 0 после этого), либо просто создает строку и вызывает trim(). Это удалит начальные и конечные пробелы, которые являются любыми символами с кодом ASCII 32 или ниже.

Последний не будет работать, если у вас есть первые пробелы, которые вы должны сохранить. Использование StringBuilder и удаление символов в конце, если они являются нулевым символом, в этом случае будет работать лучше.

1 голос
/ 16 мая 2014

Чтобы не вдаваться в соображения протокола, о которых упоминал оригинальный 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;
}
1 голос
/ 04 ноября 2011

Мне кажется, что вы игнорируете счетчик чтения, возвращаемый методом read ().Завершающие нулевые байты, вероятно, не были отправлены, они, вероятно, все еще остались от исходного состояния буфера.

...