40

Most of the languages like C++ when writing into a file, put an EOF character even if we miss to write statements like :

filestream.close

However is there any way, we can put the EOF character according to our requirement, in C++, for an instance. Or any other method we may use apart from using the functions provided in C++.

If you need to ask more of information then kindly do give a comment.

EDIT:

What if, we want to trick the OS and place an EOF character in a file and write some data after the EOF so that an application like notepad.exe is not able to read after our EOF character. I have read answers to the question related to this topic and have come to know that nowdays OS generally don't see for an EOF character rather check the length of file to get the correct idea of knowing about the length of the file but, there must be a procedure in OS which would be checking the length of file and then updating the file records.

I am sorry if I am wrong at any point in my estimation but please do help me because it can lead to a lot of new ideas.

starball
  • 20,030
  • 7
  • 43
  • 238
Apoorv Saxena
  • 4,086
  • 10
  • 30
  • 46

10 Answers10

58

There is no EOF character. EOF by definition "is unequal to any valid character code". Often it is -1. It is not written into the file at any point.

There is a historical EOF character value (CTRL+Z) in DOS, but it is obsolete these days.

To answer the follow-up question of Apoorv: The OS never uses the file data to determine file length (files are not 'null terminated' in any way). So you cannot trick the OS. Perhaps old, stupid programs won't read after CTRL+Z character. I wouldn't assume that any Windows application (even Notepad) would do that. My guess is that it would be easier to trick them with a null (\0) character.

ypnos
  • 50,202
  • 14
  • 95
  • 141
  • 9
    I only explained what EOF actually is and that it is not a character code. I don't see your problem with the answer. – ypnos Jun 17 '10 at 16:20
  • So i'd like to trick a custom stream writer class i have into artificially accepting an EOF. There is no useful purpose for this except that it would complete my coverage tests. – Stephen Feb 27 '14 at 17:09
  • EOF is ioctl level. Not data. It sounds like you want to std::flush() your file stream. That will call the virtual method sync() on your class. If you implement this yourself then do std::flush() you will be able to handle a sync. Or you can have your own method for eof() and call it directly. – Stephen Apr 11 '14 at 14:19
  • Alteratively send EOF to overflow(). i.e. overflow(EOF). its dumb but it will work if you handle it correctly. – Stephen Apr 11 '14 at 14:21
17

Well, EOF is just a value returned by the function defined in the C stdio.h header file. Its actually returned to all the reading functions by the OS, so its system dependent. When OS reaches the end of file, it sends it to the function, which in its return value than places most commonly (-1), but not always. So, to summarize, EOF is not character, but constant returned by the OS. EDIT: Well, you need to know more about filesystem, look at this.

Hi, to your second question:

once again, you should look better into filesystems. FAT is a very nice example because you can find many articles about it, and its principles are very similar to NTFS. Anyway, once again, EOF is NOT a character. You cannot place it in file directly. If you could do so, imagine the consequences, even "dumb" image file could not be read by the system.

Why? Because OS works like very complex structure of layers. One of the layers is the filesystem driver. It makes sure that it transfers data from every filesystem known to the driver. It provides a bridge between applications and the actual system of storing files into HDD.

To be exact, FAT filesystem uses the so-called FAT table - it is a table located close to the start of the HDD (or partition) address space, and it contains map of all clusters (little storage cells). OK, so now, when you want to save some file to the HDD, OS (filesystem driver) looks into FAT table, and searches for the value "0x0". This "0x0" value says to the OS that cluster which address is described by the location of that value in FAT table is free to write.

So it writes into it the first part of the file. Then, it looks for another "0x0" value in FAT, and if found, it writes the second part of the file into cluster which it points to. Then, it changes the value of the first FAT table record where the file is located to the physical address of the next in our case second part of the file.

When your file is all stored on HDD, now there comes the final part, it writes desired EOF value, but into FAT table, not into the "data part" of the HDD. So when the file is read next time, it knows this is the end, don´t look any further.

So, now you see, if you would want to manually write EOF value into the place it doesn't belong to, you have to write your own driver which would be able to rewrite the FAT record, but this is practically impossible to do for beginners.

rohitt
  • 1,124
  • 6
  • 18
B.Gen.Jack.O.Neill
  • 8,169
  • 12
  • 51
  • 79
14

I came here while going through the Kernighan & Ritchie C exercises.

Ctrl+D sends the character that matches the EOF constant from stdio.h.

(Edit: this is on Mac OS X; thanks to @markmnl for pointing out that the Windows 10 equivalent is Ctrl+Z)

