按偏移量读取文件,并打印16进制内容

在 Java 中,你可以使用 RandomAccessFileFileInputStream 来从指定偏移量(offset)读取指定长度的字节数据。以下是两种实现方式:

%02X 格式化输出16进制内容:https://www.cnblogs.com/vipsoft/p/16458095.html

MappedByteBuffer: https://www.cnblogs.com/vipsoft/p/16458161.html


方法 1:使用 RandomAccessFile(推荐)

RandomAccessFile 可以直接跳转到文件的指定位置进行读取,适合随机访问文件。

import java.io.IOException;
import java.io.RandomAccessFile;

public class ReadFileFromOffset {
    public static void main(String[] args) {
        String filePath = "your_file.bin"; // 替换为你的文件路径
        int offset = 10;                  // 起始偏移量
        int length = 2;                   // 要读取的字节数

        try (RandomAccessFile raf = new RandomAccessFile(filePath, "r")) {
            // 跳转到指定偏移量
            raf.seek(offset);

            // 读取指定长度的字节
            byte[] buffer = new byte[length];
            int bytesRead = raf.read(buffer);

            if (bytesRead != length) {
                System.err.println("未能读取足够字节,可能已到文件末尾");
            } else {
                System.out.println("读取的字节数据: " + bytesToHex(buffer));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 辅助方法:将字节数组转为十六进制字符串(方便查看)
    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02X ", b));
        }
        return sb.toString();
    }
}

方法 2:使用 FileInputStream

FileInputStream 也可以读取指定偏移量的数据,但需要手动跳过前面的字节。

import java.io.FileInputStream;
import java.io.IOException;

public class ReadFileFromOffsetWithStream {
    public static void main(String[] args) {
        String filePath = "your_file.bin"; // 替换为你的文件路径
        int offset = 10;                  // 起始偏移量
        int length = 2;                   // 要读取的字节数

        try (FileInputStream fis = new FileInputStream(filePath)) {
            // 跳过 offset 之前的字节
            long skipped = fis.skip(offset);
            if (skipped != offset) {
                System.err.println("无法跳过足够字节,可能文件太小");
                return;
            }

            // 读取指定长度的字节
            byte[] buffer = new byte[length];
            int bytesRead = fis.read(buffer);

            if (bytesRead != length) {
                System.err.println("未能读取足够字节,可能已到文件末尾");
            } else {
                System.out.println("读取的字节数据: " + bytesToHex(buffer));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 辅助方法:将字节数组转为十六进制字符串
    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02X ", b));
        }
        return sb.toString();
    }
}

关键点说明

  1. RandomAccessFile vs FileInputStream

    • RandomAccessFile 更适合随机访问(如频繁跳转偏移量)。
    • FileInputStream 适用于顺序读取,但也可以手动 skip() 到指定位置。
  2. seek(offset)skip(offset)

    • RandomAccessFile.seek(offset) 直接定位到 offset
    • FileInputStream.skip(offset) 跳过 offset 字节,但可能受流限制(如网络流可能无法跳过)。
  3. 字节读取

    • read(byte[]) 返回实际读取的字节数,可能小于请求的长度(如文件末尾)。
  4. 异常处理

    • 需处理 IOException(如文件不存在或权限问题)。
  5. 字节转十六进制

    • 示例代码提供了 bytesToHex() 方法方便查看字节数据(如 1A 2B)。

输出示例

如果文件 your_file.binoffset=10 处的 2 个字节是 0x410x42(即 ASCII 字符 AB),输出:

读取的字节数据: 41 42

适用场景

  • 读取二进制文件(如 .bin.dat)。
  • 解析文件头、特定偏移量的数据(如文件格式解析)。
  • 网络协议解析(如从固定位置读取字段)。

如果需要更复杂的文件操作(如内存映射),可以考虑 java.nioFileChannelMappedByteBuffer

posted @ 2025-04-30 09:28  VipSoft  阅读(87)  评论(0)    收藏  举报