【问题标题】:Write specific line into file将特定行写入文件
【发布时间】:2026-02-08 03:05:02
【问题描述】:

我正在尝试将行写入行位置 n 的文件中。

即使第 n 行不存在。在这种情况下,文件必须以空行增长才能达到 n。基本上类似于writer.writeLine(n, mycontent)。 mycontent 是来自ObjectOutputStream 的二进制表示。文件的每一行都包含一个序列化对象。行号是索引。

如何写入特定行? - 不使用 FileUtils 或任何非标准 API 组件。

This answer 几乎总结了我想要的东西——但在写作时,它的表现似乎有所不同。

编辑:由于cmets,我澄清了我的问题

【问题讨论】:

  • BufferedWriter 包装到 ObjectOutputStream 中?你能澄清一下吗?
  • 你的问题很不清楚。 ObjectOutputStream 将写入二进制数据 - ObjectOutputStream 中没有“线”这样的概念。
  • 抱歉,我更新了我的问题。我使用行号作为索引再次从“容器”文件中查找序列化对象。问题是如果行号是索引,我必须能够选择在文件中写入的位置。而且我不想完全缓存它。

标签: java file-io


【解决方案1】:

线的概念对你来说很重要吗?否则,您可能会在文件中序列化 Map,并使用它在特定索引处写入或读取对象(在这种情况下,索引将是映射的键)。

这是一个小例子。

    public static void main(String[] args) throws Exception {
    ObjectOutputStream tocStream = new ObjectOutputStream(new FileOutputStream("myfile.toc"));
    Map<Integer,Object> tableOfContent = new HashMap<Integer, Object>();
    String myString = "dataOne";
    Date myDate = new Date();
    tableOfContent.put(0,myDate);
    tableOfContent.put(1,myString);
    tocStream.writeObject(tableOfContent);
    tocStream.flush();
    tocStream.close();
    ObjectInputStream tocInputStream = new ObjectInputStream(new FileInputStream("myfile.toc"));
    Map<Integer,Object> restoredTableOfContent = (Map<Integer, Object>) tocInputStream.readObject();
    Object restoredMyString  =  restoredTableOfContent.get(1);
    System.out.println(restoredMyString);
    tocInputStream.close();
}

【讨论】:

  • 我想避免重写。似乎是不可能的......我不确定如何实现对包含序列化对象的文件的更新。它可能会变大。我仍然认为这是领先的。谢谢。
【解决方案2】:

这不起作用,因为每个序列化对象可能包含一个或多个换行符作为其二进制表示的一部分。因此,如果您在第 3 行编写一个新对象,您很可能将这个对象写在第一个二进制表示的中间。 测试一下:

public class OOSTest {
    public static void main(String[] args) throws IOException {
        String s = "Hello\nWorld";
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(s);
        oos.flush();
        oos.close();
        System.out.println(new String(bos.toByteArray()));
    }
}

恕我直言,您有三个选择:

  1. 选择适用于二进制数据的协议(例如:对于每个对象,将其长度(以字节为单位)写入一个整数(4 个字节),然后是对象本身的字节;
  2. 将序列化的字节编码为字符串,例如使用 Base64,并在对象之间使用不属于编码一部分的分隔符;
  3. 使用 ObjectOutputStream 序列化对象数组。编写新条目包括反序列化数组,确保它具有正确的大小或将其复制到适当大小的新数组,将对象插入其位置,然后重新序列化整个数组。

【讨论】:

  • 这仍然没有说明我如何在特定的行位置写...它似乎变得非常复杂。
【解决方案3】:
  • 循环读取文件 当前值。
  • 写出每个值 到一个新的临时文件。
  • 如果旧文件 在您的行号保留之前结束 写出空行。
  • 然后一次 你得到你想要的行号 更新写出新数据。
  • 如果有更多行到老 文件继续写。
  • 删除旧的 文件。重命名临时文件。

【讨论】:

  • 真的有必要吗?我不想仅仅因为一个变化就重写所有内容。
  • 是的。这就是为什么存储数据的数据库或其他结构可能是更好的选择。
  • 有什么简单的建议吗?我没有这方面的经验,我不想遇到太复杂的情况。
  • 数据库会是更好的选择,但确实会增加复杂性。如果这是您要存储的唯一数据,我会在每次需要保存数据时使用此文件并重建它。只要文件不是超级大,这不应该是性能问题。