[C language] Efficient processing of file content: file manipulation tips and tricks in C language

Table of contents

1. File classification

1. Classification by storage medium

2. Classified by storage method

2. Text file

3. Binary code file 

Fourth, the difference between binary and file files 

Five, the file buffer 

 1. How to refresh the file buffer

2. Analog clock

3. File pointer

6. File API

1. Open the file fopen

2. Close the file fclose

3. Read and write fgetc fputc character by character

4. Read and write a string at a time fgets fputs

5. Read and write n blocks of file data at a time fread fwrite

 6. Formatting read and write fscanf fprintfEdit

 1. Format and write fprintf (file pointer, format string, output list)

2. Formatted read fscanf (file pointer, format string, output list)

7. Random reading and writing of files

1. Sequential reading and writing introduces random reading and writing cases

2. Random read and write API

(1) rewind resets the file stream pointer

 (2) ftell returns the number of bytes from the file stream pointer to the file header

(3) fseek file stream pointer positioning

8. File Encryptor


1. File classification

1. Classification by storage medium

Disk file: the data of the file is stored on the disk (audio and video, picture files, document files)

Device file: abstract the external device file through the system

2. Classified by storage method

Physically : Any disk file is physically a binary storage.

Logically : Disk files are divided into binary files and text files .

2. Text file

        Text files are based on character encoding, common encodings include ASCII , UNICODE, etc. Generally, you can directly open it with a text editor

        For example:

        (1) The number 5678 is stored in ASCII as ASCII code:

                 00110101(==53=='5')    00110110   00110111    00111000          4B in total

        (2) Lyric file (lrc): text file 

3. Binary code file 

        Based on value encoding, the data in the memory is output to the disk as it is . Generally, you need to judge by yourself or use specific software to analyze the data format .

        For example: the storage form of the number 5678 is: Binary code: 00010110 00101110

Fourth, the difference between binary and file files 

Text file:

Advantages: One byte represents one meaning, easy to view

Disadvantages: large space, low efficiency

binary file:

Advantages: high efficiency, small space

Disadvantages: variable length, inconvenient to view

Five, the file buffer 

 1. How to refresh the file buffer

1. Line refresh: Refresh when a newline character is encountered .

2. Full refresh: the buffer data is full and refreshed

3. Forced refresh Use the fflush function to refresh the buffer

4. Turn off play new: when the program finishes running, all the buffer data will be refreshed

2. Analog clock

