FileOutputStream在追加和覆盖之间切换

时间:2014-10-02 10:14:33

标签: java file-io fileoutputstream

我制作了一个简单的数据文件,其中只包含4个字节的标头。这4个字节定义了文件中存储的记录数。标题和记录都是预定义的大小,不能改变。

编辑:此记录也只包含4个字节。它只定义一个整数。 LINE_SEPERATOR = byte {'\ r','\ n'}

我的问题是,每次添加新记录(追加)时,我都需要覆盖标题(不附加),因为记录计数应该增加1。但是程序拒绝在它们之间切换,它只是坚持非追加模式。

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的事实,它会自动寻找到底。 calculateOffset方法用于将来的实现。

我做过实验,我每次都只写头。当设置为不附加时,它完美地工作。正如预期的那样,当它被设置为追加时,它将添加多个标题。

我在尝试添加4条记录后立即从我的文件中获得的结果只有2行。标题是完美的,它没有任何问题。但是,所有4条记录都写在下一行上,相互覆盖。

生成的调试文本:

  1. 写作记录@ 6
  2. 写作记录@ 12
  3. 写作记录@ 18
  4. 写作记录@ 24
  5. 阅读记录@ 6
  6. 3457
  7. 所有记录位置都是正确的,但'3457'是在同一行上覆盖所有4条记录的结果。

1 个答案:

答案 0 :(得分:1)

如果您想要写入文件中的多个点,您应该考虑使用专为此目的而设计的RandomAccessFile

更新:您还应该为所有写入使用相同的RandomAccessFile实例,而不是每次更新标题或内容时单独创建一个。