目录
前言
一. man手册
1.1 man手册如何查询
1.2 man手册基础
二.系统IO函数接口
三.open打开文件夹
3.1 例1 open打开文件
3.2 open打开文件代码
3.3 例2 创建文件
四.write写文件
4.1 write写文件
五. read读文件
5.1 read读文件与偏移
5.2 偏移细节
5.3 read读文件代码
六.复制文件
6.1 方法1:cp 命令
6.2 方法2:使用缓冲区拷贝
6.3 方法3:主函数传参
前言
学习使用man手册,系统IO接口:open write read接口
系统I/O接口是一组用于处理输入和输出操作的函数和工具。这些接口提供了与操作系统交互的机制,允许程序读写文件、网络通信、控制设备等。系统I/O接口在C语言程序中扮演着至关重要的角色,以下是它们的一些主要作用:
一. man手册
1.1 man手册如何查询
我们输入man -f open 命令
man -f open
输入man man
可以查看man中的9本手册
1.2 man手册基础
当前第二本手册
函数的功能介绍(使用说明)
返回值介绍
错误号码
二.系统IO函数接口
在C语言中,系统I/O接口是一组用于处理输入和输出操作的函数和工具。这些接口提供了与操作系统交互的机制,允许程序读写文件、网络通信、控制设备等。系统I/O接口在C语言程序中扮演着至关重要的角色,以下是它们的一些主要作用:
文件操作: 系统I/O接口提供了一系列的函数,如
open
、read
、write
、close
等,用于打开、读取、写入和关闭文件。这些函数是进行文件处理的基础,允许程序访问磁盘上的文件资源。数据传输: 通过系统I/O接口,程序可以读写数据流。这包括从标准输入(如键盘)读取数据,以及向标准输出(如终端或文件)写入数据。这些操作对于用户交互和程序输出是必不可少的。
缓冲管理: 系统I/O接口通常使用缓冲区来优化读写操作的性能。例如,
stdio
库中的fread
和fwrite
函数会在内部使用缓冲区来减少对底层read
和write
系统调用的频繁使用。这有助于提高I/O操作的效率。错误处理: 系统I/O接口提供了错误检测和报告机制。当I/O操作失败时,这些接口会设置全局变量
errno
,并返回特定的错误代码。这使得程序员能够诊断和处理I/O操作中出现的问题。设备控制: 系统I/O接口允许程序与各种设备进行交互,如打印机、磁盘驱动器、网络接口等。通过这些接口,程序可以执行设备特定的操作,如打开设备、发送命令、读取状态等。
网络通信: 系统I/O接口提供了网络编程的基础设施,包括套接字(sockets)操作、网络协议处理、数据包发送和接收等。这些接口使得程序能够在网络上进行通信和数据交换。
多线程和异步I/O: 在多线程或异步I/O环境中,系统I/O接口可以支持并发操作,允许多个线程同时进行I/O操作,提高了程序的响应性和性能。
跨平台兼容性: C语言标准库中的I/O接口设计为跨平台兼容,这意味着在不同的操作系统和硬件平台上,程序可以使用相同的I/O函数进行开发。这大大简化了程序的移植和维护工作。
总之,系统I/O接口是C语言程序与外部世界交互的桥梁,它们为程序提供了丰富的输入输出功能,使得程序能够执行文件处理、网络通信、设备控制等多样化的任务。通过有效地使用这些接口,程序员可以构建出功能强大、性能优越的应用程序。
三.open打开文件夹
3.1 例1 open打开文件
头文件
#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);
参数分析
需要注意:
3.2 open打开文件代码
代码
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <string.h> int main(int argc, char const *argv[]) { // 打开文件 int file_fd = open("abc.c", O_RDONLY ); if( -1 == file_fd ) { fprintf( stderr , "open abc.c error , msg:%s\n", strerror(errno)); return -1 ; } else { printf("open abc.c succeed , file descriptor : %d \n " , file_fd); } return 0; }
如果没有创建文件,则会显示文件或路径不存在
接着我们创建文件abc.c再进行测试,现在就可以找到文件了
3.3 例2 创建文件
如果文件不存在如何在程序中自行创建
可以先查看umask
当前测试文件夹中的内容为open_1.c
open_1.c代码
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <string.h> int main(int argc, char const *argv[]) { // 打开文件 int file_fd = open("abc.c", O_RDONLY | O_CREAT | O_TRUNC , 0666 ); if( -1 == file_fd ) { fprintf( stderr , "open abc.c error , msg:%s\n", strerror(errno)); return -1 ; } else { printf("open abc.c succeed , file descriptor : %d \n " , file_fd); } return 0; }
运行结果:可以看出编译a.out后,我们创建了一个名为abc.c的文件
四.write写文件
4.1 write写文件
在文件中写入
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <unistd.h> int main(int argc, char const *argv[]) { // 打开文件 int file_fd = open("abc.c", O_RDWR | O_CREAT | O_TRUNC , 0666 ); if( -1 == file_fd ) { fprintf( stderr , "open abc.c error , msg:%s\n", strerror(errno)); return -1 ; } else { printf("open abc.c succeed , file descriptor : %d \n " , file_fd); } // 写入内容 ssize_t ret_val = write ( file_fd , "Hello GZ2123", sizeof("Hello GZ2123")); if( -1 == ret_val ) { fprintf( stderr , "write abc.c error , msg:%s\n", strerror(errno)); return -1 ; } else{ printf(" write succeed : %ld byet \n" , ret_val); } while(1) { } return 0; }
五. read读文件
5.1 read读文件与偏移
在读取文件中,我们需要注意偏移量的细节
读取文件
移动文件的读写位置(设置偏移量)
5.2 偏移细节
读取文件时,需要注意当前文件的操作:
若打开进行写入操作后没有关闭,那么我们进行读操作时,偏移量会到数据末尾,如这里的null,若在这里进行读取数据,则读不出来:
解决方法:1.把文件关闭再打开,再次被打开时文件的偏移量为开头部分,这是就可以正常读取数据了
close(file_fd); open("abc.c", O_RDWR, 0666 );
解决方法2:设置偏移量:通过直接设置偏移量,即可重现定位到文件的头部分
//把读写位置偏移到开头 ret_val = lseek(file_fd , 0 , SEEK_SET ); printf("偏移后:%ld\n" , ret_val);
5.3 read读文件代码
代码
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <unistd.h> int main(int argc, char const *argv[]) { // 打开文件 int file_fd = open("abc.c", O_RDWR | O_CREAT | O_TRUNC , 0666 ); if( -1 == file_fd ) { fprintf( stderr , "open abc.c error , msg:%s\n", strerror(errno)); return -1 ; } else { printf("open abc.c succeed , file descriptor : %d \n " , file_fd); } // 写入内容 char str1[] = "hello word hello FFFF ello111222"; //ssize_t ret_val = write ( file_fd , "Hello GZ2123", sizeof("Hello GZ2123")); ssize_t ret_val = write ( file_fd , str1, sizeof(str1)); if( -1 == ret_val ) { fprintf( stderr , "write abc.c error , msg:%s\n", strerror(errno)); return -1 ; } else{ printf(" write succeed : %ld byet \n" , ret_val); } //这里不使用偏移函数,使用关闭再打开文件也同样可以进行读取操作 //重新打开文件,读写的偏移位自动为开头 // close(file_fd); // open("abc.c", O_RDWR, 0666 ); //把读写位置偏移到开头 ret_val = lseek(file_fd , 0 , SEEK_SET ); printf("偏移后:%ld\n" , ret_val); //读取文件的内容 char msg [128] ; // 设置一个用户缓冲区 bzero(msg, sizeof(msg) ); // 清空内存区 ret_val = read( file_fd , msg , sizeof(msg) ); if(-1 == ret_val ) { perror("读取文件失败"); return -1 ; } else{ printf("成功%ld字节 , 内容为:%s\n" , ret_val , msg ); } close(file_fd); return 0; }
结果
六.复制文件
6.1 方法1:cp 命令
可以直接使用cp进行复制
cp open_1.c a.txt1
6.2 方法2:使用缓冲区拷贝
这里使用缓冲区进行循环拷贝
代码为:
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <stdlib.h> #define SRC_PATH "./open_1.c" #define TAG_PATH "a.txt" #define SIZE_MEM 128 int main(int argc, char const *argv[]) { //打开两个文件 int tag_fd = open( TAG_PATH , O_WRONLY | O_CREAT | O_TRUNC , 0666 ); // 以只写的权限申请打开文件 if(-1 == tag_fd ) { perror("拷贝的新文件a.txt出现问题\n"); return -1 ; } int src_fd = open( SRC_PATH , O_RDONLY ); // 以只写的权限申请打开文件 if(-1 == src_fd ) { perror("原文件open_1.c打不开\n"); return -1 ; } // 创建一个用户缓冲区 char * msg = calloc(1, SIZE_MEM); if( NULL == msg ) { perror("缓冲区容量异常"); close(src_fd); close(tag_fd); return -1 ; } ssize_t ret_val = -1 ; do { // 读取文件c.txt 存入用户缓冲区中 ret_val = read( src_fd , msg , SIZE_MEM ); if( ret_val < 0 ) { perror("读取文件异常"); break ; } printf("读取到的字节:%ld\n" , ret_val); // 写入到文件中 ret_val = write(tag_fd , msg , ret_val ); printf("写入的字节:%ld\n" , ret_val); }while ( ret_val >= SIZE_MEM ); // 关闭文件 close(src_fd); close(tag_fd); return 0; }
这里生成的a.txt为拷贝后的文件
6.3 方法3:主函数传参
使用主函数
可以看出我们把read.c复制一份为Even.c
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <stdlib.h> #define SRC_PATH "./open.c" #define TAG_PATH "a.txt" #define SIZE_MEM 128 // ./a.out 1.c 2.c int main(int argc, char const *argv[]) { if( argc != 3 ) { printf("请输入正确的参数!!!\n"); return -1 ; } //打开两个文件 int tag_fd = open( argv[2] , O_WRONLY | O_CREAT | O_TRUNC , 0666 ); // 以只写的权限申请打开文件 if(-1 == tag_fd ) { perror("作业本找不到"); return -1 ; } int src_fd = open( argv[1] , O_RDONLY ); // 以只写的权限申请打开文件 if(-1 == src_fd ) { perror("借不到作业本"); return -1 ; } // 创建一个用户缓冲区 char * msg = calloc(1, SIZE_MEM); if( NULL == msg ) { perror("脑容量异常"); close(src_fd); close(tag_fd); return -1 ; } ssize_t ret_val = -1 ; do { // 读取文件c.txt 存入用户缓冲区中 ret_val = read( src_fd , msg , SIZE_MEM ); if( ret_val < 0 ) { perror("读取文件异常"); break ; } printf("读取到的字节:%ld\n" , ret_val); // 写入到文件中 ret_val = write(tag_fd , msg , ret_val ); printf("写入的字节:%ld\n" , ret_val); }while ( ret_val >= SIZE_MEM ); // 关闭文件 close(src_fd); close(tag_fd); return 0; }