我应该使用哪些类型/函数来跟踪随机访问的文件位置?

What types/functions should I use to track a file position for random access?

提问人:Tsvi Benschar 提问时间:6/13/2023 更新时间:6/13/2023 访问量:71

问:

我正在尝试实现一种简化的 Boyer-Moore 字符串搜索算法,该算法从文件中读取其输入文本。该算法要求我从给定的文件位置开始,向后读取其字符,定期向前跳转预先计算的字符数。跳转是根据模式的长度和索引计算的,因此我将它们存储为 类型 。我应该使用什么函数来读取特定位置的文件字符,我应该使用什么类型来存储这些位置?我是 C 的新手,但这些是我考虑过的选项:size_t

Fseek

我可以使用 和 在文件中跳转,但这使用 a 作为其字符索引。我不知道在 this 和 a 之间转换是否安全,无论如何,出于可移植性的原因,GNU C 手册建议不要搜索文本流fseekgetclong intsize_t

Fsetpos

这应该更便携,但我认为我不能用它来向前或向后跳转任意数量的字符。

二进制流

我可以通过将文件作为二进制流打开来解决兼容性问题。但我不知道这是否会导致在处理模式/输入文本时出现其他兼容性问题,无论如何,这并不能解决 和 之间的强制转换问题。fseeklong intsize_t

文件描述符

我可以使用文件描述符而不是流。但是我需要在 和 之间转换,我不知道这有多安全。我也会放弃 的缓冲,我不确定这是否可取。我可以尝试滚动自己的缓冲,或者使用备用库,但这似乎是一个巨大的痛苦。size_toff_tFILE

我的第一个实现将输入文本作为命令行参数传递,因此它根本不处理文件 IO。但我认为这不适用于大型文本输入,而且我阅读的有关文件 IO 的信息越多,我就越觉得卡住了。你有什么建议?

C 文件 io stdio fseek

评论

1赞 Shawn 6/13/2023
我只是它或将整个文件读入新分配的内存中。mmap()
0赞 Shawn 6/13/2023
(或不向后看的搜索算法)
0赞 Andrew Henle 6/13/2023
您的问题中缺少很多信息,这些信息可以帮助您获得更好的答案。您的输入文件有多大?线路有多长(如果有的话)?您运行的是什么操作系统?您的代码是否需要移植到其他操作系统?
1赞 Tsvi Benschar 6/13/2023
@AndrewHenle 我计划在尽可能大的输入文件上进行测试。我不是在对行长做出假设。我正在运行 x64 linux,但我想使代码可移植,因为我正在尝试学习一般的 C。
0赞 Eric Postpischil 6/13/2023
搜索字符串可以有多长?如果最多是 ,则无论文件长度如何,您都可以使用 。Boyer-Moore 不会要求您重新定位大于弦长的距离。(无论如何,为了便于移植,您应该以二进制文件的形式打开文件,以避免查找问题。LONG_MAXfseekSEEK_CUR

答:

3赞 ikegami 6/13/2023 #1

size_t转换

如果对于文件偏移量足够大,并且您的值表示文件偏移量,则在这两者之间进行转换没有问题。(而且不需要明确的演员阵容。longsize_t

可移植性

那么实际上是否足够大,可以进行文件偏移呢? 众所周知,它在 Windows 上的最小大小为 32 位。即使在 64 位程序中。因此,如果您计划在使用接口时处理大小为 2 GiB 或更大的文件,则可能会出现可移植性问题。较小的文件应该没有问题。longlongfseek

向前或向后跳转任意数量的字符

无论您使用什么界面,Windows 中使用的 CRLF 行尾都会在这里咬您。

您很可能可以解决此问题。这取决于你对“性格”的定义,也可能取决于跳跃需要的精确程度。您没有提供足够的信息让我们为您提供帮助。

评论

0赞 Tsvi Benschar 6/13/2023
我计划在大于 2 GiB 的文件上测试该程序。该算法在文本输入中搜索子字符串的实例,并且子字符串必须逐个字节匹配。我需要精确的跳转,这样我就可以遍历子字符串的字符,并将它们与输入文本中可能的匹配项进行比较。
0赞 ikegami 6/13/2023
缺失的信息应在问题中提供,而不是在评论中提供。由于您需要逐字节匹配,这意味着 CR 和 LF 没有特殊含义。因此,在 Windows 上,行尾为两个字节没有问题。只需确保以二进制模式打开文件即可。但在 Windows 上不够大,所以如果你想要一个便携式解决方案,那就不够好了。您可能需要在不同的操作系统上使用不同的功能。 其中 是 64+ 位,或者 哪里是 64+ 位,或者如果可用 (Windows),并在其他位置失败。会调整答案。longfseekfseeklonglseekoff_tSetFilePointer
0赞 ikegami 6/13/2023
更正一下,如果您正在进行相对寻道,如果寻道距离不超过 32 位,即使文件更大,2 GiB 也足够了。