正在从文件中读取第n个元素

Reading the nth element from a file

本文关键字:元素 读取 文件      更新时间:2023-10-16

我有一个包含一列数字的文本文件。列中大约有500个数字。我怎么会只读第n个数字呢。例如,有没有一种方法可以读取并存储列中的第49个数字?

如果数字是固定大小的(您没有显示示例文件),那么您可以查找大小*n并读取。否则,只需执行读取、解析、计数循环,直到达到n

如果它们被存储为文本,因此每个数字所占的空间可能会有所不同,那么你几乎只能通读它们,直到找到正确的点,或者使用间接级别——也就是说,为数据本身创建索引。

对于前者,您可以(例如)将每个数字存储为32位二进制数字。在一台典型的机器上,这意味着每个数字都占用4个字节,所以在第N项中,将N乘以4,找到文件中的那个点,然后读取4个字节。

如果你想将数字存储为文本,但仍然支持这样的搜索,你可以用空格填充每个数字,这样它们在文件中仍然占据相同的空间(例如,每个数字10个字符)。

如果你真的想避免这种情况(或者有一个预定义的格式,所以你不能这样做),那么你可以在文件中创建一个索引。当/如果您能够证明读取整个文件和存储每一行开头的位置的成本时,这是有意义的。至少有两个明显的理由。一种是索引可以与使用分离,例如在晚上批量构建索引,以优化白天的数据使用。另一种可能性是,您对数据文件的使用量足够大,以至于能够搜索到特定点所节省的时间超过了对文件进行一次索引所需的时间。

不过,也有一些不太明显的理由——例如,您可能需要满足一些(至少是软的)实时约束,如果您通读文件以找到每一项,则可能无法满足这些约束——特别是,您可以处理的文件大小可能会受到实时约束的限制。在这种情况下,为了满足您的需求,索引可能是绝对必要的,而不仅仅是优化。

在@pm100的答案中添加详细信息(可能不必要),固定大小意味着相同的ascii计数。

001
01

001占用3个字节,而01仅占用2个字节。因此,如果你的文件有这样格式的数字:

1
2
3
100
10

只有当每一列条目的每一行都有相同数量的ASCII字符时(据我所知),才可以使用lseek(或fseek)。如果你也走这条路,你还需要跟踪n字符。lseek(fd, size * n * 2);

您可以这样做:

ifstream fin("example.txt");
std::string line;
for(size_t i = 0; i < n; ++i) {
  std::getline(fin, line);
}
// line contains line n;