C语言 fseek和SEEK_END的行为

okxuctiv  于 12个月前  发布在  其他
关注(0)|答案(4)|浏览(419)

如果我有一个包含以下内容的文本文件,

1234567890

字符串
一个这样的电话:

fseek(fp, 5L, SEEK_SET);


当我调用(char)fgetc(fp)时,给我给予6,因为我从字节0偏移了5个字节(不是从1开始,而是从2开始)
但如果我这样做:

fseek(fp, -3L, SEEK_END);


当我调用(char)fgetc(fp)时,给我给予8而不是7。
为什么呢?看起来像SEEK_END,偏移量不是从最后一个字节之后的前一个字节开始。

vq8itlhq

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

ct2axkht

ct2axkht2#

fseek允许在当前文件中附加文本。因此,filepointer被设置在文件的最后一个字符之后,因为这是新字符要被附加的地方。
从一开始:

01234         <---position
ABCDEFGHIJK   <---file content

字符串
从结尾开始:

43210  <---position
ABCDEFGHIJK   <---file content


所以当你从一开始读取时,第0个字符是A,第3个是D。
但是当你从末尾取数时,第0个字符是EndOfFile,第-3个字符是I。

lstz6jyr

lstz6jyr3#

这一切都归结为视觉化。
我认为文件是一个从零开始的数组。比如,*byte在索引0 * 等。
对于文件 * 操作 *,我倾向于认为它就像指针在 * 索引之间。它是一种不确定的指示器。对未来的期望。这也与SEEK_END有关,因为人们可以认为它是一个人想要在未来做什么。

  • SEEK_END -3-现在我可以读取最后3个字节。
  • SEEK_END 0-没有更多的字节。现在我可以追加字节。
  • ...

例如,如果 offset4,那么我知道下一个字节在索引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_ENDSEEK_SET也有直接关系:

SEEK_SET - SIZE     = SEEK_END
SEEK_END + SIZE     = SEEK_SET
SEEK_SET -     SEEK_END  = SIZE
SEEK_SET + abs(SEEK_END) = SIZE


在最后一个图中,我们有OFFSETORIGIN作为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() -´

zzlelutf

zzlelutf4#

我想是因为文件的最后一个字符是'\n''\0'或类似的东西。

相关问题