Like reading a book, sequential file access starts at the file’s beginning (or top) and reads bytes one after the other until the nefarious EOF is encountered. You probably don’t think about how that works, and you don’t need to. The operating system handles the job of reading a file; your C code is simply along for the ride.
The following code reads a text file and outputs the results. In this case, the file read is text file, gettysburg.txt
. It contains the first line of Lincoln’s Gettysburg Address. Click the link to view or download the file, which is referenced in the source code below at Line 9.
#include <stdio.h> int main() { FILE *fh; int c; /* open the file */ fh = fopen("gettysburg.txt","r"); if(fh == NULL) { perror("Unable to open file\n"); return(1); } /* read the file and display */ while( (c=fgetc(fh)) != EOF) putchar(c); /* close the file */ fclose(fh); return(0); }
This type of code should be familiar to you if you’ve read any of my C programming books. The file is opened, its contents displayed, and then the file is closed.
Here’s sample output:
Four score and seven years ago our fathers brought forth on this continent a new nation, conceived in liberty, and dedicated to the proposition that all men are created equal.
Behind the scenes, the operating system uses a position indicator as it reads the file. That indicator keeps track of the bytes read and which byte is to be read next. The indicator continues to increment as the file is read.
The ftell() function returns the file position indicator value. Its argument is the open file handle (pointer) and it returns a long int value indicating the file position.
To check the file-reading progress, modify the code above. Change Line 18 to read:
printf("(%ld)%c",ftell(fh),c);
The ftell() function is defined in stdio.h
, so the above line is the only modification you need to make to the code. The function returns a long int (%ld
) value, which the printf() function sets in parentheses for the output.
Save and build the code. Here’s the output:
(1)F(2)o(3)u(4)r(5) (6)s(7)c(8)o(9)r(10)e(11) (12)a(13)n(14)d(15) (16)s(17)e(18)v(19)e(20)n(21) (22)y(23)e(24)a(25)r(26)s(27) (28)a(29)g(30)o(31) (32)o(33)u(34)r(35) (36)f(37)a(38)t(39)h(40)e(41)r(42)s(43) (44)b(45)r(46)o(47)u(48)g(49)h(50)t(51) (52)f(53)o(54)r(55)t(56)h(57) (58)o(59)n(60) (61)t(62)h(63)i(64)s(65) (66)c(67)o(68)n(69)t(70)i(71)n(72)e(73)n(74)t(75) (76)a(77) (78)n(79)e(80)w(81) (82)n(83)a(84)t(85)i(86)o(87)n(88),(89) (90)c(91)o(92)n(93)c(94)e(95)i(96)v(97)e(98)d(99) (100)i(101)n(102) (103)l(104)i(105)b(106)e(107)r(108)t(109)y(110),(111) (112)a(113)n(114)d(115) (116)d(117)e(118)d(119)i(120)c(121)a(122)t(123)e(124)d(125) (126)t(127)o(128) (129)t(130)h(131)e(132) (133)p(134)r(135)o(136)p(137)o(138)s(139)i(140)t(141)i(142)o(143)n(144) (145)t(146)h(147)a(148)t(149) (150)a(151)l(152)l(153) (154)m(155)e(156)n(157) (158)a(159)r(160)e(161) (162)c(163)r(164)e(165)a(166)t(167)e(168)d(169) (170)e(171)q(172)u(173)a(174)l(175).(176)
(177)
The first character in the file has a position value of one, not zero. The indicator is probably initialized at zero, but then clicks up to one after reading that first character. The indicator continues to increment for each character read from the file.
The information supplied by ftell() is interesting, but your code could easily count the number of characters (or bytes) read from a file. The useful part comes from manipulating the file position indicator, which I’ll cover in next week’s Lesson.