我制作了一个简单的数据文件,其中仅包含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/

10-10 12:49