You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中RandomAccessFile读写XML文件时读取数据异常求助

修复RandomAccessFile读写数据错位问题

问题描述

使用RandomAccessFile读写员工数据(文件命名为XML格式,但实际是二进制存储)时,仅第一行数据读取正确,后续行数据完全混乱。

写入代码

public static void main(String[] args) throws IOException {
    File file = new File("C:\\Test\\employee.XML");
    RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
    String nameEmp[] = {"Name A", "Name B", "Name C", "Name D", "Name E"};
    String addEmp[] = {"Address A", "Address B",
            "Address C", " Address D",
            "Address E"};
    int saleEmp[] = {2000,1232,7653,1236,3452};
    int comEmp[] = {400,100,3000,300,500};

    StringBuffer buffer;
    StringBuffer buffer1;


    for (int i=0;i< nameEmp.length; i++){
        randomAccessFile.writeInt(i+1);

        buffer = new StringBuffer( nameEmp[i]);
        buffer.setLength(10);
        randomAccessFile.writeChars(buffer.toString());

        buffer1 = new StringBuffer( addEmp[i]);
        buffer1.setLength(100);
        randomAccessFile.writeChars(buffer1.toString());


        randomAccessFile.writeInt(saleEmp[i]);
        randomAccessFile.writeInt(comEmp[i]);
    }
    randomAccessFile.close();
}

读取代码(原错误版本)

public static void main(String[] args) throws IOException {
    File file = new File("C:\\Test\\employee.XML");
    RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");

    int codeEmp, position = 0;
    char nameEmp[] = new char[10];
    char addEmp[] = new char [100];
    int saleEmp , comEmp;

    for(;;){
        randomAccessFile.seek(position);
        codeEmp = randomAccessFile.readInt();

        for (int i = 0; i < nameEmp.length; i++) {
            nameEmp[i] = randomAccessFile.readChar();
        }
        String nameEmpS= new String(nameEmp);

        for (int i = 0; i < addEmp.length; i++) {
            addEmp[i] = randomAccessFile.readChar();
        }
        String addEmpS= new String(addEmp);

        saleEmp =randomAccessFile.readInt();
        comEmp=randomAccessFile.readInt();

        System.out.println("Cod Emp: " + codeEmp + ", nombre: " +nameEmpS+ ", dirección: "+addEmpS+
                ", sale: " + saleEmp+ ", comisión: " + comEmp );

        position= position + 36;

        if (randomAccessFile.getFilePointer()==file.length())break;
    }
    randomAccessFile.close();
}

错误输出

Cod Emp: 1, nombre: Name A , dirección: Address A , sale: 2000, comisión: 400
Cod Emp: 7536672, nombre: A , dirección: Name B Ad, sale: 6553714, comisión: 6619251
Cod Emp: 0, nombre: , dirección: Ɛ Name B Address B , sale: 0, comisión: 0

问题根源

核心错误是手动维护的记录步长position +=36完全不符合实际每条记录的字节数:

  • writeInt每次写入4字节
  • writeChars写入的每个char占2字节,10个字符的名字占20字节,100个字符的地址占200字节
  • 两个writeInt共8字节
    单条记录总字节数:4 + 20 + 200 + 8 = 232字节,原代码用36作为步长,导致每次seek到错误位置,后续读取的数据完全错位。

修复方案

有两种可靠的修复方式:

方式1:自动跟踪文件指针,无需手动计算步长

直接通过getFilePointer()判断是否读取到文件末尾,去掉手动维护的position变量:

public static void main(String[] args) throws IOException {
    File file = new File("C:\\Test\\employee.XML");
    RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");

    int codeEmp;
    char nameEmp[] = new char[10];
    char addEmp[] = new char[100];
    int saleEmp, comEmp;

    // 通过文件指针位置判断是否读完所有记录
    while (randomAccessFile.getFilePointer() < file.length()) {
        codeEmp = randomAccessFile.readInt();

        // 读取名字
        for (int i = 0; i < nameEmp.length; i++) {
            nameEmp[i] = randomAccessFile.readChar();
        }
        String nameEmpS = new String(nameEmp).trim(); // 移除多余填充空格

        // 读取地址
        for (int i = 0; i < addEmp.length; i++) {
            addEmp[i] = randomAccessFile.readChar();
        }
        String addEmpS = new String(addEmp).trim();

        saleEmp = randomAccessFile.readInt();
        comEmp = randomAccessFile.readInt();

        System.out.println("Cod Emp: " + codeEmp + ", nombre: " + nameEmpS + ", dirección: " + addEmpS
                + ", sale: " + saleEmp + ", comisión: " + comEmp);
    }
    randomAccessFile.close();
}

方式2:使用正确的记录步长

如果坚持手动维护position,将步长改为正确的232字节:

// 替换原代码中的position更新逻辑
position = position + 232;

额外优化建议

  • 将记录的字节数定义为常量(如private static final int RECORD_SIZE = 232;),避免硬编码出错
  • 读取字符串后调用trim()移除写入时填充的多余空格,让输出更整洁

内容的提问来源于stack exchange,提问作者Tuan Do

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 03:20:32