一 常用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;
}