我制作了一个简单的数据文件,其中仅包含4个字节的标头。这4个字节定义了文件中存储了多少条记录。标头和记录均具有预定义的大小,并且不能更改。
编辑:记录也只包含4个字节。其中只定义一个整数。
LINE_SEPERATOR =字节{'\ r','\ n'}
我的问题是,每次添加新记录(追加)时,都需要覆盖标头(而不是追加),因为记录数应增加一。但是该程序拒绝在它们之间切换,并且只坚持使用非附加模式。
addRecord代码:
public void addRecord(ISaveable record)
throws IllegalArgumentException, FileNotFoundException, IOException
{
if(record == null)
{
throw new IllegalArgumentException("The given record may not be null");
}
this.header.increaseRecordCount();
writeHeader();
FileOutputStream oStream = null;
try
{
oStream = new FileOutputStream(DEFAULT_DIR, true);
long offset = calculateOffset(this.header.getRecordCount() - 1, record.getSize());
System.out.println("writing record @ " + offset);
oStream.getChannel().position(offset);
PacketOutputStream pOut = new PacketOutputStream();
record.Save(pOut);
pOut.writeBytes(END_LINE);
oStream.write(pOut.Seal());
}
catch(FileNotFoundException ex)
{
throw ex;
}
catch(IOException ex)
{
throw ex;
}
finally
{
if(oStream != null)
{
oStream.flush();
oStream.close();
}
}
}
writeHeader代码:
private void writeHeader()
throws IOException
{
FileOutputStream oStream = null;
try
{
oStream = new FileOutputStream(DEFAULT_DIR, false);
oStream.getChannel().position(0);
PacketOutputStream pOut = new PacketOutputStream();
this.header.Save(pOut);
pOut.writeBytes(END_LINE);
oStream.write(pOut.Seal());
}
catch(IOException ex)
{
throw ex;
}
finally
{
if(oStream != null)
{
oStream.flush();
oStream.close();
}
}
}
如您所见,我在FileOutputStream的构造函数中正确使用了布尔值。将writeHeader设置为false(因为我想覆盖现有的标头),将记录设置为true(因为应将其添加到文件的末尾)。请忽略设置为true会自动搜索到最后的事实。 computeOffset方法用于将来的实现。
我做了实验,每次只写标题。设置为不追加时,它可以完美工作。如预期的那样,当设置为追加时,它将添加多个标题。
尝试添加4条记录后,我现在从文件中得到的结果只有2行。标头是完美的,没有任何问题。但是,所有4条记录都写在下一行,彼此覆盖。
产生的调试文本:
写作记录@ 6
写作记录@ 12
写作记录@ 18
写作记录@ 24
阅读记录@ 6
3457
所有记录位置均正确,但是“ 3457”是在同一行上覆盖所有4条记录的结果。
最佳答案
如果要写入文件中的多个点,则应真正考虑使用为此目的而设计的RandomAccessFile
。
更新:您还应该对所有写入使用相同的RandomAccessFile
实例,而不是每次更新标题或内容时都单独创建一个实例。
关于java - FileOutputStream在追加和覆盖之间切换,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26158728/