Linux系统编程:文件编程

一 常用API

打开、创建、关闭文件,读写文件,利用man指令查询相关说明

open & create

man 2 open

man 2 create

NAME
       open, creat - open and possibly create a file or device

SYNOPSIS
       #include <sys/types.h>
       #include <sys/stat.h>
       #include <fcntl.h>

       int open(const char *pathname, int flags);
       int open(const char *pathname, int flags, mode_t mode);

       int creat(const char *pathname, mode_t mode);

close 

man 2 close

NAME
       close - close a file descriptor

SYNOPSIS
       #include <unistd.h>

       int close(int fd);

write

man 2 write

NAME
       write - write to a file descriptor

SYNOPSIS
       #include <unistd.h>

       ssize_t write(int fd, const void *buf, size_t count);

DESCRIPTION
       write()  writes  up  to  count bytes from the buffer pointed buf to the
       file referred to by the file descriptor fd.

man strlen 

NAME
       strlen - calculate the length of a string

SYNOPSIS
       #include <string.h>

       size_t strlen(const char *s);

read

man 2 read

NAME
       read - read from a file descriptor

SYNOPSIS
       #include <unistd.h>

       ssize_t read(int fd, void *buf, size_t count);

DESCRIPTION
       read()  attempts to read up to count bytes from file descriptor fd into
       the buffer starting at buf.

       If count is zero, read() returns zero and has  no  other  results.   If
       count is greater than SSIZE_MAX, the result is unspecified.

man malloc

NAME
       malloc, free, calloc, realloc - Allocate and free dynamic memory

SYNOPSIS
       #include <stdlib.h>

       void *malloc(size_t size);
       void free(void *ptr);
       void *calloc(size_t nmemb, size_t size);
       void *realloc(void *ptr, size_t size);

 综合应用:创建、打开、写、读 最后关闭文件

写一个demo.c 

先打开文件,文件不存在open返回-1,

然后创建这个文件 利用 fd = open("./file1",O_RDWR|O_CREAT,0600);

因为 6 = 4 + 2 ,4和2表示权限可读可写

然后write进去字符串

此时直接read,什么也读不到,因为光标位于字符串尾部,从光标往后读取自然为空

简单粗暴的办法就是关闭文件再打开,光标自动从头部开始

然后就可以读取到写入的内容了,

最后关闭文件。

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>

int main()
{
	int fd;
	char *buf = "Zhong Guo Wan Sui!";

	fd = open("./file1",O_RDWR);

	if(fd>0)
	{
		printf("open file success,fd = %d\n",fd);
	}
	else if(fd == -1)
	{
		printf("open file fail,fd = %d\n",fd);

		fd = open("./file1",O_RDWR|O_CREAT,0600);
		if(fd>0)
		{
			printf("create file success,fd = %d\n",fd);
		}
	}

	int n_write = write(fd,buf,strlen(buf));

	if(n_write != -1)
		printf("write file success,n_write = %d\n",n_write);

	close(fd);
	fd = open("./file1",O_RDWR);

	char *read_buf;
	read_buf = (char *)malloc(sizeof(char) * n_write + 1);

	int n_read = read(fd,read_buf,sizeof(char) * n_write + 1);

	printf("read %d,context:%s\n",n_read,read_buf);
	close(fd);

	return 0;
}

 运行一下

CLC@Embed_Learn:~/part1$ gcc demo.c
CLC@Embed_Learn:~/part1$ ls
a.out  demo.c
CLC@Embed_Learn:~/part1$ ./a.out
open file fail,fd = -1
create file success,fd = 3
write file success,n_write = 18
read 18,context:Zhong Guo Wan Sui!

光标 lseek

上面这个demo处理光标的方法太low,让我们正经处理一下光标

man 2 lseek

NAME
       lseek - reposition read/write file offset

SYNOPSIS
       #include <sys/types.h>
       #include <unistd.h>

       off_t lseek(int fd, off_t offset, int whence);

