Brother Jiang takes you to play with C language | 17 - file operation

Posted by gentusmaximus on Mon, 31 Jan 2022 14:12:06 +0100

Basic concepts of documents

  • File stream:
    • c language regards a file as a sequence of characters, that is, a file is a character stream composed of one character. Therefore, c language also calls a file a file stream.
  • Document classification
    • text file

      • It is stored in ASCII format, and one character is stored in one byte. Each byte of the text file stores an ASCII code, representing a character. This facilitates character by character processing, but takes up storage space
        More, and it takes time to convert.
      • . c files are stored as text files
    • Binary file

      • Stored in complement format. Binary files store data in files in the form of binary numbers, which takes up less storage space. The data is stored as it is in the memory
      • The. exe file is stored as a binary file
  • Examples of text and binary files
    • The following code is not required to be understood for the time being. It mainly understands what is a text file and what is a binary file
#include <stdio.h>

int main()
{
    /*
     * Store as text
     * Each character will be converted to the corresponding ASCII first,
     * Then the binary of ASCII code is stored in the computer
     */
    int num = 666;
    FILE *fa = fopen("ascii.txt", "w");
    fprintf(fa, "%d", num);
    fclose(fa);

    /*
     * Stored in binary form
     * The binary of 666 will be stored directly in the file
     */
    FILE *fb = fopen("bin.txt", "w");
    fwrite(&num, 4, 1, fb);
    fclose(fb);

    return 0;
}
  • Memory diagram

  • Open footprint with text tool

  • By default, the text tool will directly decode the files one by one according to the ASCII code. Because the text file stores the ASCII code, it can be parsed and displayed normally. Because the binary file stores no ASCII code, it is garbled after parsing

Opening and closing of files

  • FILE structure
    • The FILE structure is the recorder of the read and write status of buffers and files. All operations on files are completed through the FILE structure.
  struct _iobuf {
    char *_ptr;  //Next location for file input
    int _cnt;  //The relative position of the current buffer
    char *_base; //(start of file)
    int _flag; //File flag
    int _file;  //Validation of documents
    int _charbuf; //Check the buffer condition. If there is no buffer, it will not be read
    int _bufsiz; // Buffer size
    char *_tmpfname; //Temporary file name
  };
  typedef struct _iobuf FILE;
  • fileopen function
Function declarationFILE * fopen ( const char * filename, const char * mode );
Filestdio.h
Function functionIn mode, open a FILE named filename and return a pointer to the FILE structure of the FILE buffer.
Parameter and return analysis
parameterchar*filaname: the path to open or create the file.
parameterchar*mode: the way to open a file.
Return valueFILE * returns a pointer to the FILE buffer, which is the handle of the subsequent operation FILE.
modeTreatment methodWhen the file does not existWhen file existsInput to fileExport from file
rreaderrorOpen fileNosure
wwrite inCreate new fileOverwrite original filesureNo
aAddCreate new fileAppend after original documentsureNo
r+Read / writeerrorOpen filesuresure
w+Write / readCreate new fileOverwrite original filesuresure
a+Read / appendCreate new fileAppend after original documentsuresure

Note:

  • If Windows reads and writes binary files, it also needs to add b, such as rb, r+b, etc. unix/linux does not distinguish between text and binary files
  • fclose function
Function declarationint fclose ( FILE * stream );
Filestdio.h
Function functionfclose() is used to close files previously opened by fopen()
Function functionThis action will make the data in the buffer write to the file and release the file resources provided by the system
Parameter and return analysis
parameter* pointer to the buffered file: stream.
Return valueint returns 0 for success and EOF(-1) for failure.
#include <stdio.h>

int main()
{
    FILE *fp = fopen("test.txt", "w+");
    fclose(fp);
    return 0;
}

Read and write one character at a time

  • write in
Function declarationint fputc (int ch, FILE * stream );
Filestdio.h
Function functionWrite the ch character to the file.
Parameter and return analysis
parameter* pointer to the buffered file: stream.
parameterint: the character to be written.
Return valueint is written successfully, and the character of write success is returned. If it fails, EOF is returned.
#include <stdio.h>

