fgetpos() 和 fsetpos() 仅适用于文本模式吗?如果不是字节数,fpos_t 对象填充的是什么 location/offset 数据?
Are fgetpos() and fsetpos() only for text mode? What location/offset data is the fpos_t object filled with if not number of bytes?
我了解 C 中 ftell() 和 fseek() 的工作原理,但是对于这个问题,我无法在任何地方找到任何精确的答案,包括 Whosebug 上最近的 post(LINK).
所以请您回答以下问题:
- 是否可以断定 fgetpos() 和 fsetpos() 仅与以文本模式打开的文本文件相关,而不与以二进制模式打开的文件相关?
- fgetpos()填充的fpos_t对象是什么类型的位置信息,因为它不像ftell()给出的长整型偏移等?该站点 cplusplusreference 仅说明以下内容:
The function fills the fpos_t object pointed by pos with the information needed from the stream's position indicator to restore the stream to its current position
fgetpos()
and fsetpos()
与文本和二进制模式相关。
fgetpos()
的优点是保留流中的完整位置,包括其内部状态,以便您稍后可以恢复。无论您是否处于文本模式,这都有效。如果您在同一文件中使用 wide oriented streams or mix fgetc()
and fgetwc()
,这一点尤其重要,因为某些语言环境使用状态相关的多字节编码(状态取决于之前的读取)。
fseek()
和 ftell()
也可以使用文本和二进制模式。然而,在文本模式中有一个重要的限制:你应该只使用 fseek()
和 0 或之前由 ftell()
返回的值(在二进制模式中你可以使用任何你想要的值)。这是因为与文件中的有效字节相比,文本模式读取可以更改从读取返回的字节数(典型示例,windows 文件中的 2 个 CR+LF 字节被转换为 signe LF 字节).
由于 ftell()
只有 returns 一个 long int
偏移量,如果需要的话,它无法跟踪多字节状态。所以使用 fseek()
可能会失去这种状态。
不完全是。可以从Beej:
中找到线索
On virtually every system (and certainly every system that I know of),
people don't use these functions, using ftell() and fseek() instead.
These functions exist just in case your system can't remember file
positions as a simple byte offset.
On some non-UNIX systems, an fpos_t object may be a complex object and
these routines may be the only way to portably reposition a text
stream.
在 Windows 上:
It assumes that any \n character in the buffer was originally a \r\n
sequence that had been normalized when the data was read into the
buffer.
也就是说,不是(Windows-linebreak)文本文件的文件在以文本模式打开时在 Windows 中出错,因为 fsetpos
假设文件确实存在是一个(Windows-换行符)文本文件,因此不能包含没有 \r
.
的 \n
C11 标准说(我强调):
7.21.2/6:
Each wide-oriented stream has an associated mbstate_t object that
stores the current parse state of the stream. A successful call to
fgetpos stores a representation of the value of this mbstate_t object
as part of the value of the fpos_t object. A later successful call to
fsetpos using the same stored fpos_t value restores the value of the
associated mbstate_t object as well as the position within the
controlled stream.
请注意 fseek
和 ftell
对 mbstate_t
对象无话可说:他们不报告或恢复它。因此,在面向广泛的流(也就是说,您使用面向广泛的 I/O 函数的流)上,它们只会重置文件位置,而不是(如果实现实际上有多个可能的 a 值) mbstate_t
object) 流的整个状态。
面向宽的流与文本流不是一回事,只是读取宽文本文件是它们的常见用途。实际上 fseek
和 ftell
被记录为能够重置文本文件上的文件位置,前提是您正确使用它们。所以我相信(我可能是错的)只有在流上使用宽 I/O 函数时才需要 fsetpos
和 fgetpos
。
除了其他答案中提到的原因外,如果您正在处理非常大的文件,则可能需要使用fgetpos
和fsetpos
,包含超过 LONG_MAX
字节的文件。对于 LONG_MAX
为 231 − 1 的系统,这是一个真正的问题;如今,超过 20 亿字节的文件并不少见。
如果您使用的系统实现了 POSIX.1-2001,则有更好的选择,即在包含任何系统头文件之前 #define _FILE_OFFSET_BITS 64
,然后使用 fseeko
and ftello
.这些就像 fseek
和 ftell
除了他们 take/return 一个 off_t
数量,如果你已经做了上面的 #define
,保证是一个可以表示 263 − 1 的整数类型,这对任何人来说都应该足够了。这样更好,因为您可以对 off_t
进行算术运算;你不能使用 fpos_t
去你没去过的地方。但是,如果您不在 POSIX 系统上,fgetpos
和 fsetpos
可能是您唯一的选择。
(请注意,某些系统会给您一个 fpos_t
, 不能 表示大于 LONG_MAX
字节的文件偏移量。在其中一些,应用相同的 #define _FILE_OFFSET_BITS 64
设置会有所帮助。在其他情况下,如果您想要一个大文件,您就完全不走运了。)
我了解 C 中 ftell() 和 fseek() 的工作原理,但是对于这个问题,我无法在任何地方找到任何精确的答案,包括 Whosebug 上最近的 post(LINK).
所以请您回答以下问题:
- 是否可以断定 fgetpos() 和 fsetpos() 仅与以文本模式打开的文本文件相关,而不与以二进制模式打开的文件相关?
- fgetpos()填充的fpos_t对象是什么类型的位置信息,因为它不像ftell()给出的长整型偏移等?该站点 cplusplusreference 仅说明以下内容:
The function fills the fpos_t object pointed by pos with the information needed from the stream's position indicator to restore the stream to its current position
fgetpos()
and fsetpos()
与文本和二进制模式相关。
fgetpos()
的优点是保留流中的完整位置,包括其内部状态,以便您稍后可以恢复。无论您是否处于文本模式,这都有效。如果您在同一文件中使用 wide oriented streams or mix fgetc()
and fgetwc()
,这一点尤其重要,因为某些语言环境使用状态相关的多字节编码(状态取决于之前的读取)。
fseek()
和 ftell()
也可以使用文本和二进制模式。然而,在文本模式中有一个重要的限制:你应该只使用 fseek()
和 0 或之前由 ftell()
返回的值(在二进制模式中你可以使用任何你想要的值)。这是因为与文件中的有效字节相比,文本模式读取可以更改从读取返回的字节数(典型示例,windows 文件中的 2 个 CR+LF 字节被转换为 signe LF 字节).
由于 ftell()
只有 returns 一个 long int
偏移量,如果需要的话,它无法跟踪多字节状态。所以使用 fseek()
可能会失去这种状态。
不完全是。可以从Beej:
中找到线索On virtually every system (and certainly every system that I know of), people don't use these functions, using ftell() and fseek() instead. These functions exist just in case your system can't remember file positions as a simple byte offset.
On some non-UNIX systems, an fpos_t object may be a complex object and these routines may be the only way to portably reposition a text stream.
在 Windows 上:
It assumes that any \n character in the buffer was originally a \r\n sequence that had been normalized when the data was read into the buffer.
也就是说,不是(Windows-linebreak)文本文件的文件在以文本模式打开时在 Windows 中出错,因为 fsetpos
假设文件确实存在是一个(Windows-换行符)文本文件,因此不能包含没有 \r
.
\n
C11 标准说(我强调):
7.21.2/6:
Each wide-oriented stream has an associated mbstate_t object that stores the current parse state of the stream. A successful call to fgetpos stores a representation of the value of this mbstate_t object as part of the value of the fpos_t object. A later successful call to fsetpos using the same stored fpos_t value restores the value of the associated mbstate_t object as well as the position within the controlled stream.
请注意 fseek
和 ftell
对 mbstate_t
对象无话可说:他们不报告或恢复它。因此,在面向广泛的流(也就是说,您使用面向广泛的 I/O 函数的流)上,它们只会重置文件位置,而不是(如果实现实际上有多个可能的 a 值) mbstate_t
object) 流的整个状态。
面向宽的流与文本流不是一回事,只是读取宽文本文件是它们的常见用途。实际上 fseek
和 ftell
被记录为能够重置文本文件上的文件位置,前提是您正确使用它们。所以我相信(我可能是错的)只有在流上使用宽 I/O 函数时才需要 fsetpos
和 fgetpos
。
除了其他答案中提到的原因外,如果您正在处理非常大的文件,则可能需要使用fgetpos
和fsetpos
,包含超过 LONG_MAX
字节的文件。对于 LONG_MAX
为 231 − 1 的系统,这是一个真正的问题;如今,超过 20 亿字节的文件并不少见。
如果您使用的系统实现了 POSIX.1-2001,则有更好的选择,即在包含任何系统头文件之前 #define _FILE_OFFSET_BITS 64
,然后使用 fseeko
and ftello
.这些就像 fseek
和 ftell
除了他们 take/return 一个 off_t
数量,如果你已经做了上面的 #define
,保证是一个可以表示 263 − 1 的整数类型,这对任何人来说都应该足够了。这样更好,因为您可以对 off_t
进行算术运算;你不能使用 fpos_t
去你没去过的地方。但是,如果您不在 POSIX 系统上,fgetpos
和 fsetpos
可能是您唯一的选择。
(请注意,某些系统会给您一个 fpos_t
, 不能 表示大于 LONG_MAX
字节的文件偏移量。在其中一些,应用相同的 #define _FILE_OFFSET_BITS 64
设置会有所帮助。在其他情况下,如果您想要一个大文件,您就完全不走运了。)