#include<unistd.h>
void test()
{
    int i=0;
    while(1)
    {
        printf(\r%02d:%02d",i/60,i%60);//\r回到行首
        fflush(stdout);//强制刷新
        sleep(1);
        i++;
}

3. File pointer

All library functions         that operate files need to use file pointers to operate files .

3 file pointers opened by default for each process:

(1) stdin : The standard input is the current terminal (keyboard) by default.
The scanf and getchar functions we use get data from this terminal by default.

(2) stdout : standard output , the default is the current terminal (screen)
The printf and puts functions we use output information to this terminal by default
(3) stderr : the standard error output device file defaults to the current terminal (screen)

When our program makes an error and uses the: perror function, the information is printed on this terminal

例:fgets(buf,sizeof(buf),stdin);

        fwrite("hello world",12,1,stdout);//12 blocks of 1 byte output

6. File API

File operation steps: open, read, write, close

1. Open the file fopen

        f in fopen describes it as a library function, and its bottom layer uses the open function to complete the system call.

Definition: FILE *fopen(const char *path, const char *mode);

path: the path of the file

mode: Open file mode

return value:

        Success: the open file pointer

        Failed: NULL

File opening mode: r, w, a, +, t, b

r : open as read-only

w : Open for writing only

a : Open by appending (clear and rewrite)

+ : open in readable and writable mode

t : Open as a text file (default, can be omitted)

b : open in binary mode (must show description)

 Combination method:

model Function
r or rb open a file read-only (do not create a file)
w or wb Open file for writing (truncate file length to 0 bytes ( delete ), create a file)
a or ab Open the file in the append mode, that is, add content at the end. When the file does not exist, create a file for append writing
r+ or rb+ Open the file for reading and writing ( do not create a new file)
w+ or wb+ Open file as readable, writable
(make file length 0 bytes ( delete ), create a file)
a+ or ab+ Open the file as add, open the file and change the file at the end (create the file if it doesn't exist)

2. Close the file fclose

Definition: int fclose(FILE *fp);

return value:

        Returns 0 on success

        Return non-0 on failure

void test()
{
	FILE* fp = NULL;
	fp = fopen("test.txt", "r");
	if (fp = NULL)//文件不存在
	{
		perror("fopen");
		return;
	}
	fclose(fp);
}

3. Read and write fgetc fputc character by character

Write one byte at a time : fputc

Function definition: int fputc(int c, FILE *stream)

Function description: fputc writes the value of c to the file represented by stream.

Return value:
        If the output is successful , return the byte value of the output ;

Returns an EOF         if output fails .

EOF is a macro symbol constant defined in the stdio.h file, with a value of -1, and EOF is only valid in text files .

 Write the hello world string:

void test()
{
	FILE* fp = NULL;
	fp = fopen("test.txt", "w");
	if (fp = NULL)
	{
		perror("fopen");
		return;
	}
	char* file_data = "hello word";
	while (*file_data != '\0')
	{
		fputc(*file_data, fp);
		file_data++;
	}
	fclose(fp);
}

Read one byte at a time : fgetc

Function definition: int fgetc(FILE *stream);

Function description: fgetc reads a byte from the file marked by stream, and returns the byte value

Return value:
        in the way of t : read to the end of the file and return EOF
        in the way of b : read to the end of the file, use the feof function (will be discussed later) to judge the end

 Read strings one by one:

void test()
{
	FILE* fp = NULL;
	fp = fopen("test.txt", "r");
	if (fp = NULL)
	{
		perror("fopen");
		return;
	}
	while(1)
	{
		char ch = fgetc(fp);
		if (ch != EOF)
			break;
		printf("%c", ch);
	}
	fclose(fp);
}

4. Read and write a string at a time fgets fputs

Write a string: int fputs(const char *s, FILE *stream)

Read a string: char *fgets(char *s, int size, FILE *stream)

Read a string (end of line break), read a line of file data

Successfully return the first address of the destination array , namely s

Return NULL on failure

 There is a test program that reads the data in the test.txt file and writes it to b.txt under the test.txt file:

void test06()
{
    FILE *fp_r = fopen("test.txt", "r");
    if (fp_r == NULL)
    {
         perror("fopen");
         return;
    }
    FILE *fp_w = fopen("b.txt", "w");
    if (fp_w == NULL)
    {
        perror("fopen");
        return;
    }

    while (1)
    {
        char buf[128] = "";//存放读到的数据并写到b.txt中
        //读一行
        char *ret = fgets(buf, sizeof(buf), fp_r);
        if (ret == NULL)
        break;

        //写一行
        fputs(buf, fp_w);
    }

 fclose(fp_r);
 fclose(fp_w);
}

5. Read and write n blocks of file data at a time fread fwrite

块写:size_t fwrite(void *ptr, size_t size, size_t n, FILE *stream);

Function description: The fwrite function writes the data in the memory pointed to by ptr to the file marked by stream, one block is size bytes, and there are n blocks in total.

Block write : Write the data in the memory to the disk file as it is

Return value : the number of blocks actually written

Quick write example: 

#include <string.h>
typedef struct
{
    int num;
    char name[30];
}STU;
void test()
{
    STU A[3]={
   
   {1,"lucy"},{2,"bob"},{3,"张三",{4,"李四"}};
    int n = sizeof(hero) / sizeof(hero[0]);
    FILE *fp = fopen("S.txt", "w");
    if (fp == NULL)
    {
         perror("fopen");
        return;
     }
    fwrite(A, sizeof(A), n, fp);
    fclose(fp);
}

快读:size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

Quick readthe disk data is input to the memory as it is

Return value: The number of whole blocks actually read : less than one block is not counted but the data is read.

Block read instance 

#include <string.h>
void test02()
{
    STU A[3];
    memset(A, 0, sizeof(A));
    FILE *fp = fopen("S.txt", "r");
    if (fp == NULL)
    {
        perror("fopen");
        return;
    }
    fread(A, sizeof(STU), 3, fp);
    int i = 0;
    for (i = 0; i < 3; i++)
    {
        printf("%d %s\n", A[i].num, A[i].name);
    }
    fclose(fp);
}

 6. Formatting read and write fscanf fprintf

 1. Format and write fprintf (file pointer, format string, output list)

#include <string.h>
typedef struct
{
    int num;
    char name[30];
}STU;
void test()
{
    STU A[3]={
   
   {1,"lucy"},{2,"bob"},{3,"张三",{4,"李四"}};
    int n = sizeof(hero) / sizeof(hero[0]);
    FILE *fp = fopen("S.txt", "w");
    if (fp == NULL)
    {
         perror("fopen");
        return;
     }
    //格式化写
   int i = 0;
    for (i = 0; i < n; i++)
    {
        fprintf(fp, "%s %d \n", A[i].num, A[i].name);
    }

    fclose(fp);
}

2. Formatted read fscanf (file pointer, format string, output list)

#include <string.h>
void test02()
{
    STU A[3];
    memset(A, 0, sizeof(A));
    FILE *fp = fopen("S.txt", "r");
    if (fp == NULL)
    {
        perror("fopen");
        return;
    }
    int i = 0;
    for (i = 0; i < 3; i++)
    {
        fscanf(fp, "%d %s",&A[i].num, A[i].name);
    }
    int i = 0;
    for (i = 0; i < 3; i++)
    {
        printf("%d %s\n", A[i].num, A[i].name);
    }
    fclose(fp);
}

7. Random reading and writing of files

By default, the file is read and written in the order of stream pointers , and the user cannot change the order of reading and writing by moving the stream pointers .

                             Random read and write: users can change the position of the file stream pointer

1. Sequential reading and writing introduces random reading and writing cases

void test()
{
	FILE* fp = NULL;
	fp = fopen("test.txt", "w+");
	if (fp = NULL)
	{
		perror("fopen");
		return;
	}
	fpus("hello world", fp);//此时流指针指向该字符串末尾
	char buf[100] = "";
    //读时从流指针开始往后顺序读,会读不到字符串hello world
	fgets(buf, sizeof(buf), fp);
	printf("读到的数据:%s\n", buf);//无数据显示
	fclose(fp);
}

Sequential reading and writing solves this problem: the stream pointer will be reset after the file is closed and reopened. But the file is opened twice and closed twice.

void test()
{
	FILE* fp = NULL;
	fp = fopen("test.txt", "w+");
	if (fp = NULL)
	{
		perror("fopen");
		return;
	}
	fpus("hello world", fp);//此时流指针指向该字符串末尾
    //流指针复位
    fclose(fp);
    fp=fopen("test.txt","r");
    //读取数据
	char buf[100] = "";
	fgets(buf, sizeof(buf), fp);
	printf("读到的数据:%s\n", buf);
	fclose(fp);
}

2. Random read and write API

(1) rewind resets the file stream pointer

void rewind(FILE *stream);

void test()
{
	FILE* fp = NULL;
	fp = fopen("test.txt", "w+");
	if (fp = NULL)
	{
		perror("fopen");
		return;
	}
	fpus("hello world", fp);//此时流指针指向该字符串末尾
    //复位文件流指针
    rewind(fp);
    //读取数据
	char buf[100] = "";
	fgets(buf, sizeof(buf), fp);
	printf("读到的数据:%s\n", buf);
	fclose(fp);
}

 (2) ftell returns the number of bytes from the file stream pointer to the file header

long ftell(FILE *stream);

void test()
{
	FILE* fp = NULL;
	fp = fopen("test.txt", "w+");
	if (fp = NULL)
	{
		perror("fopen");
		return;
	}
	fpus("hello world", fp);//此时流指针指向该字符串末尾
    //复位文件流指针
    long len=ftell(fp);
	printf("文件的大小:%ld\n", len);
	fclose(fp);
}

(3) fseek file stream pointer positioning

int fseek(FILE *stream, long offset, int whence);

 whence locates the starting position of the stream pointer

                File starts with SEEK_SET 0

                File current position SEEK_ CUR 1

                end of file SEEK_ END 2

offset: the offset of the stream pointer , if it is a positive number, the offset to the right (in bytes) is a negative number, it is an offset to the left

Case: Read file data at one time

The main steps:

(1) Position the file stream pointer to the end

(2) ftell returns the offset of the file stream pointer (total file size len)

(3) According to the total file size, apply for space len+1 from the heap area

(4) Use fread to read the file data at one time 

 Implementation code:

#include <stdlib.h>
#include <string.h>
void test06()
{
    FILE *fp = fopen("c.txt", "r");
    if (fp == NULL)
    {
        perror("fopen");
        return;
    }

     fseek(fp, 0, 2);
     long len = ftell(fp);
    //复位文件流指针
    rewind(fp);
    printf("文件总大小:len=%ld\n", len);

     unsigned char *text = (unsigned char *)calloc(1, len + 1);
     fread(text, len, 1, fp);

     printf("%s\n", text);
     fclose(fp);

     //释放堆区空间(不是必须操作)
     if (text != NULL)
     {
         free(text);
        text = NULL;
     }
 }

8. File Encryptor

main.c

#include <stdio.h>
#include <stdlib.h>
#include "fun.h"

int main(int argc ,char *argv[])
{
	while(1)
	{	
		


		int cmd=0;
		print_help();
		printf("请输入指令:");
		scanf("%d",&cmd);



		if(cmd==1)
		{
			char dest_file[31]="";
			char src_file[31]="";
			unsigned long file_length=0;
			char  *read=NULL;
			unsigned int password=0;
			//从键盘获取源文件和目的文件名字
			get_file_name(dest_file,src_file);
			
			//从文件中读出内容

			read = read_src_file(&file_length,src_file);
			//获取加密password
			printf("请输入密码:");
			scanf("%u",&password);
			//字符数组加密
			read=file_text_encrypt(read,file_length,password);
			
			//保存文件
			save_file(read,file_length,dest_file);
			

		}
		else if (cmd==2)
		{
			char dest_file[31]="";
			char src_file[31]="";
			unsigned long file_length=0;
			char  *read=NULL;
			unsigned int password=0;
			//从键盘获取源文件和目的文件名字
			get_file_name(dest_file,src_file);
			
			//从文件中读出内容

			read = read_src_file(&file_length,src_file);
			//获取加密password
			printf("请输入密码:");
			scanf("%u",&password);
			//字符数组加密
			read=file_text_decrypt(read,file_length,password);
			
			
			//保存文件
			save_file(read,file_length,dest_file);
			
		}
		else if (cmd==3)
		{
			break;
		}
		else
		{
			printf("输入指令出错!!!\n");
		}

	
	}
	
	return 0;
}

 fun.c

#include <stdio.h>
#include <stdlib.h>

void print_help()
{
	printf("********1:加密文件***********\n");
	printf("********2:解密文件***********\n");
	printf("********3:退出程序***********\n");
}


void get_file_name(char * dest_file_name,char * src_file_name)
{
	printf("请输入源文件的名称:");
	scanf("%s",src_file_name);
	printf("请输入目的文件的名称:");
	scanf("%s",dest_file_name);
	return;
}


char *read_src_file(unsigned long  *file_length,char *src_file_name)
{
	char *data=NULL;
	FILE *fp;

	
	fp=fopen(src_file_name,"r");//只读的方式打开文件
	if(fp==NULL)
	{
		perror("fopen");
		return NULL;
	}
	
	//流指针go尾部
	fseek(fp,0,2);
	//流指针的偏移量
	*file_length = ftell(fp);
	//流指针复位
	rewind(fp);

	//申请空间保存文件
	data=(char *)calloc(1,*file_length);
	if(NULL==data)
	{
		perror("calloc");
		return NULL;
	}

	//一次性读
	fread(data,*file_length,1,fp);

	fclose(fp);
	return data;

}


char *file_text_encrypt(char * src_file_text,unsigned long int length,unsigned int password)
{
	char *data=NULL;
	unsigned int i=0;
	for(i=0;i<length;i++)
	{
		src_file_text[i] += password;
	}
	
	return src_file_text;

	
}


void save_file(char* text,unsigned long int length,char * file_name)
{	
	char *data=NULL;
	FILE *fp;
	fp=fopen(file_name,"w");
	if(NULL==fp)
	{
		perror("fp");
		return;
	}
	
	//写
	fwrite(text,length,1,fp);

	fclose(fp);
	if(text !=NULL)
	{
		free(text);
		text =NULL;

	}
	return;
}


char *file_text_decrypt(char * src_file_text,unsigned long int length,unsigned int password)
{
	char *data=NULL;
	unsigned int i=0;
	for(i=0;i<length;i++)
	{
		src_file_text[i] -= password;
	}
	
	return src_file_text;	
}

 fun.h

#ifndef __FUN_H__
#define __FUN_H__

extern void print_help();
extern void get_file_name(char * dest_file_name,char * src_file_name);
extern char *read_src_file(unsigned long  *file_length,char *src_file_name);
extern char *file_text_encrypt(char * src_file_text,unsigned long int length,unsigned int password);
extern void save_file(char* text,unsigned long int length,char * file_name);
extern char *file_text_decrypt(char * src_file_text,unsigned long int length,unsigned int password);

#endif

Guess you like

Origin blog.csdn.net/m0_75045191/article/details/131750810