int main()
{
    // 1. Open a file
    FILE *fp = fopen("test.txt", "w+");

    // 2. Write content to the file
    for(char ch = 'a'; ch <= 'z'; ch++){
        // Write one character at a time
        char res = fputc(ch, fp);
        printf("res = %c\n", res);
    }

    // 3. Close the open file
    fclose(fp);
    return 0;
}
  • read
Function declarationint fgetc ( FILE * stream );
Filestdio.h
Function functionRead a character from the file stream and return it.
Parameter and return analysis
parameter* pointer to the buffered file: stream.
Return valueint is normal and returns the read characters; EOF when the end of the file is read or an error occurs.
#include <stdio.h>

int main()
{
    // 1. Open a file
    FILE *fp = fopen("test.txt", "r+");

    // 2. Read content from file
    char res = EOF;
    while((res = fgetc(fp)) != EOF){
        printf("res = %c\n", res);
    }

    // 3. Close the open file
    fclose(fp);
    return 0;
}
  • Judge the end of the file
    • feof function
Function declarationint feof( FILE * stream );
Filestdio.h
Function functionJudge whether the file is read to the end of the file
Parameter and return analysis
parameter* pointer to the buffered file: stream.
Return valueint 0 did not read to the end of the file, non-zero read to the end of the file.
#include <stdio.h>

int main()
{
    // 1. Open a file
    FILE *fp = fopen("test.txt", "r+");

    // 2. Read content from file
    char res = EOF;
    // Note: since the flag bit can be modified only after reading it first,
    // Therefore, to judge whether to reach the end of the file through feof, you must read it first and then judge it. You can't judge it first and then read it
    while((res = fgetc(fp)) && (!feof(fp))){
        printf("res = %c\n", res);
    }

    // 3. Close the open file
    fclose(fp);
    return 0;
}
  • Note:
  • feof this function is to read the flag bit to determine whether the file is over.
  • The flag bit can only be modified after reading, so if you judge first and then read the flag bit, you will hit it again
  • Therefore, when using feof function in enterprise development, we must read it first and then judge it, not judge it first and then read it
  • task
    • Realize the simple encryption and decryption of files
#include <stdio.h>
#include <string.h>
void encode(char *name, char *newName, int code);
void decode(char *name, char *newName, int code);
int main()
{
    encode("main.c", "encode.c", 666);
    decode("encode.c", "decode.c", 666);
    return 0;
}
/**
 * @brief encode Encrypted file
 * @param name File name to be encrypted
 * @param newName Encrypted file name
 * @param code Secret key
 */
void encode(char *name, char *newName, int code){
    FILE *fw = fopen(newName, "w+");
    FILE *fr = fopen(name, "r+");
    char ch = EOF;
    while((ch = fgetc(fr)) && (!feof(fr))){
        fputc(ch ^ code, fw);
    }
    fclose(fw);
    fclose(fr);
}
/**
 * @brief encode Decrypt file
 * @param name Name of the file to be decrypted
 * @param newName Decrypted file name
 * @param code Secret key
 */
void decode(char *name, char *newName, int code){
    FILE *fw = fopen(newName, "w+");
    FILE *fr = fopen(name, "r+");
    char ch = EOF;
    while((ch = fgetc(fr)) && (!feof(fr))){
        fputc(ch ^ code, fw);
    }
    fclose(fw);
    fclose(fr);
}

Read and write one line of characters at a time

  • What is OK
  • Line is a concept in the text editor, and a character is in the file stream. This is different on different platforms. Windows platform '\ r\n', linux platform '\ r\n'
  • Platform differences
    • When writing '\ n' on windows platform, it will be reflected as' \ r\n ', and when writing' \ n 'on linux platform, it will be reflected as' \ n'. When reading '\ r\n' in windows platform, it is reflected as a character '\ n', and when reading '\ n' in linux platform, it is reflected as a character '\ n'
    • If linux reads the line feed in windows, it will read one more character. If windows reads the line feed in linux, there is no problem
#include <stdio.h>

int main()
{
    FILE *fw = fopen("test.txt", "w+");
    fputc('a', fw);
    fputc('\n', fw);
    fputc('b', fw);
    fclose(fw);
    return 0;
}

  • Write one line
