2013-11-21 7 views
1

Я хочу преобразовать код C в Java. Она считывает двоичный файл:Java read двоичный файл (unsigned long long)

int main(int argc, char**argv) 
{ 
    FILE *fd; 
    unsigned long trameNumber = 0; 
    unsigned long long INDEX; 

    fd = fopen(argv[1],"rb"); 
    if (fd == NULL) 
    { 
     printf("Usage %s [File]\n", argv[0]); 
     exit(1); 
    } 

    fread(&INDEX, sizeof(INDEX),1, fd); 
    printf("INDEX %llx\n",INDEX); 
    trameNumber++; 

    while (fread(&INDEX, sizeof(INDEX),1, fd) != 0) 
    { 
     printf("INDEX %llx\n",INDEX); 
     trameNumber++; 
    } 

    fclose(fd); 
    printf("%lu", trameNumber); 

    return 0; 
} 

Выход с этим кодом выглядит следующим образом:

INDEX 0 
INDEX 9800000000000000 
INDEX 1801000000000000 
INDEX 5001000000000000 
INDEX b801000000000000 

Вот мой Java-код. Я пытался сделать это с BigInteger:

public static final int DATA_BYTE_LENGHT = 8; 

public void readBinary(final String readFilePath) 
{ 
    // A 8 byte buffer = 64 bits 
    ByteBuffer byteBuffer = ByteBuffer.allocate(DATA_BYTE_LENGHT); 

    // Those channels will be used to read/write files 
    FileChannel channelFileInput = null; 

    BigInteger bigIndex = null; 

    try { 

     // File to read 
     final File fileRead = new File(readFilePath); 

     // Channel used to read the file. 
     channelFileInput = new FileInputStream(fileRead).getChannel(); 

     byteBuffer.put(new byte[DATA_BYTE_LENGHT]); 
     byteBuffer.rewind(); 

     // While the file has content 
     while(channelFileInput.read(byteBuffer) != -1) { 

      byteBuffer.rewind(); 

      // Big integer positive 
      bigIndex = new BigInteger(1, byteBuffer.array()); 

      byteBuffer.rewind(); 

      System.out.println("INDEX "+bigIndex.toString(16)); 

      // Clear the buffer 
      byteBuffer.put(new byte[DATA_BYTE_LENGHT]); 
      byteBuffer.rewind(); 

     } 

    } catch(FileNotFoundException e) { 
     System.err.println("The file cannot be read: "+e.getMessage()); 
    } catch(Exception e) { 
     System.err.println(e.getMessage()); 
    } finally { 
     // Close file connections 
     IOUtils.closeQuietly(channelFileInput); 
    } 
} 

Однако read(), кажется, не правильно прочитать файл. Поскольку выходной сигнал:

INDEX 0 
INDEX 98 
INDEX 118 
INDEX 150 
INDEX 1b8 

Может быть проблема с энзидиантой? Как его решить?

Благодаря

ответ

1

Конструктор BigInteger принимает представление в виде большого конца, в то время как данные в файле, по-видимому, хранятся в little-endian. Чтобы устранить эту проблему, вы можете поменять местами байты в массиве, которые Вы получаете, или использовать order метод в ByteBuffer установить порядок следования байтов и использовать тип данных long:

// before loop 
byteBuffer.order(ByteOrder.LITTLE_ENDIAN); 

// in loop 
long bigIndex = byteBuffer.getLong(); 
byteBuffer.rewind(); 
System.out.println("INDEX "+Long.toHexString(bigIndex)); 

тип long данных в Java подписанную хотя. Это может быть или не быть проблемой в зависимости от того, что вы хотите делать с цифрами впоследствии.

Update: Если вы должны использовать BigInteger вы можете просто реверс массив байтов, как я уже говорил ранее, или читать числа, используя long, а затем исправить знак:

BigInteger bi = BigInteger.valueOf(bigIndex & ~Long.MIN_VALUE); 
if (bigIndex < 0) bi = bi.setBit(63); 
+0

Да Я пробовал это решение с помощью 'order()', но у меня был тот же результат. И, как вы можете видеть в моем вопросе (код на C++), мои номера, к сожалению, неподписанны. – Maxbester

+0

Подписанные и неподписанные числа отличаются только тем, как наиболее значимый бит обрабатывается в таких операциях, как сравнение и деление, для большинства целей, независимо от того, используете ли вы подписанный или неподписанный, нет никакой разницы. Метод 'order()' не влияет на поведение 'array()', вам нужно использовать 'getLong()' и подобные методы, чтобы увидеть разницу, которую он делает. – Joni

+0

Хорошо, я не знал, что мне пришлось преобразовать его в длинный, чтобы использовать 'order()'. Спасибо – Maxbester

0

Java определяет все примитивные типы данных, как с помощью большой Endian. Если вы работаете на платформе x86 (windows или linux или OSX), ваш компьютер, скорее всего, использует немного endian. Эндианс, вероятно, является причиной вашего несчастья. Вероятно, вы можете решить проблему, используя операции маски и сдвига, чтобы отменить порядок байтов. Ответ на это фактически дается в this answer

+0

спасибо за ссылку. Для записи Apache Commons IO предлагает очень хороший инструмент для устранения проблем с контентом: ['EndianUtils'] (http://commons.apache.org/proper/commons-io/javadocs/api-2.4/). – Maxbester

Смежные вопросы