如果我有一个包含以下内容的文本文件,
1234567890
字符串一个这样的电话:
fseek(fp, 5L, SEEK_SET);
型当我调用(char)fgetc(fp)时,给我给予6,因为我从字节0偏移了5个字节(不是从1开始,而是从2开始)但如果我这样做:
(char)fgetc(fp)
fseek(fp, -3L, SEEK_END);
型当我调用(char)fgetc(fp)时,给我给予8而不是7。为什么呢?看起来像SEEK_END,偏移量不是从最后一个字节之后的前一个字节开始。
SEEK_END
vq8itlhq1#
SEEK_END从文件的最后一个字节开始搜索:
1234567890 <--- bytes from the file 0123456789A <--- SEEK_SET-relative position A9876543210 <--- SEEK_END-relative position (absolute value) ^ This is the (0, SEEK_END) byte
字符串考虑到这一点,文件的最后一个字节是在(-1, SEEK_END)处找到的字节,因此(-3, SEEK_END)字节是8。注意,这与C语言通常处理这类事情的方式是一致的。例如,指向内存块末尾的指针通常指向该块最后一个字节的过去一位。它还有一个很好的功能,你可以通过调用fseek(SEEK_END)加上ftell()来获得文件的大小。不需要添加或子删除1!fseek()的手册页对此问题有点模糊,但与包含相同问题的man lseek相比:如果whence为SEEK_END,则文件偏移量应设置为文件大小加上偏移量。在你的例子中,文件的大小是10,偏移量是-3,所以最终位置是10-3 = 7。在偏移量7中有一个8。
(-1, SEEK_END)
(-3, SEEK_END)
8
fseek(SEEK_END)
ftell
1
fseek()
man lseek
10-3 = 7
ct2axkht2#
fseek允许在当前文件中附加文本。因此,filepointer被设置在文件的最后一个字符之后,因为这是新字符要被附加的地方。从一开始:
01234 <---position ABCDEFGHIJK <---file content
字符串从结尾开始:
43210 <---position ABCDEFGHIJK <---file content
型所以当你从一开始读取时,第0个字符是A,第3个是D。但是当你从末尾取数时,第0个字符是EndOfFile,第-3个字符是I。
lstz6jyr3#
这一切都归结为视觉化。我认为文件是一个从零开始的数组。比如,*byte在索引0 * 等。对于文件 * 操作 *,我倾向于认为它就像指针在 * 索引之间。它是一种不确定的指示器。对未来的期望。这也与SEEK_END有关,因为人们可以认为它是一个人想要在未来做什么。
0
SEEK_END -3
SEEK_END 0
例如,如果 offset 是4,那么我知道下一个字节在索引4处,最后一个读字节在索引3处。
4
3
0 1 2 3 4 5 6 7 Offset +---+---+---+---+---+---+---+ | 0 | 1 | 2 | 3 | 4 | 5 | 6 | Index +---+---+---+---+---+---+---+ | | | | | +--- Next Index | +----- Offset 4 +------- Last Index
字符串有些人可能会觉得尴尬,但对我来说很有效。至于SEEK_END,它是在名称中。查找相对于END。END全部读取,表明没有留下任何东西。SEEK_END和SEEK_SET也有直接关系:
SEEK_SET
SEEK_SET - SIZE = SEEK_END SEEK_END + SIZE = SEEK_SET SEEK_SET - SEEK_END = SIZE SEEK_SET + abs(SEEK_END) = SIZE
型在最后一个图中,我们有OFFSET和ORIGIN作为seek()的参数。
OFFSET
ORIGIN
seek()
(Size: 7 bytes) ,-- END of FILE / 0 1 2 3 4 5 6 | O O | BYTES | +---+---+---+---+---+---+---+ F R | L | R | | A | B | C | D | E | F | G | F I | E | E | +---+---+---+---+---+---+---+ S G | F | A | | | | | E I | T | D | | | | | T N . . RELATION | | | | . . . . | | | +-- 7, SEEK_SET | 0 | 7 | 7 - 7 = 0 | | | +-+ 0, SEEK_END | 0 | 7 | 0 + 7 = 7 | | | | 7 - -0 = 7 | | | | | | +-----| 6, SEEK_SET | 1 | 6 | 6 - 7 = -1 | | +-----+ -1, SEEK_END | 1 | 6 | -1 + 7 = 6 | | | 6 - -1 = 7 | | | | +-------------| 4, SEEK_SET | 3 | 4 | 4 - 7 = -3 | +-------------+ -3, SEEK_END | 3 | 4 | -3 + 7 = 4 | | 4 - -3 = 7 | | +-----------------------------| 0, SEEK_SET | 7 | 0 | 0 - 7 = -7 +-----------------------------+ -7, SEEK_END | 7 | 0 | -7 + 7 = 0 | | 0 - -7 = 7 fseek(fh, offs, origin) | / ftell() -´
型
zzlelutf4#
我想是因为文件的最后一个字符是'\n'或'\0'或类似的东西。
'\n'
'\0'
4条答案
按热度按时间vq8itlhq1#
SEEK_END
从文件的最后一个字节开始搜索:字符串
考虑到这一点,文件的最后一个字节是在
(-1, SEEK_END)
处找到的字节,因此(-3, SEEK_END)
字节是8
。注意,这与C语言通常处理这类事情的方式是一致的。例如,指向内存块末尾的指针通常指向该块最后一个字节的过去一位。
它还有一个很好的功能,你可以通过调用
fseek(SEEK_END)
加上ftell
()来获得文件的大小。不需要添加或子删除1
!fseek()
的手册页对此问题有点模糊,但与包含相同问题的man lseek
相比:如果whence为SEEK_END,则文件偏移量应设置为文件大小加上偏移量。
在你的例子中,文件的大小是10,偏移量是-3,所以最终位置是
10-3 = 7
。在偏移量7中有一个8
。ct2axkht2#
fseek允许在当前文件中附加文本。因此,filepointer被设置在文件的最后一个字符之后,因为这是新字符要被附加的地方。
从一开始:
字符串
从结尾开始:
型
所以当你从一开始读取时,第0个字符是A,第3个是D。
但是当你从末尾取数时,第0个字符是EndOfFile,第-3个字符是I。
lstz6jyr3#
这一切都归结为视觉化。
我认为文件是一个从零开始的数组。比如,*byte在索引
0
* 等。对于文件 * 操作 *,我倾向于认为它就像指针在 * 索引之间。它是一种不确定的指示器。对未来的期望。这也与
SEEK_END
有关,因为人们可以认为它是一个人想要在未来做什么。SEEK_END -3
-现在我可以读取最后3个字节。SEEK_END 0
-没有更多的字节。现在我可以追加字节。例如,如果 offset 是
4
,那么我知道下一个字节在索引4
处,最后一个读字节在索引3
处。字符串
有些人可能会觉得尴尬,但对我来说很有效。
至于
SEEK_END
,它是在名称中。查找相对于END。END全部读取,表明没有留下任何东西。SEEK_END
和SEEK_SET
也有直接关系:型
在最后一个图中,我们有
OFFSET
和ORIGIN
作为seek()
的参数。型
zzlelutf4#
我想是因为文件的最后一个字符是
'\n'
或'\0'
或类似的东西。