我应该如何将 POJO 表示写入 RandomAccessFile?

How should I write a POJO representation to a RandomAccessFile?

我有一个 POJO,其中有多个 String 字段。我想将此对象的实例(按自然顺序排序)写入 RandomAccessFile,然后最终在该文件中搜索我需要的对象。

问题是我不太确定如何解决这个问题 - 例如,在纯文本文件中,我会用新行来分隔新的对象实例。使用 RandomAccessFile 时,我是否应该使用对象的大小(以字节为单位)来指示文件中的新对象 - 如果我知道我想要第二个对象,我会在文件中查看 2 个对象的字节数?

我遵循了将排序 integers 写入文件的教程 - 如果我想找到第二次出现的地方,我会在文件中查找 8 个字节。我应该对我的 POJO 应用相同的逻辑吗?还是我可以只使用 new line 进行分隔?

编辑*这些是我对象的字段:

import java.io.FileWriter;
import java.io.IOException;
import java.io.Serializable;

/**
 * A RegradeRule is an individual rule found in the Regrade .dat file (one
 * line).
 * 
 * @author E Rowlands
 */
public class RegradeRule implements Serializable,  Comparable<RegradeRule> { 

    private String privateData;
    private String privateData;
    private String privateData;
    private String privateData;
    private String privateData;
    private String privateData;
    private String privateData;
    private String privateData;
    private String privateData;
    private String privateData;
    private String privateData;
    private String privateData;

    // getters & setters
}

将可变长度记录放入随机访问文件有两种主要策略。

  1. 为所有记录选择一个固定的最大长度并乘以该值以找到所需的字符串。 您将需要选择一个 null 字符来填充每条记录的未使用部分,在读取时将其删除并在写入时将其添加为填充。
  2. 维护每个字符串(在文件或内存中)的开头和长度的索引,并通过该索引传递每个文件访问。 维护文件中的索引可能很棘手,尤其是当您需要添加更多记录时。您可能更喜欢使用第二个文件作为索引或在每次打开文件时重建它。

各有各的优势。 (1) 不需要索引但会显着增加文件大小。 (2) 不会增大文件大小但需要维护索引。

您有几种通用的实现方法:

  • 使用固定长度的字符串 - 确定您的字符串具有特定的最大长度,并用一些未使用的字符(例如,零)填充您写入该长度的所有字符串.如果要允许超过 127 的 Unicode 代码点,则需要处理字符串的编码。
  • 在文件顶部或单独的文件中写入索引 - 在文件顶部添加单独的数据块以帮助您导航到正确的项目.这种方法使得文件难以超出一定限制,因为内容需要复制或读入内存以进行扩展。
  • 如果您总是一次获取整个文件,请不要使用 RandomAccessFile - 这是最简单的实现方法,您会得到一个 human-viewable/editable文本文件。这种方法的缺点是您无法在不阅读其余项目的情况下导航到特定项目。

您可以为您的 POJO 提供一个 one-line csv-formatted toString() 方法,并始终将其作为单行写入您的随机访问文件。

public class RegradeRule implements Serializable,  Comparable<RegradeRule> { 

    private String privateData;
    private String privateData;
    private String privateData;
    private String privateData;
    private String privateData;
    private String privateData;
    private String privateData;
    private String privateData;
    private String privateData;
    private String privateData;
    private String privateData;
    private String privateData;

    // getters & setters

    @override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(privateData);
        sb.append(";");
        sb.append(privateData);
        sb.append(";");
        // do that until your last String attribute and then the last one without a semicolon
        sb.append(privateData);
        return sb.toString();
    }
}

这样做会写入一个 csv 文件(您可以在其中提供 header 行)。