Function declarationint fputs(char *str,FILE *fp)
Filestdio.h
Function functionWrite the string pointed to by str to the file pointed to by fp.
Parameter and return analysis
parameterchar * str: pointer to the string pointed to.
parameterFILE *fp: pointer to the file stream structure.
Return valueint normal, return to 0; Error returned to EOF.
#include <stdio.h>

int main()
{
    FILE *fw = fopen("test.txt", "w+");
    // Note: fputs will not be automatically added \ n
    fputs("lnj\n", fw);
    fputs("it666\n", fw);
    fclose(fw);
    return 0;
}
  • Encountered \ 0 auto terminate write
#include <stdio.h>

int main()
{
    FILE *fp = fopen("test.txt", "w+");
    // Note: fputs will automatically terminate writing when encountering \ 0 during writing
    fputs("lnj\0it666\n", fp);

    fclose(fp);
    return 0;
}
  • Read one line
Function declarationchar *fgets(char *str,int length,FILE *fp)
Filestdio.h
Function functionRead at most length-1 characters from the file pointed to by fp and send them into the character array str. if you encounter \ n or EOF before the end of reading length-1 characters, the reading will end. After reading the string, add a '\ 0' character at the end.
Parameter and return analysis
parameterchar * str: point to the buffer where data needs to be read in.
parameterint length: the number of characters read at each time.
parameterFILE* fp: file stream pointer.
Return valuechar * normal, return str pointer; Error or NULL pointer returned at end of file encountered.
  • A maximum of N-1 characters can be read
#include <stdio.h>

int main()
{
    FILE *fp = fopen("test.txt", "w+");
    // Note: fputs will not be automatically added \ n
    fputs("it666\n", fp);

    // Move the read-write pointer in the FILE structure back to the front
    // Note: the read / write pointer in the FILE structure will move back after each character is read or written
    rewind(fp);
    char str[1024];
    // Read 4 characters from fp and store them in str
    // Can only read N-1 characters at most, and will be automatically added at the end \ 0
    fgets(str, 4, fp);

    printf("str = %s", str); // it6
    fclose(fp);
    return 0;
}
  • Auto end encountered \ n
#include <stdio.h>
int main()
{
    FILE *fp = fopen("test.txt", "w+");
    // Note: fputs will not be automatically added \ n
    fputs("lnj\n", fp);
    fputs("it666\n", fp);

    // Move the read-write pointer in the FILE structure back to the front
    // Note: the read / write pointer in the FILE structure will move back after each character is read or written
    rewind(fp);
    char str[1024];
    // Read 1024 characters from fp and store them in str
    // But after reading the fourth one, the function will automatically stop reading
    // Note: \ n will be read in
    fgets(str, 1024, fp);

    printf("str = %s", str); // lnj
    fclose(fp);
    return 0;
}
  • Read EOF automatically ends
#include <stdio.h>

int main()
{
    FILE *fp = fopen("test.txt", "w+");
    // Note: fputs will not be automatically added \ n
    fputs("lnj\n", fp);
    fputs("it666", fp);

    // Move the read-write pointer in the FILE structure back to the front
    // Note: the read / write pointer in the FILE structure will move back after each character is read or written
    rewind(fp);
    char str[1024];
    // 1024 characters are read from fp each time and stored in str
    // Automatic end when reading to the end of the file
    while(fgets(str, 1024, fp)){
        printf("str = %s", str);
    }
    fclose(fp);
    return 0;
}
  • Note:
    • feof function is not needed in enterprise development
    • If there is no line '\ n' in the last line, read one less line
#include <stdio.h>

int main()
{
    FILE *fp = fopen("test.txt", "w+");
    // Note: fputs will not be automatically added \ n
    fputs("12345678910\n", fp);
    fputs("12345678910\n", fp);
    fputs("12345678910", fp);

    // Move the read-write pointer in the FILE structure back to the front
    // Note: the read / write pointer in the FILE structure will move back after each character is read or written
    rewind(fp);
    char str[1024];
    // 1024 characters are read from fp each time and stored in str
    // Automatic end when reading to the end of the file
    while(fgets(str, 1024, fp) && !feof(fp)){
        printf("str = %s", str);
    }
    fclose(fp);
    return 0;
}
  • Job:
    • How many times will the following text be read using fgets(str, 5, fp)?
