C fgetpos()和fsetpos()是否仅用于文本模式?如果不是字节数,fpos\t对象填充的是什么位置/偏移量数据?

C fgetpos()和fsetpos()是否仅用于文本模式?如果不是字节数,fpos\t对象填充的是什么位置/偏移量数据?,c,fseek,ftell,fgetpos,C,Fseek,Ftell,Fgetpos,我了解C语言中ftell()和fseek()的工作原理,但对于这个问题,我在任何地方都找不到任何精确的答案,包括最近关于StackOverflow()的文章 因此,请您回答以下问题: 是否可以得出结论,fgetpos()和fsetpos()仅与以文本模式打开的文本文件相关,而与以二进制模式打开的文件无关 fgetpos()填充的fpos_t对象是什么类型的位置信息,假设它不是长整数偏移量等,如ftell()所给出的?网站cpluplusreference仅说明以下内容: 该函数使用流的位置指

我了解C语言中ftell()和fseek()的工作原理,但对于这个问题,我在任何地方都找不到任何精确的答案,包括最近关于StackOverflow()的文章

因此,请您回答以下问题:

  • 是否可以得出结论,fgetpos()和fsetpos()仅与以文本模式打开的文本文件相关,而与以二进制模式打开的文件无关
  • fgetpos()填充的fpos_t对象是什么类型的位置信息,假设它不是长整数偏移量等,如ftell()所给出的?网站cpluplusreference仅说明以下内容:
该函数使用流的位置指示器所需的信息填充pos指向的fpos_t对象,以将流恢复到其当前位置

和与文本和二进制模式都相关

fgetpos()
的优点是保持流中的完整位置,包括其内部的状态,以便稍后恢复。无论您是否处于文本模式,此选项都有效。如果在同一文件中使用或混合使用
fgetc()
,这一点尤其重要,因为某些语言环境使用依赖于状态的多字节编码(状态取决于以前的读取)

ftell()
也可以使用文本和二进制模式。但是,在文本模式中有一个重要的限制:只能将
fseek()
与0或先前由
ftell()
返回的值一起使用(在二进制模式中,您可以使用任何想要的值)。这是因为,与文件中有效的字节相比,文本模式读取可以更改读取返回的字节数(典型示例是,windows文件中的2个CR+LF字节被转换为符号LF字节)


由于
ftell()
只返回
long int
偏移量,因此如果需要,它无法跟踪多字节状态。因此,使用
fseek()
可能会失去这种状态

不完全是。线索可从以下方面找到:

在几乎每一个系统上(当然我知道的每一个系统), 人们不使用这些函数,而是使用ftell()和fseek()。 这些函数的存在只是为了防止系统无法记住文件 位置作为一个简单的字节偏移量

以及:

在某些非UNIX系统上,fpos_t对象可能是一个复杂的对象,并且 这些例程可能是可移植地重新定位文本的唯一方法 小溪

它假定缓冲区中的任何\n字符最初都是\r\n 将数据读入数据库时已规范化的序列 缓冲区

也就是说,在Windows中以文本模式打开时,非(Windows linebreak)文本文件的文件会出错,因为
fsetpos
假定该文件实际上是(Windows linebreak)文本文件,因此不能包含没有
\r
\n

C11标准说明(我的重点):

7.21.2/6:

每个面向广域的流都有一个关联的mbstate\t对象 存储流的当前解析状态。成功呼叫 fgetpos存储此mbstate_t对象的值的表示形式 作为fpos\u t对象值的一部分。后来成功呼叫 fsetpos使用相同的存储fpos_t值恢复 关联的mbstate_t对象以及 控制流

请注意,
fseek
ftell
mbstate\t
对象没有任何说明:它们不报告或恢复它。因此,在面向广泛的流(也就是说,您使用了面向广泛的I/O函数的流)上,它们只重置文件位置,而不是(如果实现实际上有一个以上的
mbstate\t
对象的可能值)流的整个状态


面向广域的流与文本流不同,只是读取广域文本文件是它们的常见用途。实际上,
fseek
ftell
都有文档记录,只要您正确使用它们,就可以重置文本文件上的文件位置。因此我相信(我可能错了)只有在流上使用宽I/O函数时才需要
fsetpos
fgetpos

除了其他答案中提到的原因之外,如果您处理的文件非常大,可能需要使用
fgetpos
fsetpos
,包含超过
LONG\u MAX
字节的文件。在
LONG_MAX
为231的系统中,这是一个真正的问题− 1.现在,超过20亿字节的文件并不少见

如果您在一个实现POSIX.1-2001的系统上,有一个更好的选择,那就是在包含任何系统头文件之前定义文件偏移位64,然后使用。它们与
fseek
ftell
类似,不同的是它们获取/返回一个
off\t
数量,如果您已经定义了上述
#define
,则保证为一个可以表示263的整数类型− 这对任何人来说都应该足够了。这更好,因为您可以在
off\t
上进行算术运算;你不能使用
fpos\u t
去你还没去过的地方。但如果您不在POSIX系统上,
fgetpos
fsetpos
可能是您唯一的选择


(注意,有些系统会给你一个
fpos\u t
,不能表示大于
LONG\u MAX
字节的文件偏移量。在其中一些系统上,应用相同的
\define\u file\u offset\u BITS 64
设置会有所帮助。在另一些系统上,如果你想要一个大文件,你就完全不走运了。)

我掌握了你的大部分答案。但是第一行对我来说是新的。你能提供一份sh吗