DESCRIPTION
       The lseek() function repositions the offset of the open file associated
       with the file descriptor fd to the argument  offset  according  to  the
       directive whence as follows:

       SEEK_SET
              The offset is set to offset bytes.

       SEEK_CUR
              The offset is set to its current location plus offset bytes.

       SEEK_END
              The offset is set to the size of the file plus offset bytes.

 修改代码,将关闭重新打开换为直接将光标移动到头部。

//	close(fd);
//	fd = open("./file1",O_RDWR);

	lseek(fd,0,SEEK_SET);

拓展:利用lseek巧算文件大小

	lseek(fd,0,SEEK_SET);
	int fileSize = lseek(fd,0,SEEK_END);
	printf("fileSize = %d\n",fileSize);

二 文件编程应用

1.实现CP操作

测试:参数传入main函数,运行指令拆分为二维数组

#include <stdio.h>


int main(int argc,char **argv)
{
	printf("total params : %d\n",argc);
	printf("No.1 params : %s\n",argv[0]);
	printf("No.2 params : %s\n",argv[1]);
	printf("No.3 params : %s\n",argv[2]);

	return 0;
}
CLC@Embed_Learn:~/part1$ ./a.out One Two
total params : 3
No.1 params : ./a.out
No.2 params : One
No.3 params : Two

实现:CP指令效果

传入两个目标文件,打开目标1,计算文件大小,读目标1文本,打开目标2,将文本写入目标2。

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>

int main(int argc,char **argv)
{
	int fd,fd1;
	fd = open(argv[1],O_RDWR);

	int fileSize = lseek(fd,0,SEEK_END);
	lseek(fd,0,SEEK_SET);
	
	char *read_buf = (char *)malloc(fileSize);
	read(fd,read_buf,fileSize);

	fd1 = open(argv[2],O_RDWR|O_CREAT|O_TRUNC,0600);
	write(fd1,read_buf,fileSize);

	close(fd);
	close(fd1);

	return 0;
}

编译运行

CLC@Embed_Learn:~/part1$ gcc demo_cp.c -o mycp
CLC@Embed_Learn:~/part1$ ls
a.out  demo.c  demo_cp.c  demo_cp.c~  file1  mycp  test.c
CLC@Embed_Learn:~/part1$ ./mycp file1 file2
CLC@Embed_Learn:~/part1$ ls
a.out  demo.c  demo_cp.c  demo_cp.c~  file1  file2  mycp  test.c

2.实现修改程序配置文件功能

将BBB由3改为8。

步骤:读出文本字符串,找到对应参数的位置,修改读出字符串的内容,将内容覆写进文件 

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

int main(int argc,char **argv)
{
	int fd;
	fd = open(argv[1],O_RDWR);

	int fileSize = lseek(fd,0,SEEK_END);
	lseek(fd,0,SEEK_SET);
	
	char *read_buf = (char *)malloc(fileSize);
	read(fd,read_buf,fileSize);

	char *p = strstr(read_buf,argv[2]);
	if(p == NULL)
	{
		printf("%s not found\n",argv[2]);
		exit(-1);
	}

	p += strlen(argv[2]) + 1;
	*p = '8';

	lseek(fd,0,SEEK_SET);
	write(fd,read_buf,fileSize);

	close(fd);

	return 0;
}

运行

CLC@Embed_Learn:~/part1$ gcc  demo_turn.c -o TurnData
CLC@Embed_Learn:~/part1$ ./TurnData DataFile BBB

注意:

不要陷入buf只能是字符串的误区,buf是指针,写整型、数组、结构体等等都可以正常读写,但是vi查看可能是乱码,人类看不懂,但是不影响读写使用。

例如:读写结构体

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>

struct Test
{
	int a;
	char c;

};

int main()
{
	int fd;
	
	struct Test data[2] = {{100,'a'},{101,'b'}};
	struct Test data2[2];

	fd = open("./file1",O_RDWR);

	int n_write = write(fd,&data,sizeof(struct Test)*2);

	lseek(fd,0,SEEK_SET);

	int n_read = read(fd, &data2, sizeof(struct Test)*2);
	
	printf("read %d,%c \n",data2[0].a,data2[0].c);
	printf("read %d,%c \n",data2[1].a,data2[1].c);
	close(fd);

	return 0;
}

