Преобразование шестнадцатеричного файла в unsigned int 32 Big-Endian в Java

#java #integer #endianness

#java #целое число #порядковый номер

Вопрос:

Возможно, это уже заданный вопрос, но я пока не нашел удовлетворительного ответа. В частности, потому, что это преобразование всегда выполнялось на c или C .

Кстати, как преобразовать шестнадцатеричный файл (200 МБ) в его UINT32 Big-endian представление в Java?

Это пример того, чего я пытаюсь достичь:

 54 00 00 00  -> 84       
55 F1 2E 04  -> 70185301
A2 3F 32 01  -> 20070306  
and so on
  

Редактировать

 File fileInputString = new File(inputFileField.getText());
FileInputStream fin = new FileInputStream(fileInputString); 
FileOutputStream out = new FileOutputStream(fileDirectoryFolder.getText()  "/"  fileInputString.getName());
byte[] fileContent = new byte[(int)fileInputString.length()];
fin.read(fileContent);
System.out.println("File Lenght"   fileContent.length);
for(int i = 0; i < fileContent.length; i  ){
Byte b = fileContent[i]; // Boxing conversion converts `byte` to `Byte`
int value = b.intValue();
out.write(value);
}
close();                                            
System.out.println("Done"); 
  

РЕДАКТИРОВАТЬ 2

 File fileInputString = new File(inputFileField.getText());
FileInputStream fin = new FileInputStream(fileInputString); 
FileOutputStream out = new FileOutputStream(fileDirectoryFolder.getText()  "/"  fileInputString.getName());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] fileContent = new byte[(int)fileInputString.length()];
System.out.println("File Lenght"   fileContent.length);
int bytesRead;
while (( bytesRead = fin.read(fileContent)) != -1) {
ByteBuffer.wrap(fileContent).order(ByteOrder.LITTLE_ENDIAN).getLong();
bos.write(fileContent, 0, bytesRead);
}
out.write(bos.toByteArray()); 
System.out.println("Done"); 
  

РЕДАКТИРОВАТЬ 3

 DataOutputStream out = new DataOutputStream(new FileOutputStream(output)); 
DataInputStream in = new DataInputStream(new FileInputStream(input))) {
int count = 0;        

while (count < input.length() - 4) {
    in.readFully(buffer, 4, 4);
    String s=Long.toString(ByteBuffer.wrap(buffer).order(ByteOrder.LITTLE_ENDIAN).getLong());
    out.writeBytes( s   " ");
    count  = 4;
}
  

Спасибо

Комментарии:

1. можете ли вы показать нам, что вы пробовали до сих пор?

2. Java не имеет целочисленного типа без знака. Как вы планируете хранить данные? Вы могли бы использовать long .

3. @SpringLearner См. Редактирование

4. Данные вашего примера искажены на одну строку? Разве «54 00 00 00» не должно читаться как 84?

5. Я использовал этот веб-сайт для преобразования данных, и информация, которую я ожидаю найти, находится в UINT32 — Big Endian (ABCD)

Ответ №1:

Надеюсь, следующего кода будет достаточно. Он использует long значения, чтобы гарантировать, что мы можем полностью представить диапазон положительных значений, которые могут представлять четыре байта.

Примечание: этот код предполагает, что шестнадцатеричный ввод равен четырем байтам. Возможно, вы захотите добавить еще несколько проверок и мер в рабочий код.

 private static long toLong(String hex) {
    hex = hex.replace(" ", "")   "00000000";
    byte[] data = DatatypeConverter.parseHexBinary(hex);
    return ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN).getLong();
}

public static void main(String[] args) throws Exception {
    System.out.println(toLong("54 00 00 00"));
    System.out.println(toLong("55 F1 2E 04"));
    System.out.println(toLong("A2 3F 32 01"));        
    System.out.println(toLong("FF FF FF FF"));
}
  

Вывод:

84
70185301
20070306
4294967295

Основываясь на ваших недавних правках, я предлагаю некоторый код, например, следующий. Обратите внимание, что предполагается, что длина вашего ввода кратна четырем байтам. Любые оставшиеся байты игнорируются:

 File input = new File("whatever");

byte[] buffer = new byte[8];
List<Long> result = new ArrayList<>();

try (DataInputStream in = new DataInputStream(new FileInputStream(input))) {
    int count = 0;        

    // Note: any trailing bytes are ignored
    while (count < input.length() - 4) {
        in.readFully(buffer, 4, 4);
        result.add(ByteBuffer.wrap(buffer)
                .order(ByteOrder.LITTLE_ENDIAN).getLong());
        count  = 4;
    }
}
  

Комментарии:

1. Спасибо, я попытался изменить ваш код в соответствии со своими потребностями, но я столкнулся со многими проблемами. Как вы можете видеть в моем вопросе, мне нужно импортировать данные, которые представлены в шестнадцатеричном формате, но на практике это двоичный код, и преобразовать его в читаемый формат (возможно, строка). ваша функция получает в качестве входных данных шестнадцатеричные файлы, а не двоичные файлы. можете ли вы помочь мне понять, как это сделать

2. @QuentinTanioartino Проверьте редактирование выше. Это демонстрирует, как использовать входной поток в четырехбайтовых блоках и выполнять преобразование.

3. Моя проблема заключается не в импорте данных, а в их записи в новый файл

4. @QuentinTanioartino Итак, как вы хотите, чтобы выглядел ваш выходной файл? Разделенные пробелом значения int, например: 84 70185301 20070306 ?

5. @QuentinTanioartino Вы не можете понять, как добиться этого из моего ответа? Вместо добавления в список просто выведите строку в файл, за которым следует пробел. На самом деле я здесь не для того, чтобы предоставить вам именно тот код, который вы хотите 🙂

Ответ №2:

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

 Big Endian:    12 34 56 78
Little Endian: 78 56 34 12
  

Итак, если вы делали это во время обработки InputStream, прочитайте четыре байта и запишите их для вывода в обратном порядке.

Комментарии:

1. В моем конкретном случае я немного запутался между кодировкой необработанного файла и представлением необработанного файла. когда я импортирую данные в поток, это двоичные данные, но когда я визуализирую их в редакторе, они представлены в шестнадцатеричной записи. Мне нужно извлечь данные, поэтому я думаю, что мне нужно не только поменять местами биты, но только преобразовать их в строку. Что вы думаете о моем заявлении?

2. @QuentinTanioartino Опубликованный вами код не показывает ничего, связанного с преобразованием строк, и о каком редакторе вы говорите? Из всего вашего вопроса я не могу сказать, какую проблему вы пытаетесь решить.