writeInt(Integer)覆盖零

时间:2019-02-25 17:25:16

标签: java file randomaccessfile

我使用RandomAccessFile类,尝试测试在Java中向文件写入/从文件读取的概念。所以我尝试了这段代码:

public static void main (String[] args) throws IOException {
        RandomAccessFile storage = new RandomAccessFile("FILE.txt", "rw");

        storage.seek(0);
        storage.writeInt(1);

        storage.seek(1);
        storage.writeInt(2);

        storage.seek(2);
        storage.writeInt(3);

        storage.seek(3);
        storage.writeInt(4);

        storage.seek(4);
        storage.writeInt(5);

        System.out.println(storage.readInt());
        System.out.println(storage.readInt());
        System.out.println(storage.readInt());
        System.out.println(storage.readInt());
        System.out.println(storage.readInt());

        storage.close();

我认为它应该打印: 1个 2 3 4 5

但是会发生以下情况: 3 4 5 EOFException ...为什么?

2 个答案:

答案 0 :(得分:1)

这里有2个问题-您不允许每个int写入4个字节,并且在将int读回内存时也没有寻找文件的开头。

首先,seek方法将字节数的参数作为文件的偏移量。

  

pos-从文件开头算起的偏移位置,以字节为单位设置文件指针。

但是在Java中,int有4个字节,因此每次后续写入操作都将覆盖前int的4个字节中的3个。每次以后都将标记显式设置为4个字节:

storage.seek(4);
storage.writeInt(2);

storage.seek(8);
storage.writeInt(3);

// etc.

甚至更容易地,标记“做正确的事”并向前移动适当数量的字节。只需在此处忽略seek

storage.writeInt(1);
storage.writeInt(2);
storage.writeInt(3);
storage.writeInt(4);
storage.writeInt(5);

第二个问题是,当回读字节时,您不会将标记重设回文件的开头,从而导致EOFException。添加对seek(0)的调用,以将标记发送回文件的开头。

storage.seek(0);

System.out.println(storage.readInt());
System.out.println(storage.readInt());
System.out.println(storage.readInt());
System.out.println(storage.readInt());
System.out.println(storage.readInt());

然后我得到输出:

1
2
3
4
5

答案 1 :(得分:0)

我在这里看到两个问题:

  1. 在最后一次写入和第一次读取之间不会出现seek的情况,因此您要在上次写入的位置结束之后开始读取。 (事实上​​,您没有立即得到EOFException,这表明在此程序运行开始时文件不为空。)
  2. seek接受表示字节位置的参数,但是writeIntreadInt写入和读取四个字节。因此,如果您不希望整数相互重叠,则需要查找0、4、8等位置,而不是0、1、2等位置。(尽管发生了这种情况,如果您的目标是使整数相邻,则实际上需要您当前对seek的调用。)