三 标准C库

总结open与fopen的区别 - NickyYe - 博客园 (cnblogs.com)

fopen fwrite fclose fread fseek ... ... 

NAME
       fopen, fdopen, freopen - stream open functions

SYNOPSIS
       #include <stdio.h>

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

       FILE *fdopen(int fd, const char *mode);

       FILE *freopen(const char *path, const char *mode, FILE *stream);

   Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

       fdopen(): _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _POSIX_SOURCE
//=========================================================================

NAME
       fread, fwrite - binary stream input/output

SYNOPSIS
       #include <stdio.h>

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

       size_t fwrite(const void *ptr, size_t size, size_t nmemb,
                     FILE *stream);
//=========================================================================
NAME
       fgetpos, fseek, fsetpos, ftell, rewind - reposition a stream

SYNOPSIS
       #include <stdio.h>

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

       long ftell(FILE *stream);

       void rewind(FILE *stream);

       int fgetpos(FILE *stream, fpos_t *pos);
       int fsetpos(FILE *stream, fpos_t *pos);

"r"           文件只读
"w"           创建文字文件只写
"a"           增补, 如果文件不存在则创建一个
"r+"          打开一个文字文件读/写
"w+"          创建一个文字文件读/写
"a+"          打开或创建一个文件增补
"b"           二进制文件(可以和上面每一项合用)
"t"           文这文件(默认项)

例1: 

#include <stdio.h>
int main() {
    FILE *fp;
    int ret;
    /* 打开文件 */
    fp = fopen("123.txt", "r");
    if (fp == NULL)
        puts("打开失败!");
    else
        puts("打开成功!");
    /* 关闭文件 */
    ret = fclose(fp);
    if (ret == 0)
        puts("关闭成功!");
    else
        puts("关闭失败!");
    return 0;
}

例2: 

#include <stdio.h>
#include <string.h>

int main()
{
	//FILE *fopen(const char *path, const char *mode);

	FILE *fp;
	char *str = "Hello World";
	char readBuf[128] = {0};

	fp = fopen("./file1.txt","w+");

	//size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);
	//ptr  buf
	//size  sizeof char   
	// geshu 
	// which file
	int nwrite = fwrite(str,sizeof(char),strlen(str),fp);
//	fwrite(str,sizeof(char)*strlen(str),1,fp);
	fseek(fp,0,SEEK_SET);
//	size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
	int nread = fread(readBuf,sizeof(char),strlen(str),fp);
	
	printf("read data: %s\n",readBuf);
    printf("read=%d,write = %d\n",nread,nwrite);

    fclose(fp);

	return 0;
}

fputc fgetc feof ... ...li

NAME
       fputc,  fputs,  putc,  putchar,  puts  -  output  of characters and
       strings

SYNOPSIS
       #include <stdio.h>

       int fputc(int c, FILE *stream);

       int fputs(const char *s, FILE *stream);

       int putc(int c, FILE *stream);

       int putchar(int c);

       int puts(const char *s);
//=========================================================================
NAME
       clearerr, feof, ferror, fileno - check and reset stream status

SYNOPSIS
       #include <stdio.h>

       void clearerr(FILE *stream);

       int feof(FILE *stream);

       int ferror(FILE *stream);

       int fileno(FILE *stream);

   Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

       fileno(): _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _POSIX_SOURCE

例1:

#include <stdio.h>
#include <string.h>

int main()
{
	FILE *fp;
	int i;
	char *str = "chenlichen hen shuai o!";
	int len = strlen(str);

	fp = fopen("./test.txt","w+");
	for(i=0;i<len;i++){

		fputc(*str,fp);
		str++;
	}
	fclose(fp);
	return 0;
}

例2:

#include <stdio.h>
#include <string.h>

int main()
{
	FILE *fp;
	int i;
	char c;

	fp = fopen("./test.txt","r");

	while(!feof(fp)){// nonezero if reach end of file
		
		c = fgetc(fp);
		printf("%c",c);
	}
	fclose(fp);
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值