Разбор байтового массива, связывающего поля неизвестной длины - PullRequest
6 голосов
/ 24 февраля 2011

Я разбираю в Java байтовый массив, имеющий следующую спецификацию:

Trace data format:
    - 4 bytes containing the Id.
    - 4 bytes containing the address.
    - N bytes containing the first name, where 0 < N < 32
    - N bytes containing the last name, where 0 < N < 32
    - 4 bytes containing the Minimum
    - 4 bytes containing the Maximum 
    - 4 bytes containing the Resource Default Level

Сегодня я не вижу никакого решения для анализа этого массива, чтобы получить 7 переменных с правильным типом.Вы подтверждаете или я пропускаю что-то вроде магической функции в Java, позволяющей находить «ограничения» строк в байтовом массиве (я не вижу, как значение Minimum можно отличить от ассоциированного с ним символа ASCII).

Есть ли какое-либо "соглашение" о специальном символе между двумя строками?

Ответы [ 5 ]

12 голосов
/ 24 февраля 2011

Ну, вы знаете, что имя начинается с байта 9, а фамилия заканчивается байтом (длина-13). Неопределенным является то, как найти, где заканчивается имя и начинается фамилия. Я вижу несколько возможных решений:

  • Если формат был определен программистом C, два поля имени, скорее всего, заканчиваются нулевым байтом, так как это соглашение C для строк.
  • Если он был определен программистом Java, его можно записать как writeUTF(), что означает, что спецификация количества байтов, скорее всего, неверна. Однако это, по крайней мере, определяет кодировку, которая в остальном является открытым вопросом.
  • Если это было определено программистом на языке COBOL, два поля могут быть фиксированной длины и дополнены нулями или пробелами, причем в спецификации формата указывается длина полезной нагрузки, а не длина поля.
  • Если он был определен действительно некомпетентным программистом (независимо от языка), он содержит два имени без разделителя или счетчика, поэтому невозможно их реально разделить (если у вас нет информации, нет «волшебства») функция в Java или в другом месте, которое может вызвать его из воздуха). Я полагаю, вы могли бы надеяться, что фамилия всегда начинается с заглавной буквы, и никто не использует двойные имена или заглавные буквы.
5 голосов
/ 24 февраля 2011

Есть ли какое-либо "соглашение" о специальном символе между двумя строками?

Ну c-строки часто заканчиваются нулем \0.

Если такого символа нет, я бы сказал, что невозможно разобрать структуру.

3 голосов
/ 24 февраля 2011

Если имя и фамилия оканчиваются нулем, вы бы сделали это так:

int firstNameLength = 0;
while(firstNameLength<32) {
    if(theArray[firstNameLength]=='0') break;
    firstNameLength++;
}
int lastNameLength = 0;
while(lastNameLength<32) {
    if(theArray[8+firstNameLength+1+lastNameLength]=='0') break;
    i++;
}
String firstName = new String(theArray).substring(8,8+firstNameLength);
String lastName = new String(theArray).substring(8+firstNameLength+1,8+firstNameLength+1+lastNameLength);
2 голосов
/ 24 февраля 2011

, если вы хотите прочитать N ASCII байтов и превратить их в строку.

public static String readString(DataInputStream dis, int num) throws IOException {
    byte[] bytes = new byte[num];
    dis.readFully(bytes);
    return new String(bytes, 0);
}

Для остальных значений вы можете использовать

dis.readInt();

Если вы спрашиваетеЕсли есть какой-либо способ узнать, как долго строки, я не думаю, что вы можете определить это по предоставленной информации.Возможно, строки заканчиваются байтом '0' или имеют длину в качестве первого байта.Возможно, если вы посмотрите на байты в файле, вы увидите, что это за формат.

od -xc my-format.bin
0 голосов
/ 20 августа 2013

Просто чтобы добавить еще одну возможность для ответа Майкла.

Предполагая, что N одинаково для обоих полей, и поскольку используется одна и та же буква, я бы предположил, что это так, положения полейбыть таким:

int len = array.length;
int varLen = len - 5*4;
int fieldPos[] = new int[7];
fieldPos[0] = 0;
fieldPos[1] = 4;
fieldPos[2] = 8;
fieldPos[3] = 8 + varLen;
fieldPos[4] = 8 + 2*varLen;
fieldPos[5] = 8 + 2*varLen + 4;
fieldPos[6] = 8 + 2*varLen + 8;
...