chbrown
  • 11,865
  • 2
  • 52
  • 60
7

Actually in C++ there is no physical EOF character written to a file using either the fprintf() or ostream mechanisms. EOF is an I/O condition to indicate no more data to read.

Some early disk operating systems like CP/M actually did use a physical 0x1A (ASCII SUB character) to indicate EOF because the file system only maintained file size in blocks so you never knew exactly how long a file was in bytes. With the advent of storing actual length counts in the directory it is no longer typical to store an "EOF" character as part of the 'in-band' file data.

Amardeep AC9MF
  • 18,464
  • 5
  • 40
  • 50
5

Under Windows, if you encounter an ASCII 26 (EOF) in stdin, it will stop reading the rest of the data. I believe writing this character will also terminate output sent to stdout, but I haven't confirmed this. You can switch the stream to binary mode as in this SO question:

#include <io.h>
#include <fcntl.h>
...
_setmode(0, _O_BINARY)

And not only will you stop 0x0A being converted to 0x0D 0x0A, but you'll also gain the ability to read/write 0x1A as well. Note you may have to switch both stdin (0) and stdout (1).

Community
  • 1
  • 1
Malvineous
  • 25,144
  • 16
  • 116
  • 151
  • thanks for mentioning both stdin, stdout. It still doesnt work with this though. Does compiling with c++ make a difference? – eleijonmarck Dec 15 '14 at 15:30
  • No the language won't make a difference as it's an issue with the Windows API. I can confirm the code above works, but make sure you change the 0 to the number of the stream you want to switch. – Malvineous Dec 16 '14 at 02:07
  • Oh i see, so I have to switch to, `_setmode(0, _0_BINARY)` and not `_setmode(stdin,_0_BINARY)`to set stdin as binary – eleijonmarck Dec 16 '14 at 05:57
  • I think you have to use particular values, so use 0 for stdin, 1 for stdout and 2 for stderr. There are probably constants defined for these but I'm not sure of them just at the moment. – Malvineous Dec 16 '14 at 10:49
4

There is no such thing as the "EOF" character. The fact of closing the stream in itself is the "EOF" condition.

When you press Ctrl+D in a unix shell, that simply closes the standard input stream, which in turn is recognized by the shell as "EOF" and it exits.

So, to "send" an "EOF", just close the stream to which the "EOF" needs to be sent.

rustyx
  • 80,671
  • 25
  • 200
  • 267
4

Nobody has yet mentioned the [f]truncate system calls, which are how you make a file shorter without recreating it from scratch.

The truncate() and ftruncate() functions cause the regular file named by path or referenced by fd to be truncated to a size of precisely length bytes.

If the file previously was larger than this size, the extra data is lost. If the file previously was shorter, it is extended, and the extended part reads as null bytes ('\0').

Understand that this is a distinct operation from writing any sort of data to the file. The file is a linear array of bytes, laid out on disk somehow, with metadata that says how long it is; truncate changes the metadata.

Community
  • 1
  • 1
zwol
  • 135,547
  • 38
  • 252
  • 361
4

If by the EOF character you mean something like Control-Z, then modern operating systems don't need such a thing, and the C++ runtime will not write one for you. You can of course write one yourself:

 filestream.put( 26 );     // write Ctrl-Z

but there is no good reason to do so. There is also no need to do:

 filesystem.close();

as the file stream will be closed for you automatically when its destructor is called, but it is (I think) good practice to do so.

2

On modern filesystems EOF is not a character, so you don't have to issue it when finishing to write to a file. You just have to close the file or let the OS do it for you when your process terminates.

mouviciel
  • 66,855
  • 13
  • 106
  • 140
  • I have a doubt: If EOF is used for return value purpose only & No such character is actually written to a File, then how a C Program determines that End of File is reached & No More Input is available (w.r.t. File Read Process)? Please help me on this. – Sandeep Singh Nov 13 '12 at 06:34
  • 1
    @SandeepSingh - The size of the file on the filesystem determines whether no more input is available. If EOF were a character, how could a zero-byte file exist? – mouviciel Nov 13 '12 at 06:39
0

Yes, you can manually add EOF to a file. 1) in Mac terminan, create a new file. touch filename.txt

2) Open the file in VI

vi filename.txt

3) In Insert mode (hit i), type Control+V and then Control+D. Do not let go of the Control key on the Mac.

Alternatively, if I want other ^NewLetters, like ^N^M^O^P, etc, I could do Contorl+V and then Control+NewLetter. So for example, to do ^O, hold down control, and then type V and O, then let go of Control.

Gene
  • 10,819
  • 1
  • 66
  • 58