12345678910
12345
123

Read and write one piece of data at a time

  • C language has been distinguished from the interface level, text reading and writing mode and binary reading and writing mode. What we talked about earlier is the way of reading and writing text.
  • All file interface functions either end with '\ 0', or end with '\ n', EOF(0xFF)\ 0 '' \ n 'and others are important identifications of text files, and all binary interfaces are insensitive to these identifications.
    +Binary interfaces can read text, while text interfaces cannot read binary
  • Write one piece of data at a time
Function declarationint fwrite(void *buffer, int num_bytes, int count, FILE *fp)
Filestdio.h
Function functionWrite the data pointed to by buffer into the file pointed to by fp
parameterchar * buffer: pointer to the first address of the data storage area to be written
int num_bytes: bytes of each field to be written count
int count: the number of fields to write
FILE* fp: pointer to the file to be written
Return valueint success, return the number of fields written; Error or end of file, return 0.
#include <stdio.h>
#include <string.h>

int main()
{
    FILE *fp = fopen("test.txt", "wb+");
    // Note: fwrite does not care about the format of the written data
    char *str = "lnj\0it666";
     /*
     * First parameter: written data pointer
     * Second parameter: how many bytes are written each time
     * The third parameter: how many times to write
     * Fourth parameter: pointer to the opened file structure
     */
    fwrite((void *)str, 9, 1, fp);

    fclose(fp);
    return 0;
}
  • Read one piece of data at a time
Function declarationint fread(void *buffer, int num_bytes, int count, FILE *fp)
Filestdio.h
Function functionRead the data in the file pointed to by fp into the buffer.
parameterchar * buffer: pointer to the first address of the data storage area to be read
int num_bytes: bytes of each field to be read count
int count: the number of fields to read
FILE* fp: pointer to the file to be read
Return valueint success, return the number of read fields; Error or end of file, return 0.
#include <stdio.h>

int main()
{
    // test.txt is "lnj"lnj \ 0it666"it666"
    FILE *fr = fopen("test.txt", "rb+");
    char buf[1024] = {0};
    // The fread function returns the number of bytes read after reading successfully, and 0 if reading fails
    /*
     * First parameter: the container that stores the read data
     * Second parameter: how many bytes are read each time
     * The third parameter: how many times to read
     * Fourth parameter: pointer to the opened file structure
     */ 
    int n = fread(buf, 1, 1024, fr);
    printf("%i\n", n);
    for(int i = 0; i < n; i++){
        printf("%c", buf[i]);
    }
    fclose(fr);
    return 0;
}
  • Note:
  • Read num_bytes should be filled in the minimum unit of the read data type, while count can be written at will
  • If num is read_ Bytes is not the smallest unit of read data type, which will cause read failure
  • For example, stored is char type 6C 6e 6A 00 69 74 36
    If num_ If bytes is equal to 1 and count is equal to 1024, take out 6C 6e 6A 00 69 74 36 successively until it cannot be taken
    If num_ If bytes is equal to 4 and count is equal to 1024, then [6C 6E 6A 00][69 74 36 36] will be taken out in turn, but there is still one 36 left, but it does not meet 4 bytes, then the last 36 will not be taken
#include <stdio.h>
#include <string.h>

int main()
{

    // test.txt is "lnj"lnj \ 0it666"it666"
    FILE *fr = fopen("test.txt", "rb+");
    char buf[1024] = {0};
    /*
    while(fread(buf, 4, 1, fr) > 0){
        printf("%c\n", buf[0]);
        printf("%c\n", buf[1]);
        printf("%c\n", buf[2]);
        printf("%c\n", buf[3]);
    }
    */
    /*
    while(fread(buf, 1, 4, fr) > 0){
        printf("%c\n", buf[0]);
        printf("%c\n", buf[1]);
        printf("%c\n", buf[2]);
        printf("%c\n", buf[3]);
    }
    */
    while(fread(buf, 1, 1, fr) > 0){
        printf("%c\n", buf[0]);
    }
    fclose(fr);
    return 0;
}
  • Note: fwrite and fread are essentially used to manipulate binaries
  • So the following usage is their correct opening posture
