Two types of I/O file functions
- Fopen
ANSI standard file I/O, based on low-level I/O
- Open
Low-level I/O
Ansi I/O Nature
- DOS/Windows platform, ms dos file read/write, compilation language
- Linux platform, Unix/Linux File read/write, C Language
File Type
Contains a pointer
Contains a stream (the C language regards the file as stream
)
File Open
R
Open Text File for reading
R +
Open for reading and writing
W truncate
File to zero length or create text file for writing
W +
The file is created if it does not exist,
Otherwise it is truncated
A
Open
Appending (writing at end of file ).
The stream is positioned at the end of the file.
Fopen three basic modes: R, W, and
Parts
C language allows up to 16 files to be opened at the same time
Only 13 files can be opened at the same time, because there are three other standard files stdout, stdin, stderr
Basic statements for file read/write
1 |
# Include <stdio. h> File * Stream; note that the data type is uppercase. |
2 |
If (Stream = fopen ("testtmp", "R +") = NULL) {Printf ("Open File error/N "); Return; } |
3 |
Int ret; If (ret = fclose (Stream) =-1) printf ("Close file Error/N "); |
Read files in sequence (by character)
While (C = fgetc (Stream ))! =
EOF
)
Printf ("% C", C );
The file pointer will (automatically) move one cell per read character
Sequential reading of a file (by string) ------- read one row from a file until null is read.
Char record [100], * Re;
While (RE = fgets (record, 100
, Stream ))! = NULL
)
Printf ("% s", record );
Read a row. Press enter to wrap the line as the tail sign of the row to be read.
The fgets string from the file is to read a row, that is, including the carriage return
Therefore, printf ("% s") does not need "% s/n", because the string contains a carriage return.
This is also a vulnerability where a carriage return is included in the string.
Therefore, it is not conducive to strcmp
Scanf reads the file, the file pointer is not moved, you need to manually move the pointer fseek
Fseek (stream, 3, seek_set ); Fscanf (stream, "% C", & C [0]); Fseek (stream, 11, seek_set ); Fscanf (stream, "% C", & C [1]); |
Read/write to the end of the file
The file pointer indicates null.
(Instead of EOF, EOF is not an address, but an ending character.
)
Fput (), fgetc () will return EOF
Fgets () returns NULL.
Linux and DOS have different end discrimination for files.
Linux does not have a file Terminator
It uses the file length of the Directory item as the identification method for end of the file
DOS check 0x1a file Terminator
Differences between line breaks in Linux and DoS
Linux |
DoS |
0x0a 10
That is, '/N' That is, lf |
Cr, lf dual-code |
When reading a file, you cannot use unsigned char C as the return value,
Because EOF is not in the unsigned range
Char C;
C = GETC (Stream );
Fscanf reads the numbers in the text file, either % C or % d.
Read with % C (char), can read 3, 1 |
Read with % d (INT) or 3, 1 |
Fseek (stream, 3, seek_set ); Fscanf (stream, "% C", & C [0]); Fseek (stream, 11, seek_set ); Fscanf (stream, "% C", & C [1]); |
Fseek (stream, II, seek_set ); Fscanf (stream, "% d", & ln [I]. Frame ); Fseek (stream, II + 8, seek_set ); Fscanf (stream, "% d", & ln [I]. line ); |
Only the two three, one is the actual value 3, 1, the other is '3', '1'
Integer numbers with several common special characters
Char |
Int |
Space'' |
32 |
Tab key |
9 |
Enter |
10 |
End EOF |
-1 |
String end symbol |
Number 0 (not '0 ') |
Be careful when handling TAB characters. After you copy/paste to notepad, the tab key is converted into several spaces.
For (; STR [I] =' '| STR [I] ='
'; I ++ ); |
But after the notepad copy/paste, the tab key is converted into several spaces Therefore, the system always reports the following: TMP. C: 58: Warning: comparison is always false due to limited range Of Data Type TMP. C: 59: 27: Warning: character constant too long for its Type |
Change the fgets string pointer to a string array to eliminate segmentation.
Fault Error
Char * re, * REC; Re = fgets (REC, 100, srcstream );Output segmentation fault Error |
Change Char * re, REC [100]; Re = fgets (REC, 100, srcstream );Error disappears |
A common display file content
Functions
Printfile (File * stream, char * filename, Int or) { Int I, RE; Char rec [100]; File * tmpstream; If (OR) { If (tmpstream = fopen (filename, "R") = NULL) { Printf ("Open File error/N ");
Return 0;
} For (I = 0; (RE = fgets (REC, 100, tmpstream ))! = NULL; I ++) Printf ("[% d]: % s", I, REC ); When the file content is displayed, the row number is added to each line. If (RE = fclose (tmpstream) =-1) printf ("close File error/N ");} Else { Fseek (stream, 0, seek_set ); For (I = 0; (RE = fgets (REC, 100, stream ))! = NULL; I ++) Printf ("[% d]: % s", I, REC ); } } |
Printfile (null, "testtmp. tmp", 1 );[0]: Total 48 [1]: 1 MACG 3301 Jan 16 file. c [2]:-RW-r -- 1 MACG MACG 52 Jan 16 Makefile [3]: 1 MACG 0 Jan 16 testtmp [4]: This is a testthis is A testth [5]:-RW-r -- 1 MACG 1428 Jan 16 TMP. o |
If (Stream = fopen ("testtmp", "R +") = NULL) {Printf ("Open File error/N "); Return 0; } Printfile (Stream , Null, 0 );[0]: Total 48 [1]:-RW-r -- 1 MACG 3301 Jan 16
File. c [2]:-RW-r -- 1 MACG MACG 52 Jan 16 Makefile [3]: -RW-r -- 1 MACG MACG 0 Jan 16 02: 56 testtmp [4]: This is a testthis is A testth [5]:-RW-r -- 1 MACG 1428 Jan 16 TMP. o |
According to the SED/awk principle, the function for reading records/rows is to retrieve the row recno from the file.
Int getrecord (char * rec, file * stream, int recno) { Int I, RET; Char * Re; For (I = 0; I <= recno; I ++) Re = fgets (REC, 100, stream ); Number rows and read rows on one sideIf (RE = NULL) return 0; If the row length exceeds the file length, 0 is returned. Else return 1; } |
Getrecord (record, stream, 4 ); Take the record/row and the fourth row of the file Printf ("record is % s/n", record ); Printf ("/n "); |
$./Tmp Record Is -RW-r -- 1 MACG MACG 0 Jan 16 02: 56 testtmp |
According to the SED/awk principle, read the field function -- Obtain the valueno field from the string
Int getvalue (char * STR, int valueno, char * value) { Int I, j, Vali;Number segment
For (I = 0, Vali = 0; vali <valueno; vali ++) { For (; STR [I] = ''| STR [I] = 9; I ++ ); For (; STR [I]! =' '& STR [I]! = 9 & STR [I]! = 0; I ++ ); If (STR [I] = 0) return 0; } Retrieve Fields
For (; STR [I] = ''| STR [I] = 9; I ++ ); For (j = 0; STR [I]! =' '& STR [I]! = 9 & STR [I]! = 0; I ++, J ++) { Value [J] = STR [I]; } Value [J] = 0; } |
For (I = 0; I <20; I ++) { If (getvalue (record, I, Val) printf ("No % d is % s/n", I, Val ); } |
$./Tmp Record Is -RW-r -- 1 MACG MACG 0 Jan 16 02: 56 testtmp This row was edited intentionally in advance, and several tabs were added, including tabs at the end of the row.
No 0 is-RW-r -- No 1 is 1 No 2 is MACG No 3 is MACG No 4 is 0 No 5 is Jan No 6 is 16 No 7 is No 8 is testtmp No 9 is |
Fputs (stren, streamwrite)
The Written string does not contain a carriage return, and fprintf (strea, "% s", STR) does not contain a carriage return. Therefore, to write a file to a carriage return, you must write/n.
Fputs (stren, streamwrite ); Cat aaa.txt 008421aa
|
Fprintf (streamwrite, "% s/n ", Stren );Cat aaa.txt 008421
AA
|
It is difficult to modify and write the file. We recommend that you append the file.
The best way is to write new files.
, Or write to stdout and then redirect to the file. Then overwrite the old file.
Writefile (char * tmpfilename, char
* Srcfilename, struct filerecord * FR, int
Frsi) ------- modify the file Function
Actually reading files from srcfile
Modify the row that matches the WordPress [J]. recno to the WordPress [J]. Record.
The other rows remain unchanged and are still read using srcfile.
Then write these rows into a new file tmpfile.
Writefile (char * tmpfilename, char * Srcfilename, struct filerecord * FR, int frsi O tmpfilename New File NameO srcfilename Old File Name O struct Filerecord * the struct array of the row to be modified in the WordPress. Struct filerecord { Char record [100]; Int recno; }; Struct filerecord FR [20]; O Number of elements in the frsi struct Array |
Writefile (char * tmpfilename, char * srcfilename, struct filerecord * FR, int frsi) { Int No, RET, I, j, bol; Char * re, REC [100]; File * tmpstream, * srcstream;If (tmpstream = fopen (tmpfilename, "W + ") = NULL) Write a new { Printf ("Open File error/N ");
Return 0; } If (srcstream = fopen (srcfilename, "R") = NULL) {Printf ("Open File error/N ");
Return 0; } For (NO = 0; (RE = fgets (REC, 100, srcstream ))! = NULL; no ++) { For (j = 0, bol = 1; j <frsi & Bol; j ++) { If (NO = FR [J]. recno ){
BOL = 0;
Strcpy (REC, FR [J]. Record );
} } Fputs (REC, tmpstream ); } If (ret = fclose (tmpstream) =-1) printf ("Close file Error/N "); If (ret = fclose (srcstream) =-1) printf ("Close file Error/N "); } |
Example: remove the tab key and leading space or tab in the file. Run:
Read each line of the original file, checkinvaild (), and check whether it contains a tab. The first line is space/tab.
If yes, recombine and remove the tab. The space/tab is first written into the struct person FR [20] array.
Writefile ("testtmp. tmp", "testtmp", FR, Fri ); ------------------ The sick File ---------------------------------------- [0]: Total 48 [1]:-RW-r -- 1 MACG 3301 Jan 16
File. c [2]:-RW-r -- 1 MACG MACG 52 Jan 16 Makefile [3]: -RW-r -- 1 MACG MACG 0 Jan 16 02: 56 testtmp [4]: This is a testthis is A testth [5]:-RW-r -- 1 MACG 1428 Jan 16 TMP. o -------------------- Modify Line -------------------------------------- Fri is 2, the new line is following: [1] row: 1 MACG 3301 Jan 16 file. c [3] row: 1 MACG 0 Jan 16 0:56 testtmp ------------------- New File --------------------------------------- [0]: Total 48 [1]: 1 MACG 3301 Jan 16 file. c [2]:-RW-r -- 1 MACG MACG 52 Jan 16 Makefile [3]: 1 MACG 0 Jan 16 testtmp [4]: This is a testthis is A testth [5]:-RW-r -- 1 MACG 1428 Jan 16 TMP. o |
Three Modes of fseek (stream, offset, Mode)
Seek_set: Number of offsets starting from
Seek_cur: Number of offsets from the current number
Seek_end: The last offset from the end.
The file pointer position starts from 0 (File Header ).
Fseek (stream, 0, seek_set );
Int ftell (File
* Stream)
Returns the current pointer position of stream.
Simple operations on getting the file size and size
Fseek (stream, 0, seek_end); first point the pointer to the end of the file Ret = ftell (Stream); then obtain the current address indicated by the pointer
The pointer address pointing to the end of the file is the file size. |
The file size operation is very useful for reading and writing files, because it is difficult to judge the end of the file.
File example
$ Cat TMP. c # Define debug 0# Include <stdio. h> # Include <string. h> # Include <unistd. h> Struct filerecord { Char record [100]; Int recno; }; Main () { Char directory [100]; # Ifdef syst Getcwd (directory, 100 ); Printf ("Current directory is % s/n", directory ); # Endif Filemanage (); } Filemanage () { Int I, j, Fri, RET; Char record [2, 100], Val [50], modi_rec [100]; File * stream; Struct filerecord FR [20]; If (Stream = fopen ("testtmp", "R +") = NULL) {Printf ("Open File error/N "); Return 0; } Printf ("------------------ the sick File -----------------------/N "); Printfile (stream, null, 0 ); For (I = 0, Fri = 0; getrecord (record, stream, I); I ++) { If (Debug) printf ("No % d row is: % s/n", I, record ); If (ret = findinvalid (record ))
{ For (j = 0; getvalue (record, J, Val); j ++)
{ If (Debug) printf ("No % d's Val is % s % D/N ", J, Val, Val [0]);
If (j = 1) strcpy (modi_rec, Val );
If (j> 1 ){
Strcat (modi_rec ,"");
Strcat (modi_rec, Val );
}
} FR [Fri]. recno = I; Strcpy (FR [Fri]. Record, modi_rec ); If (Debug) printf ("FR [% d] is % d % S/n ", Fri, FR [Fri]. recno, FR [Fri]. Record ); Fri ++;
} If (Debug) printf ("---------------------------------/N "); } Printf ("-------------------- modify Line --------------------/N "); Printf ("Fri is % d, the new line is following:/N", Fri ); For (I = 0; I <Fri; I ++) Printf ("[% d] row: % s", FR [I]. recno, FR [I]. Record ); If (ret = fclose (Stream) =-1) { Printf ("Close file error/N "); Return 0; } Writefile ("testtmp. tmp", "testtmp", FR, Fri ); Printf ("------------------- new file -----------------/N "); Printfile (null, "testtmp. tmp", 1 ); } Int findinvalid (char * Str) { Int I, RET; I = 0; If (STR [I] = '') { If (Debug) printf ("str [% d] = % d/N", I, STR [I]); Return 32; } For (I = 0; STR [I]! = 9 & STR [I]! = 0; I ++) ; If (STR [I] = 9) { If (Debug) printf ("str [% d] = % d/N", I, STR [I]); Return 9; } Else { If (Debug) printf ("str [% d] = % d/N", I, STR [I]); Return 0; } } |
$ Make Gcc-g-c tmp. c TMP. C: In function compute extends rintfile syntax? TMP. C: 158: Warning: Assignment makes integer from pointer without Cast TMP. C: 158: Warning: Comparison between pointer and integer TMP. C: 165: Warning: Assignment makes integer from pointer without Cast TMP. C: 165: Warning: Comparison between pointer and integer Gcc-o tmp. O-G |
$./Tmp ------------------ The sick file ---------------------- [0]: Total 48 [1]:-RW-r -- 1 MACG 3301 Jan 16
File. c [2]:-RW-r -- 1 MACG MACG 52 Jan 16 Makefile [3]: -RW-r -- 1 MACG MACG 0 Jan 16 02: 56 testtmp [4]: This is a testthis is A testth [5]:-RW-r -- 1 MACG 1428 Jan 16 TMP. o -------------------- Modify line -------------------- Fri is 2, the new line is following: [1] row: 1 MACG 3301 Jan 16 file. c [3] row: 1 MACG 0 Jan 16 0:56 testtmp ------------------- New file ------------------------- [0]: Total 48 [1]: 1 MACG 3301 Jan 16 file. c [2]:-RW-r -- 1 MACG MACG 52 Jan 16 Makefile [3]: 1 MACG 0 Jan 16 testtmp [4]: This is a testthis is A testth [5]:-RW-r -- 1 MACG 1428 Jan 16 TMP. o |