尝试从 Java 中的二进制文件中读取 Int 时出现 BufferUnderflowException

Posted

技术标签:

【中文标题】尝试从 Java 中的二进制文件中读取 Int 时出现 BufferUnderflowException【英文标题】:BufferUnderflowException while trying to read an Int from a binary file in Java 【发布时间】:2020-11-14 11:00:37 【问题描述】:

我正在尝试读取代表 int 的 4 个字节,位于二进制文件中的字节位置 64。

这是我尝试过的:

package testbinaryfile2;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

public class TestBinaryFile2 

    public static void main(String[] args) throws IOException 
        
            FileChannel fc;    
            ByteBuffer indexField = ByteBuffer.allocate(4);
            
            fc = (FileChannel.open(Paths.get("myBinaryFile.bin"), StandardOpenOption.READ));                        
            fc.position(64);
            fc.read(indexField);
            System.out.println(indexField.getInt());
            
    
            

这是我得到的错误:

run:
Exception in thread "main" java.nio.BufferUnderflowException
    at java.nio.Buffer.nextGetIndex(Buffer.java:509)
    at java.nio.HeapByteBuffer.getInt(HeapByteBuffer.java:373)
    at testbinaryfile2.TestBinaryFile2.main(TestBinaryFile2.java:30)
/home/user/.cache/netbeans/11.3/executor-snippets/run.xml:111: The following error occurred while executing this line:
/home/user/.cache/netbeans/11.3/executor-snippets/run.xml:94: Java returned: 1
BUILD FAILED (total time: 0 seconds)

【问题讨论】:

【参考方案1】:

读取后的indexField指向它的结尾,所以在获取int之前需要使用.rewind()方法。

此代码有效:

package testbinaryfile2;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

public class TestBinaryFile2 

    public static void main(String[] args) throws IOException 
        
            FileChannel fc;    
            ByteBuffer indexField = ByteBuffer.allocate(4);
            
            fc = (FileChannel.open(Paths.get("myBinaryFile.bin"), StandardOpenOption.READ));                        
            fc.position(64);
            fc.read(indexField);
            indexField.rewind();    // <-- ADD THIS
            System.out.println(indexField.getInt());
            
    
            

另外我得到了使用映射缓冲区的建议:

  public static void main(String[] args) throws Exception 
    FileChannel fc = (FileChannel.open(Paths.get("myBinaryFile.bin"), StandardOpenOption.READ));
    MappedByteBuffer buffer = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
    buffer.position(64);
    System.out.println(buffer.getInt());
  

但我想知道fc.map 是否一次读取整个文件并使用与文件大小一样多的内存。

【讨论】:

以上是关于尝试从 Java 中的二进制文件中读取 Int 时出现 BufferUnderflowException的主要内容,如果未能解决你的问题,请参考以下文章

java读取二进制文件

尝试从文件中读取矢量时出错

使用 c++ 时从二进制文件中读取 int 不正确

从 C++ 中读取文件时动态分配内存给结构

用C++写的二进制文件,用JAVA怎么读取?

在 C++ 中为结构读取二进制文件的运行时错误