#include <stdio.h>

int main()
{

    FILE *fp = fopen("test.txt", "wb+");
    int ages[4] = {1, 3, 5, 6};
    fwrite(ages, sizeof(ages), 1, fp);
    rewind(fp);
    int data;
    while(fread(&data, sizeof(int), 1, fp) > 0){
        printf("data = %i\n", data);
    }
    return 0;
}

Read write structure

  • The data types in the structure are not unified. At this time, it is most suitable to read and write in binary mode
  • Read and write single structure
#include <stdio.h>

typedef struct{
    char *name;
    int age;
    double height;
} Person;

int main()
{
    Person p1 = {"lnj", 35, 1.88};
//    printf("name = %s\n", p1.name);
//    printf("age = %i\n", p1.age);
//    printf("height = %lf\n", p1.height);

    FILE *fp = fopen("person.stu", "wb+");
    fwrite(&p1, sizeof(p1), 1, fp);

    rewind(fp);
    Person p2;
    fread(&p2, sizeof(p2), 1, fp);
    printf("name = %s\n", p2.name);
    printf("age = %i\n", p2.age);
    printf("height = %lf\n", p2.height);

    return 0;
}
  • Read / write structure array
#include <stdio.h>

typedef struct{
    char *name;
    int age;
    double height;
} Person;

int main()
{
    Person ps[] = {
      {"zs", 18, 1.65},
      {"ls", 21, 1.88},
      {"ww", 33, 1.9}
    };


    FILE *fp = fopen("person.stu", "wb+");
    fwrite(&ps, sizeof(ps), 1, fp);

    rewind(fp);
    Person p;
    while(fread(&p, sizeof(p), 1, fp) > 0){
        printf("name = %s\n", p.name);
        printf("age = %i\n", p.age);
        printf("height = %lf\n", p.height);
    }
    return 0;
}
  • Read write structure linked list
#include <stdio.h>
#include <stdlib.h>

typedef struct person{
    char *name;
    int age;
    double height;
    struct person* next;
} Person;
Person *createEmpty();
void  insertNode(Person *head, char *name, int age, double height);
void printfList(Person *head);
int saveList(Person *head, char *name);
Person *loadList(char *name);

int main()
{

//    Person *head = createEmpty();
//    insertNode(head, "zs", 18, 1.9);
//    insertNode(head, "ls", 22, 1.65);
//    insertNode(head, "ws", 31, 1.78);
//    printfList(head);
//    saveList(head, "person.list");
    Person *head = loadList("person.list");
    printfList(head);
    return 0;
}

/**
 * @brief loadList Load linked list from file
 * @param name File name
 * @return  Loaded chain header pointer
 */
Person *loadList(char *name){
    // 1. Open the file
    FILE *fp = fopen(name, "rb+");
    if(fp == NULL){
        return NULL;
    }
    // 2. Create an empty linked list
    Person *head = createEmpty();
    // 3. Create a node
    Person *node = (Person *)malloc(sizeof(Person));
    while(fread(node, sizeof(Person), 1, fp) > 0){
        // 3. Insert
        // 3.1 make the next node of the new node equal to the next node of the head node
        node->next = head->next;
        // 3.2 make the next node of the head node equal to the new node
        head->next = node;

        // Apply for space for the next node
        node = (Person *)malloc(sizeof(Person));
    }
    // Free up extra node space
    free(node);
    fclose(fp);
    return head;
}

/**
 * @brief saveList Store linked list to file
 * @param head Chain header pointer
 * @param name Stored file name
 * @return  Store success - 1 failed 0 succeeded
 */
int saveList(Person *head, char *name){
    // 1. Open the file
    FILE *fp = fopen(name, "wb+");
    if(fp == NULL){
        return -1;
    }
    // 2. Take out the next node of the head node
    Person *cur = head->next;
    // 3. Save all valid nodes to a file
    while(cur != NULL){
        fwrite(cur, sizeof(Person), 1, fp);
        cur = cur->next;
    }
    fclose(fp);
    return 0;
}
/**
 * @brief printfList Traversal linked list
 * @param head Head pointer of linked list
 */
