Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #53855 > unrolled thread
| Started by | arnuld <sunrise@invalid.address> |
|---|---|
| First post | 2014-12-04 08:42 +0000 |
| Last post | 2014-12-04 21:29 -0500 |
| Articles | 10 — 7 participants |
Back to article view | Back to comp.lang.c
fseek(), offset and ftell() arnuld <sunrise@invalid.address> - 2014-12-04 08:42 +0000
Re: fseek(), offset and ftell() Robert Wessel <robertwessel2@yahoo.com> - 2014-12-04 03:28 -0600
Re: fseek(), offset and ftell() James Kuyper <jameskuyper@verizon.net> - 2014-12-04 11:25 -0500
Re: fseek(), offset and ftell() glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2014-12-04 16:49 +0000
Re: fseek(), offset and ftell() Keith Thompson <kst-u@mib.org> - 2014-12-04 09:05 -0800
Re: fseek(), offset and ftell() "Bill Cunningham" <nospam@nspam.invalid> - 2014-12-04 14:13 -0500
Re: fseek(), offset and ftell() "Bill Cunningham" <nospam@nspam.invalid> - 2014-12-04 16:01 -0500
Re: fseek(), offset and ftell() glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2014-12-04 21:42 +0000
Re: fseek(), offset and ftell() Nobody <nobody@nowhere.invalid> - 2014-12-05 00:24 +0000
Re: fseek(), offset and ftell() "Bill Cunningham" <nospam@nspam.invalid> - 2014-12-04 21:29 -0500
| From | arnuld <sunrise@invalid.address> |
|---|---|
| Date | 2014-12-04 08:42 +0000 |
| Subject | fseek(), offset and ftell() |
| Message-ID | <54801e7e$0$297$14726298@news.sunsite.dk> |
There are several contradicting definitions of the behavior of fseek() . I do not know mhich one to believe: > n1570.pdf: > section 7.21.9.2 > int fseek(FILE *stream, long int offset, int whence); > For a binary stream, the new position, measured in characters from the > beginning of the file, is obtained by adding offset to the position > specified by whence. The specified position is the beginning of the > file if whence is SEEK_SET, the current value of the file position > indicator if SEEK_CUR, or end-of-file if SEEK_END. A binary stream need > not meaningfully support fseek calls with a whence value of SEEK_END. I have used seek on a text file (I assume a file containing C code as text qualifies as a text stream) and I see new position is measured in characters there too. Then why standard mentioned only binary streams ? > For a text stream, either offset shall be zero, or offset shall be a > value returned by an earlier successful call to the ftell function on a > stream associated with the same file and whence shall be SEEK_SET. Standard says value should be eitehr zero or a returned value from ftell() which returns only current position. Now if I want to go past the 100 characters and start reading from 101st character onwards, how to do that ? In gcc simply putting 100 or 101 or 9 works, you can seek to any character by just putting it as 2nd argument to fseek() but is that correct way ? -- arnuld http://lispmachine.wordpress.com/
[toc] | [next] | [standalone]
| From | Robert Wessel <robertwessel2@yahoo.com> |
|---|---|
| Date | 2014-12-04 03:28 -0600 |
| Message-ID | <ro908atorhi7n1199ohngm04l2j76m54sc@4ax.com> |
| In reply to | #53855 |
On 04 Dec 2014 08:42:39 GMT, arnuld <sunrise@invalid.address> wrote: >There are several contradicting definitions of the behavior of fseek() . >I do not know mhich one to believe: > >> n1570.pdf: >> section 7.21.9.2 > >> int fseek(FILE *stream, long int offset, int whence); > >> For a binary stream, the new position, measured in characters from the >> beginning of the file, is obtained by adding offset to the position >> specified by whence. The specified position is the beginning of the >> file if whence is SEEK_SET, the current value of the file position >> indicator if SEEK_CUR, or end-of-file if SEEK_END. A binary stream need >> not meaningfully support fseek calls with a whence value of SEEK_END. > >I have used seek on a text file (I assume a file containing C code as >text qualifies as a text stream) and I see new position is measured in >characters there too. Then why standard mentioned only binary streams ? > > >> For a text stream, either offset shall be zero, or offset shall be a >> value returned by an earlier successful call to the ftell function on a >> stream associated with the same file and whence shall be SEEK_SET. > >Standard says value should be eitehr zero or a returned value from >ftell() which returns only current position. Now if I want to go past >the 100 characters and start reading from 101st character onwards, how to >do that ? In gcc simply putting 100 or 101 or 9 works, you can seek to >any character by just putting it as 2nd argument to fseek() but is that >correct way ? There simply is no standard way to do that on a text stream. Consider a platform like Windows that store two bytes in the text file for a \n. Remember that your C program will always see the \n as a *single* character, despite the fact that (on Windows) it's store as two bytes. There's no good way to seek some number of characters without reading each intervening character to check for cf/lf pairs. OTOH, you can read forward yourself. Or use a binary stream, but then you have to deal with line ends yourself. On some platforms seeking on a text file works exactly as you'd hope, for example on most *nix implementations, but it's definitely not standard, and may or may not by something your implementation promises (whether or not it works at the moment).
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2014-12-04 11:25 -0500 |
| Message-ID | <54808AF8.8090603@verizon.net> |
| In reply to | #53855 |
On 12/04/2014 03:42 AM, arnuld wrote: > There are several contradicting definitions of the behavior of fseek() . What are the contradictory definitions? Unless I've misread your message, you only provide one definition below, and I didn't notice any internal contradictions. What contradictions have you seen between the definitions you're referring to? > I do not know mhich one to believe: > >> n1570.pdf: >> section 7.21.9.2 > >> int fseek(FILE *stream, long int offset, int whence); > >> For a binary stream, the new position, measured in characters from the >> beginning of the file, is obtained by adding offset to the position >> specified by whence. The specified position is the beginning of the >> file if whence is SEEK_SET, the current value of the file position >> indicator if SEEK_CUR, or end-of-file if SEEK_END. A binary stream need >> not meaningfully support fseek calls with a whence value of SEEK_END. > > I have used seek on a text file (I assume a file containing C code as > text qualifies as a text stream) and I see new position is measured in > characters there too. Then why standard mentioned only binary streams ? Because there are many different ways a text stream can indicate the end of a line, and correspondingly many different ways of implementing fseek() on text streams. Examples of schemes that I've heard about: 1. A single new-line character - which can be different on different systems. 2. A pair of characters that together indicate end-of-line - the pairing can be different on different systems. 3. Files organized in blocks, with end-of-line within a block indicated by having the rest of the block filled in with padding. On some systems, the padding character is '\0', but on others it's a blank - which is why the standard explicitly permits the number of blank characters at the end of a line be different when it is read from a text stream than it was when the line was written. 4. Files organized in blocks, with end-of-line indicated by a byte at the beginning of the block saying how much of the block is actually used. The remaining bytes of the block might be either padded or filled with garbage. So - how would you like the offset to work when it crosses the end of a line? Should it increase by only 1, regardless of how end-of-line is indicated? Should it increase by 2 if the two characters are used to indicate end-of-line? Should it include or exclude padding/garbage at the end of a block? Each way of doing things has it's advantages and disadvantages, and different systems make different choices. The committee chose to define text mode for the specific purpose of allowing such variations. If such variations weren't allowed, binary mode would not need to be distinct from text mode. >> For a text stream, either offset shall be zero, or offset shall be a >> value returned by an earlier successful call to the ftell function on a >> stream associated with the same file and whence shall be SEEK_SET. > > Standard says value should be eitehr zero or a returned value from > ftell() which returns only current position. Now if I want to go past > the 100 characters and start reading from 101st character onwards, how to > do that ? In gcc simply putting 100 or 101 or 9 works, you can seek to > any character by just putting it as 2nd argument to fseek() but is that > correct way ? Violating a "shall" that occurs outside of a constraint section means that the behavior is undefined - which is standardese with simply means that the standard itself does not define the behavior - the implementation is free to provide it's own definition. On Unix-like systems, text mode behaves exactly the same as binary mode, so what you're saying should work fine. You'll have to read the documentation for other systems to find out what works there. Since the behavior is undefined, rather than implementation-defined, a conforming implementation of C need not provide such documentation, but any reasonable implementation of C will document it. For portable code working on a text stream, replace calls to fseek() which would violate those shalls with calls to functions which read the the appropriate number of characters, which you can then discard unprocessed. This will result in newlines always being treated as 1 character long, regardless of the actual method used to indicate end-of-line.
[toc] | [prev] | [next] | [standalone]
| From | glen herrmannsfeldt <gah@ugcs.caltech.edu> |
|---|---|
| Date | 2014-12-04 16:49 +0000 |
| Message-ID | <m5q39s$u4a$1@speranza.aioe.org> |
| In reply to | #53892 |
James Kuyper <jameskuyper@verizon.net> wrote: > On 12/04/2014 03:42 AM, arnuld wrote: >> There are several contradicting definitions of the behavior of fseek() . (snip) > Because there are many different ways a text stream can indicate the end > of a line, and correspondingly many different ways of implementing > fseek() on text streams. Examples of schemes that I've heard about: (snip) > 4. Files organized in blocks, with end-of-line indicated by a byte at > the beginning of the block saying how much of the block is actually > used. The remaining bytes of the block might be either padded or filled > with garbage. For VM/CMS, the system keeps track of block numbers, but not the length of blocks. For fixed length blocks, in non-text files, it can figure out the byte offset. Otherwise, ftell() returns, and fseek() accepts 32768*block+offset. I believe for FB the trailing blanks are returned as part of the data, but it could be that they are removed. The VB format has a four byte block descriptor at the beginning of a block, and a four byte record descriptor at the beginning of each record. For text files, you get '\n' as usual. > So - how would you like the offset to work when it crosses the end of a > line? Should it increase by only 1, regardless of how end-of-line is > indicated? Should it increase by 2 if the two characters are used to > indicate end-of-line? Should it include or exclude padding/garbage at > the end of a block? Each way of doing things has it's advantages and > disadvantages, and different systems make different choices. The > committee chose to define text mode for the specific purpose of allowing > such variations. If such variations weren't allowed, binary mode would > not need to be distinct from text mode. (snip) -- glen
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2014-12-04 09:05 -0800 |
| Message-ID | <lna933pcqk.fsf@nuthaus.mib.org> |
| In reply to | #53855 |
arnuld <sunrise@invalid.address> writes:
> There are several contradicting definitions of the behavior of fseek() .
> I do not know mhich one to believe:
There is no real contradiction.
>> n1570.pdf:
>> section 7.21.9.2
>
>> int fseek(FILE *stream, long int offset, int whence);
>
>> For a binary stream, the new position, measured in characters from the
>> beginning of the file, is obtained by adding offset to the position
>> specified by whence. The specified position is the beginning of the
>> file if whence is SEEK_SET, the current value of the file position
>> indicator if SEEK_CUR, or end-of-file if SEEK_END. A binary stream need
>> not meaningfully support fseek calls with a whence value of SEEK_END.
>
> I have used seek on a text file (I assume a file containing C code as
> text qualifies as a text stream) and I see new position is measured in
> characters there too. Then why standard mentioned only binary streams ?
>
>> For a text stream, either offset shall be zero, or offset shall be a
>> value returned by an earlier successful call to the ftell function on a
>> stream associated with the same file and whence shall be SEEK_SET.
>
> Standard says value should be eitehr zero or a returned value from
> ftell() which returns only current position. Now if I want to go past
> the 100 characters and start reading from 101st character onwards, how to
> do that ? In gcc simply putting 100 or 101 or 9 works, you can seek to
> any character by just putting it as 2nd argument to fseek() but is that
> correct way ?
On a UNIX-like system, a text file is a sequence of lines, where each
line is a sequence of characters terminated by a '\n' character. You
can read the same file in text or binary mode and get exactly the same
byte sequence.
That's not true on all systems, and the standard doesn't require it.
The standard only specifies the behavior that's guaranteed for *all*
conforming implementations.
A binary stream need not meaningfully support fseek calls with a
whence value of SEEK_END.
Some systems might store binary files as a whole number of fixed-length
blocks, with no information about how many bytes are in the final block.
On such a system, fseek with SEEK_END might go to the end of the last
block, even if not that many bytes have been written. On a UNIX-like
system, a binary file is stored as an arbitrary sequence of bytes, and
fseek with SEEK_END works perfectly well. Code that relies on this will
not be portable to non-UNIX systems.
For a text stream, either offset shall be zero, or offset shall
be a value returned by an earlier successful call to the ftell
function on a stream associated with the same file and whence
shall be SEEK_SET.
This is a Standardese use of the word "shall". If the word "shall"
appears in the Standard outside a constraint, as it does here, it
doesn't mean that something is either required or forbidden; it means
that any program that violates it has undefined behavior (which merely
means behavior that is not defined *by the C standard*).
If you fseek() to position 100 in a text file on a UNIX-file system, it
will do exactly what you expect. The above quoted paragraph merely
means that the C standard doesn't guarantee that behavior.
Some examples:
On Windows, end-of-line is represented by a 2-character sequence "\r\n".
Reading an end-of-line from a text file on Windows returns a single '\n'
character, but fseek works on the number of bytes *in the physical
file*, not the number of characters you'll get if you read from it. You
can specify a position in a text file by reading to that position and
then calling ftell(); that method will work on any conforming C
implementation.
On other systems, text files might be stored as fixed-length records.
Reading from such a file in text mode will convert that format to
sequences of characters terminated by '\n'; seeking to arbitary
positions won't do what you expect, and might not even be permitted.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | "Bill Cunningham" <nospam@nspam.invalid> |
|---|---|
| Date | 2014-12-04 14:13 -0500 |
| Message-ID | <m5qbns$l1u$1@speranza.aioe.org> |
| In reply to | #53896 |
"Keith Thompson" <kst-u@mib.org> wrote in message
news:lna933pcqk.fsf@nuthaus.mib.org...
> On a UNIX-like system, a text file is a sequence of >lines, where each
> line is a sequence of characters terminated by a '\n' >character. You
> can read the same file in text or binary mode and get >exactly the same
> byte sequence.
>
> That's not true on all systems, and the standard doesn't >require it.
>
> The standard only specifies the behavior that's >guaranteed for *all*
> conforming implementations.
>
> A binary stream need not meaningfully support fseek >calls with a
> whence value of SEEK_END.
I'm glad you mentioned this Keith. I will also mention fget_pos and
fput_pos, but I don't think they need any introduction.
On my linux there is a unix2dos and dos2unix command, respectively. DOS
has control line terminators as windows and DOS use that. Linux and *nixes.
Indeed do not.
Bill
[toc] | [prev] | [next] | [standalone]
| From | "Bill Cunningham" <nospam@nspam.invalid> |
|---|---|
| Date | 2014-12-04 16:01 -0500 |
| Message-ID | <m5qi3t$5pj$1@speranza.aioe.org> |
| In reply to | #53900 |
"Bill Cunningham" <nospam@nspam.invalid> wrote in message
news:m5qbns$l1u$1@speranza.aioe.org...
>
> "Keith Thompson" <kst-u@mib.org> wrote in message
> news:lna933pcqk.fsf@nuthaus.mib.org...
>
>> On a UNIX-like system, a text file is a sequence of >lines, where each
>> line is a sequence of characters terminated by a '\n' >character. You
>> can read the same file in text or binary mode and get >exactly the same
>> byte sequence.
>>
>> That's not true on all systems, and the standard doesn't >require it.
>>
>> The standard only specifies the behavior that's >guaranteed for *all*
>> conforming implementations.
>>
>> A binary stream need not meaningfully support fseek >calls with a
>> whence value of SEEK_END.
>
> I'm glad you mentioned this Keith. I will also mention fget_pos and
> fput_pos, but I don't think they need any introduction.
> On my linux there is a unix2dos and dos2unix command, respectively. DOS
> has control line terminators as windows and DOS use that. Linux and
> *nixes. Indeed do not.
>
> Bill
Correction fgetpos and fsetpos.
[toc] | [prev] | [next] | [standalone]
| From | glen herrmannsfeldt <gah@ugcs.caltech.edu> |
|---|---|
| Date | 2014-12-04 21:42 +0000 |
| Message-ID | <m5qkfg$ck8$1@speranza.aioe.org> |
| In reply to | #53896 |
Keith Thompson <kst-u@mib.org> wrote: > arnuld <sunrise@invalid.address> writes: >> There are several contradicting definitions of the behavior of fseek() . (snip) >> Standard says value should be eitehr zero or a returned value from >> ftell() which returns only current position. Now if I want to go past >> the 100 characters and start reading from 101st character onwards, how to >> do that ? In gcc simply putting 100 or 101 or 9 works, you can seek to >> any character by just putting it as 2nd argument to fseek() but is that >> correct way ? > On a UNIX-like system, a text file is a sequence of lines, where each > line is a sequence of characters terminated by a '\n' character. You > can read the same file in text or binary mode and get exactly the same > byte sequence. > That's not true on all systems, and the standard doesn't require it. > The standard only specifies the behavior that's guaranteed for *all* > conforming implementations. > A binary stream need not meaningfully support fseek calls with a > whence value of SEEK_END. > Some systems might store binary files as a whole number of fixed-length > blocks, with no information about how many bytes are in the final block. > On such a system, fseek with SEEK_END might go to the end of the last > block, even if not that many bytes have been written. On a UNIX-like > system, a binary file is stored as an arbitrary sequence of bytes, and > fseek with SEEK_END works perfectly well. Code that relies on this will > not be portable to non-UNIX systems. As I understand the way PDF readers are supposed to work, they fseek() to the end, back up some, and look for a special byte sequence. If the block padding isn't so big, it should be able to find what it needs. When that fails, I believe that Adobe Reader instead starts reading from the beginning. Presumably those who compile versions of Adobe Reader know the fseek() properties of the system in use. > For a text stream, either offset shall be zero, or offset shall > be a value returned by an earlier successful call to the ftell > function on a stream associated with the same file and whence > shall be SEEK_SET. > This is a Standardese use of the word "shall". If the word "shall" > appears in the Standard outside a constraint, as it does here, it > doesn't mean that something is either required or forbidden; it means > that any program that violates it has undefined behavior (which merely > means behavior that is not defined *by the C standard*). > If you fseek() to position 100 in a text file on a UNIX-file system, it > will do exactly what you expect. The above quoted paragraph merely > means that the C standard doesn't guarantee that behavior. > Some examples: > On Windows, end-of-line is represented by a 2-character sequence "\r\n". > Reading an end-of-line from a text file on Windows returns a single '\n' > character, but fseek works on the number of bytes *in the physical > file*, not the number of characters you'll get if you read from it. You > can specify a position in a text file by reading to that position and > then calling ftell(); that method will work on any conforming C > implementation. I mentioned before how VM/CMS does it for some file types. CMS keeps track of block numbers, but not the length of the blocks. Users can choose a block size between 1 and about 32767 bytes. (It can't be less than 9 for variable length records.) > On other systems, text files might be stored as fixed-length records. > Reading from such a file in text mode will convert that format to > sequences of characters terminated by '\n'; seeking to arbitary > positions won't do what you expect, and might not even be permitted. For fixed length records, (and blocks) CMS fseek can convert a byte offset to a block number and block offset for both text and non-text. I believe for VB, both text and non-text, it uses 32768*block+offset. If a program reads from the beginning, recording the values of ftell() all the way through, it will work as expected. -- glen
[toc] | [prev] | [next] | [standalone]
| From | Nobody <nobody@nowhere.invalid> |
|---|---|
| Date | 2014-12-05 00:24 +0000 |
| Message-ID | <pan.2014.12.05.00.24.03.504000@nowhere.invalid> |
| In reply to | #53906 |
On Thu, 04 Dec 2014 21:42:08 +0000, glen herrmannsfeldt wrote: > Presumably those who compile versions of Adobe Reader know the > fseek() properties of the system in use. Examining the dependencies of AcroRd32.exe indicates that it doesn't use MSVCRT (the library providing the standard C library functions), but instead uses the Windows I/O functions (SetFilePointer() is the equivalent of fseek()). Which isn't particularly surprising. C's stdio functions are something of a lowest common denominator. The OS' native I/O capabilities will always offer additional functionality. Probably the most common issue with stdio is that fseek/ftell are problematic for files whose size cannot fit into a signed "long" (which is only 32 bits even on "64-bit" versions of Windows).
[toc] | [prev] | [next] | [standalone]
| From | "Bill Cunningham" <nospam@nspam.invalid> |
|---|---|
| Date | 2014-12-04 21:29 -0500 |
| Message-ID | <m5r5a0$fp2$1@speranza.aioe.org> |
| In reply to | #53908 |
"Nobody" <nobody@nowhere.invalid> wrote in message
news:pan.2014.12.05.00.24.03.504000@nowhere.invalid...
[...]
Probably the most common issue with
> stdio is that fseek/ftell are problematic for files whose size cannot fit
> into a signed "long" (which is only 32 bits even on "64-bit" versions of
> Windows).
I noticed that myself lately.
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.c
csiph-web