(实验2)文件IO实验
原创
©著作权归作者所有:来自51CTO博客作者喜欢打篮球的普通人的原创作品,请联系作者获取转载授权,否则将追究法律责任
文章目录
- 1.仿写cp命令的部分功能(编写mycp程序)
- 2.命令行参数
- 3.打开文件(POSIX API)
- 3.读取文件(POSIX API)
- 4.写文件(POSIX API)
- 5.关闭文件(POSIX API)
- 6.文件定位(POSIX API)
- 7.错误处理
- 8.仿写cp命令的部分功能的进阶要求
1.仿写cp命令的部分功能(编写mycp程序)
(1)将源文件复制到另外一个文件(将test1.text复制成test2.txt)
[test@linux test]$ ./mycp /home/test1.txt /usr/test2.txt
(2)将源文件复制到另外一个目录(将test1.txt复制到/tmp目录)
[test@linux test]$ ./mycp /home/test1.txt /tmp
源文件路径和目标文件路径通过命令行参数来指定
2.命令行参数
- 命令行参数:在命令(也是可执行文件名) 后,传递进入程序的
参数(字符串形式)
cp命令:根据接收的命令行参数进行复制
✓ cp /usr/local/src/main.c /root/main.c(文件到文件复制)
✓ cp /usr/local/src/main.c /root (文件到目录复制)
✓ cp –r /usr/local/src /root(-r 递归复制,用于目录到目录的复制)
权限不够的情况,采用sudo cp XX XX的方式。
sudo,在linux中输入sodu就是调用这个程序提升权限
操作系统启动C程序->调用C启动例程->例程获取命令行参数->main函数接收
int main(int argc, char* argv[])
argc:整型,输入参数个数
argv:字符串数组,存储命令行参数
root@ubuntu:/root# ./pg I am NEW
argv[1]:I
argv[2]:am
argv[3]:NEW
#include <stdio.h>
int main(int argc ,char* argv[])
{
int i;
for (i=0;i<argc;i++)
{
printf("Argv %d is %s.\n", i, argv[i]);
}
return 0;
}
将左边代码编译为hello.o
命令行中执行两种命令:
./hello.o
./hello.o aaa bbb ccc ddd eee
argv[0]->可执行文件名;
argv[1]-argv[5] ->命令行参数
以字符串的形式传递(空格作为命令行参数之间的分隔)
3.打开文件(POSIX API)
头文件: fcntl.h
函数: int open( const char *pathname, int oflag, …);
作用: 打开或者创建一个文件,返回值是打开文件的文件描述符
pathname:文件的路径
oflag:打开文件的方式
…:变参创建新文件时使用
Oflag值 含义
O_RDONLY 只读打开
O_WRONLY 只写打开
O_RDWR 读、写打开
Oflag值 含义
O_APPEND 每次写都加到文件尾
O_CREAT 若此文件不存在则创建它,此时需要第三个参数mode,
该参数约定了所创建文件的权限,计算方法mode&~umask
O_EXCL 如同时指定了O_CREAT,此指令会检查文件是否存在,
若不存在则建立此文件;若文件存在,此时将出错
O_TRUNC 如果此文件存在,并以读写或只写打开,则文件长度0
3.读取文件(POSIX API)
头文件: unistd.h
函数: ssize_t read( int filedes, void *buf, size_t nbytes);
作用:从打开的文件中读数据
返回值:
✓ 成功: 返回实际读取的字节数(例外情况:读普通文件,未到要求的字节数前
就到达文件末尾,此时返回字节数不等于要求字节数)
✓ 出错: 返回-1, 原因: 磁盘满、权限问题、超文件长度限制
注: 读操作完成后,文件的当前位置变为之前位置+实际读取字节数
4.写文件(POSIX API)
头文件: unistd.h
函数: ssize_t write( int filedes, const void *buf, size_t nbytes);
作用: 向打开的文件中写数据
返回值:
✓ 成功: 写入成功返回实际写入字节数
✓ 出错: 返回-1, 原因: 磁盘满、权限问题、超文件长度限制
注: 写操作完成后,文件的当前位置变为之前位置+实际写入字节数
5.关闭文件(POSIX API)
头文件: unistd.h
函数: int close(int filedes)
作用: 关闭打开的文件
返回值:
✓ 成功: 返回0
✓ 出错: 返回-1
注: 关闭后,不能通过该文件描述符操作该文件
6.文件定位(POSIX API)
头文件: unistd.h
函数: off_t lseek( int filedes, off_t offset, int whence);
作用:设置或查询文件当前位置
✓每个打开文件都有一个“文件当前位置”
✓打开文件时默认当前位置为文件头(0)
✓打开时如指定O_APPEND选项,则当前位置变为文件尾(文件长度)
✓回忆:读写操作完成后文件的当前位置变为之前位置+实际读写字节数
文件定位lseek函数的参数whence及offset(offset可正可负)
✓ whence=SEEK_SET, 文件当前位置=文件头+offset(字节)
✓ whence=SEEK_CUR, 文件当前位置=文件当前位置+offset(字节)
✓ whence=SEEK_END, 文件当前位置=文件尾+offset(字节)
7.错误处理
调用POSIX API会发生错误,需要定位产生问题的更具体原因
系统错误码: POSIX规范定义的记录系统错误的标准码,
使用方式: 通过全局变量errorno获取该错误码,记录最后一次错误
✓ extern errorno
✓ 头文件: errorno.h
(1)将错误码转换为易读的错误信息:
函数1: char *strerror(int errnum);
头文件: string.h
作用: 将errnum转换为对应错误信息(字符串)
(2)函数2: void perror(const char * msg);
头文件: stdio.h
作用: 先输出msg字符串,然后输出当前errorno对应错误信息
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include <errno.h>//引入头文件
extern errno;//引入变量
int main(int argc,char *argv[])
{
int i=open("/usr/src/s.t", 0);
perror([argv[0]]);
printf(strerror(error));
printf("\n");
return 0;
}
编译为error.o
使用./error.o运行
得到如下结果:
8.仿写cp命令的部分功能的进阶要求
- 实现基本功能基础上,针对特殊情况及边界条件,进行流程完善与优化:
✓目标文件存在时,提示“是否覆盖” or“是否合并”等提示信息,并实现覆盖或者目标文件与源文件合并的功能(目标文件尾部追加写入)
✓源文件不存在时给出错误提示信息
✓源文件是目录时给出错误提示信息
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include <errno.h>//引入头文件
extern errorno;//引入变量
int main(int argc, char *argv[])
{
int fd_src,fd_dst;
char *buf;
int fd_src_length;
int n,m;
if (-1==(fd_src=open(argv[1],O_RONLY)))
perror(argv[1]);
if (-1==(fd_dst=open(argv[2],O_WRONLY|O_CREAT|O_TRUNC, 0666)))
perror(argv[2]);
if (-1==(fd_src_length=lseek(fd_src,0, SEEK_END)))
exit(-1);
buf=(buf *)malloc(long (fd_src_length+1));
if (buf==NULL)
printf("malloc error");
memset(buf,'0',fd_src_length+1);
if ((n=read(fd_src, buf, fd_src_length))>0)
{
printf("buf:%d", strlen(buf));
if (n!=(m=write(fd_dst, buf, n)))
printf("write error");
exit(-1);
}
close(fd_src);
close(fd_dst);
free(buf);
return 0;
}