void printfList(Person *head){
    // 1. Take out the next node of the head node
    Person *cur = head->next;
    // 2. Judge whether it is NULL. If it is not NULL, start traversal
    while(cur != NULL){
        // 2.1 take out the data of the current node and print it
        printf("name = %s\n", cur->name);
        printf("age = %i\n", cur->age);
        printf("height = %lf\n", cur->height);
        printf("next = %x\n", cur->next);
        printf("-----------\n");
        // 2.2 move the current node backward
        cur = cur->next;
    }
}

/**
 * @brief insertNode Insert new node
 * @param head Head pointer of linked list
 * @param p Structure to be inserted
 */
void  insertNode(Person *head, char *name, int age, double height){
    // 1. Create a new node
    Person *node = (Person *)malloc(sizeof(Person));
    // 2. Save data to a new node
    node->name = name;
    node->age = age;
    node->height = height;

    // 3. Insert
    // 3.1 make the next node of the new node equal to the next node of the head node
    node->next = head->next;
    // 3.2 make the next node of the head node equal to the new node
    head->next = node;
}
/**
 * @brief createEmpty Create an empty linked list
 * @return Chain header pointer, NULL returned if creation failed
 */
Person *createEmpty(){
    // 1. Define header pointer
    Person *head = NULL;
    // 2. Create a null node and assign it to the header pointer
    head = (Person *)malloc(sizeof(Person));
    if(head == NULL){
        return head;
    }
    head->next = NULL;
    // 3. Return header pointer
    return head;
}

Other file operation functions

  • ftell function
Function declarationlong ftell ( FILE * stream );
Filestdio.h
Function functionGet the current read / write position of the streaming file, and its return value is the number of bytes that the current read / write position deviates from the file header
Parameter and return analysis
parameterFILE * stream FILE handle
Return valueint succeeded. Returns the number of bytes that the current read / write position deviates from the file header. Failed, return - 1
#include <stdio.h>

int main()
{
    char *str = "123456789";
    FILE *fp = fopen("test.txt", "w+");
    long cp = ftell(fp);
    printf("cp = %li\n", cp); // 0
    // Write a byte
    fputc(str[0], fp);
    cp = ftell(fp);
    printf("cp = %li\n", cp); // 1
    fclose(fp);
    return 0;
}
  • rewind function
Function declarationvoid rewind ( FILE * stream );
Filestdio.h
The function redirects the file pointer to the beginning of a stream.
Parameter and return analysis
parameterFILE * stream FILE handle
Return valuevoid has no return value
#include <stdio.h>

int main()
{
    char *str = "123456789";
    FILE *fp = fopen("test.txt", "w+");
    long cp = ftell(fp);
    printf("cp = %li\n", cp); // 0
    // Write a byte
    fputc(str[0], fp);
    cp = ftell(fp);
    printf("cp = %li\n", cp); // 1
    // New points to the beginning of a stream
    rewind(fp);
    cp = ftell(fp);
    printf("cp = %li\n", cp); // 0
    fclose(fp);
    return 0;
}
  • fseek function
Function declarationint fseek ( FILE * stream, long offset, int where);
Filestdio.h
Function functionOffset file pointer.
Parameter and return analysis
ParametersFILE * stream file handle
long offset offset
int where offset start position
Return valueint returns 0 for success and - 1 for failure
  • Common macros
#define SEEK_CUR 1 current text
#define SEEK_END 2 end of file
#define SEEK_ Start of set 0 file
#include <stdio.h>

int main()
{
    FILE *fp = fopen("test.txt", "w+");
    fputs("123456789", fp);
    // Move the file pointer to the end of the file and offset by 0 units
    fseek(fp, 0, SEEK_END);
    int len = ftell(fp); // Calculate file length
    printf("len = %i\n", len);
    fclose(fp);
    return 0;
}
#include <stdio.h>

int main()
{
    FILE *fp;
   fp = fopen("file.txt","w+");
   fputs("123456789", fp);

   fseek( fp, 7, SEEK_SET );
   fputs("lnj", fp);
   fclose(fp);
    return 0;
}

If you think the article is helpful to you, click like, collect, pay attention to and comment, and support four times with one button, your support is the driving force for brother Jiang's continuous update

Topics: C C++ linked list pointer stream