8.文件操作小应用之实现cp指令
需要实现cp指令要怎么做呢?(可以看看下图)思路入下图:
按照上面的步骤完成代码(demo13.c):
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main(int argc,char **argv)//char **argv是二级指针
{
int fdSrc;
int fdDes;
char *readBuf = NULL;
if (argc != 3){
printf("paramer error\n");
exit(-1);
}
fdSrc = open(argv[1],O_RDWR);
int size = lseek(fdSrc,0,SEEK_END);//这里很巧妙的用lseek光标计算出源文件的大小。
lseek(fdSrc,0,SEEK_SET);//算出源文件大小记得要把光标返回到文件头的位置。
readBuf = (char *)malloc(sizeof(char)*size + 8);//用malooc开辟一个与源文件相近大小的空间,不浪费。
int n_read = read(fdSrc,readBuf,size);//读源文件的内容
fdDes = open(argv[2],O_RDWR|O_CREAT,0600);//打开或者创建一个文件
int n_write = write(fdDes,readBuf,strlen(readBuf));//把读到的内容到目标文件中去。
close(fdSrc);关闭文件,使得对动态文件的操作保存在静态文件中
close(fdDes);
return 0;
}
下图就是运行自己写的cp指令运行成功图:
9.解决上节课中的隐藏bug
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main(int argc,char **argv)
{
int fdSrc;
int fdDes;
char *readBuf = NULL;
if (argc != 3){
printf("paramer error\n");
exit(-1);
}
fdSrc = open(argv[1],O_RDWR);
int size = lseek(fdSrc,0,SEEK_END);
lseek(fdSrc,0,SEEK_SET);
readBuf = (char *)malloc(sizeof(char)*size + 8);
int n_read = read(fdSrc,readBuf,size);
fdDes = open(argv[2],O_RDWR|O_CREAT|O_TRUNC,0600);//上节课存在的小bug是当目标文件文件存在且其大小超过源文件的大小,那么对目标文件的写操作只能覆盖源文件大小的部分,目标文件的多出部分还是会留下,所以用O_TRUNC把目标文件原来的内容全部干掉。
int n_write = write(fdDes,readBuf,strlen(readBuf));
close(fdSrc);
close(fdDes);
return 0;
}
10.文件编程小应用之修改程序的配置文件
就是修改文件的字符:思路如图
(demo14.c代码)
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main(int argc,char **argv)
{
int fdSrc;
char *readBuf = NULL;
if (argc != 2){
printf("paramer error\n");
exit(-1);
}
fdSrc = open(argv[1],O_RDWR);
int size = lseek(fdSrc,0,SEEK_END);
lseek(fdSrc,0,SEEK_SET);
readBuf = (char *)malloc(sizeof(char)*size + 8);
int n_read = read(fdSrc,readBuf,size);
lseek(fdSrc,0,SEEK_SET);//*注意*这里不加光标的话,write函数就是在文件的尾位置写了,所以加lseek函数使得光标返回原来位置,或者在open函数哪里加O_TRUNC常数。
//此处修改字符的字段可以封装成一个函数,供以后工作参考。
char *p = strstr(readBuf,"LENG=");//用字符串函数找出a的位置
if(p==NULL){
printf("not found\n");
exit(-1);
}
p = p+strlen("LENG=");//然后移到b的位置
*p = '5';//修改字符
int n_write = write(fdSrc,readBuf,strlen(readBuf));
close(fdSrc);
return 0;
}
这里需要提醒的是在工作中需要对函数的返回值进行判断,这里就为了代码简洁没有判断read open这些函数的返回值。
下图是函数运行的图:(LENG=3成功改成LENG=5)
11.写一个整数到文件
前面我们都是对文件字符的读写,包括对TEST.config写的也是字符,这里我们硬是要写一个整数。
在demo15.c中把字符‘5’改为整数5如下图:
对TEST.config的修改如图:(不是错,只是和字符串有冲突)
代码(demo16.c):
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int fd;
int data = 100;
int data2 = 0;
fd = open("./file1",O_RDWR);
int n_write = write(fd,&data,sizeof(int));//write函数的第二个参数只要是地址就好了,所以可以取整形数的地址
lseek(fd,0,SEEK_SET);
int n_read = read(fd,&data2,n_write);//read函数的第二个参数只要是地址就好了,所以可以取整形数的地址
printf("read %d,data=%d\n",n_read,data2);
close(fd);
return 0;
}
下面是运行结果file1的截图:这个结果并不是错误的,程序可以正常的读写,这个修改file1是正确的。
这里是把结构体写入配置文件中(demo17.c):
#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 = {100,'a'};
struct Test data2;
fd = open("./file1",O_RDWR);
int n_write = write(fd,&data,sizeof(struct Test));//取结构体地址,然后把其写入。
lseek(fd,0,SEEK_SET);
int n_read = read(fd,&data2,sizeof(struct Test));//取结构体地址,把读到的结构体数据存入到结构体地址中去。
printf("read %d,data=%d,char=%c\n",n_read,data2.a,data2.c);
close(fd);
return 0;
}
下图是运行结果图,配置文件就不看了,都是乱码,程序看的懂,人看不懂!!!
12.写结构体数组到文件
直接上代码(demo18.c)
#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,data1=%d,char1=%c,data2=%d,char2=%c\n",n_read,data2[0].a,data2[0].c,data2[1].a,data2[1].c);
close(fd);
return 0;
}
下图是运行结果:(file1还是看不懂,不截图了)