本文主要内容:
Linux系统应用编程(一)文件编程
一、Linux文件I/O
1.打开文件
▲ 函数原型:int open(const char *pathname,int flagsmode_mode)
- Linux文件权限:三位十进制分别表示用户、组用户、其他用户对该文件的权限。
2.写文件
▲ 函数原型:ssize_t write(int fd, const void *buf, size_t count);
3.读文件
▲ 函数原型:ssize_t read(int fd, void *buf, size_t count);
4.操作文件指针
▲ 函数原型:off_t lseek(int fd, off_t offset, int whence);
【4-1】应用:lseek( )计算文件大小
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc,char **argv){
if(argc != 2){
printf("error.Usage:count fileName\n");
exit(-1);
}
int fd;
fd = open(argv[1],O_RDONLY);
// lseek(fd,0,SEEK_SET); //默认打开文件时的文件指针在头
int fileSize = lseek(fd,0,SEEK_END); //lssek让指针偏移到文件尾,偏移了多少就是文件的大小
printf("%s size:%d\n",argv[1],fileSize);
close(fd);
return 0;
}
5.实现cp命令
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc,char **argv){
if(argc != 3){
printf("copy:error.Usage:copy srcFile destFile\n");
exit(-1);
}
int srcFd = open(argv[1],O_RDONLY);
if(srcFd == -1){
perror("open");
exit(-1);
}
int destFd = open(argv[2],O_RDWR | O_CREAT,0600);
if(destFd == -1){
perror("open");
exit(-1);
}
/* 计算源文件的大小 */
off_t size = lseek(srcFd,0,SEEK_END);
lseek(srcFd,0,SEEK_SET); //让文件指针回到原位置
char *readBuffer = (char *)malloc(size); //文件多大就申请多大的空间
ssize_t cnt = read(srcFd,readBuffer,size);
write(destFd,readBuffer,cnt);
close(srcFd);
close(destFd);
return 0;
}
二、标准I/O
1.文件IO和标准IO的区别?
- 文件IO:直接调用内核提供的系统调用函数,一般特定于Linux/Unix平台。其操作文件机制不经过内核的缓存(无缓存),数据直接在磁盘和应用程序地址空间进行传输。
- 标准IO:间接调用内核提供的系统调用函数(先调用C库,再到内核的系统调用),不限于平台,且实现的跨平台的缓存(包括行缓存、全缓存、无缓存几种类型),所有其执行效率会优于文件IO。
2.打开文件
▲ 函数原型:FILE *fopen(const char *pathname, const char *mode, FILE *stream);
3.读文件
▲ 函数原型:size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
4.写文件
▲ 函数原型:size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);
▲ 参数解释:
- pstr:存放本次读取/写入的存储空间
- size:读取/写入一个数据元素的大小
- nmemb:本次读取/写入的数据大小
- stream:读取/写入的文件流
▲ 返回值:
- 读取/写入成功:返回nmemb,即读取/写入成功的元素个数
- 读取/写入失败:返回0
文档中所述,对于返回值为0的情况,不区分是读取/写入失败了还是文件结束了
5.移动文件指针
▲ 函数原型:int fseek(FILE *stream, long offset, int whence);
-
fseek( )和lseek( )不同,fseek( )返回值:如果成功,则该函数返回零,否则返回非零值。
在计算文件大小时,需要配合ftell( )使用实现。
6.实现cp命令
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc,char **argv){
if(argc != 3){
printf("Error.Usage:%s srcFile desFile\n",argv[0]);
return -1;
}
/* 打开源文件和目标文件 */
FILE *fpSrc = fopen(argv[1],"r"); //返回文件流指针
FILE *fpDes = fopen(argv[2],"w+");
if(fpSrc == NULL || fpDes == NULL){
perror("fopen");
exit(-1);
}
/* 计算源文件大小 */
fseek(fpSrc,0,SEEK_END);
long int srcSize = ftell(fpSrc);
printf("fileSize:%ld\n",srcSize);
fseek(fpSrc,0,SEEK_SET);
char *buffer = (char *)malloc(srcSize);
int readSize = 0;
while( (readSize = fread(buffer,4,1024*4,fpSrc)) != 0){
printf("readSize:%d\n",readSize);
fwrite(buffer,4,readSize,fpDes);
}
printf("copy done\n");
return 0;
}
7.其他函数fgetc()、fpurc( )、feof( )
三、目录IO
1.函数原型
- DIR *opendir(const char *name);
- DIR *fdopendir(int fd);
- int mkdir(const char *pathname, mode_t mode);
- struct dirent *readdir(DIR *dirp);
2.应用:打印输出指定目录下的所有文件名个inode号
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <stdlib.h>
int main(int argc,char **argv){
DIR *dp = NULL;
char isCreate = 'n';
struct dirent *p = NULL;
if(argc != 2){
printf("error.Usage:%s [dirName]\n",argv[0]);
exit(-1);
}
reopen:
dp = opendir(argv[1]); //打开目标目录
if(dp == NULL){
//打开失败,如果是目录不存在,询问是否创建该目录
printf("No such direcory\nDo you want to create %s?[y/n] ",argv[1]);
scanf("%c",&isCreate);
if(isCreate == 'y'){
mkdir(argv[1],0666); //创建目录
goto reopen;
}else{
printf("done\n");
exit(-2);
}
}
/* 读出目录下所有文件的inode号和name(排除.和..) */
while((p = readdir(dp)) != NULL){
if( strcmp(p->d_name,".") && strcmp(p->d_name,"..")){
printf("Inode:%ld\t name:%s\n",p->d_ino,p->d_name);
}
}
closedir(dp);
return 0;
}