Linux+C学习笔记之IO编程

1. linux中的文件类型
a.任何设备在Linux中都是文件
  b.普通文件(regular file) [-]
纯文本文件(ASCII)
二进制文件(binary)
数据格式的文件(data) /var/log/wtmp (cat last)
c.目录文件(directory) [d]
d.连接文件(link) 快捷方式 [l]
e.设备与设备文件(device) /dev
块设备文件(block) [b]
字符设备文件(character) [c]
套接字(sockets) /var/run [s]

f.管道(pipe,FIFO),先进先出,[p]


2.文件描述符
在linux系统中,所有打开的文件都对应一个文件描述符。文件描述符的本质是一个非负整数。当打开一个文件时,该整数由系统来分配。文件描述符的范围是0~OPEN_MAX。早期的UNIX版本OPEN_MAX=19,即允许每个进程同时打开20个文件,现在很多系统则将其增加到1024。
三个系统自定义的文件描述符:
#define STDIN_FILENO 0  //标准输入设备
#define STDOUT_FILENO 1 //标准输出设备
#define STDERR_FILENO 2 //标准错误输出设备

3.linux中文件编程可以使用两种方法:
linux系统调用
C语言库函数

4.linux系统调用函数
①int creat(const char *filename,mode_t mode)
filename:要创建的文件名(包含路径,缺省为当前路径)
mode:创建模式
常见创建模式:
S_IRUSR 可读
S_IWUSR 可写
S_IXUSR 可执行
S_IRWXU 可读、写、执行
注意:模式也可以用數字來表示,如:4(100)可以表示可读。
为什么将模式设为0777的话,结果文件权限是755?此时要知道umask(用户掩码)的知识,每个文件的最大权限只能是755(用0777和0022异或)。

②int open(const char *pathname, int flags)
 int open(const char *pathname, int flags, mode_t mode)
  pathname:要打开的文件名(包含路径,缺省为当前路径)
flags:打开标志
常见的打开标志:
O_RDONLY 只读方式打开
O_WRONLY 只写方式打开
O_RDWR 读写方式打开
O_APPEND 追加方式打开
O_CREAT 创建一个文件
O_NOBLOCK 非阻塞方式打开
注意:如果打开标志用到了O_CREAT,就要使用第二个函数打开文件,因为文件之前没有创建且没有权限。

③int close(int fd)
关闭指定的文件。

④ssize_t read(int fd, void *buf, size_t length)
功能: 从文件描述符fd所指定的文件中读取 length个字节到buf所指向的缓冲区中, 返回值为实际读取的字节数。
返回值:
成功:读到的字节数
已到达文件末尾:0
出错:-1

⑤ssize_t write(int fd, void *buf, size_t length)
功能: 把length个字节从buf指向的缓冲区中写到文件描述符fd所指向的文件中,返回值为实际写入的字节数。

⑥off_t lseek(int fd, off_t offset, int whence)
功能: 将文件读写指针相对whence移动offset 个字节。操作成功时,返回文件指针相对于文件头的位置。
返回值:
成功:文件的当前偏移
已出错:-1
whence可使用下述值之一:
SEEK_SET:相对文件开头
SEEK_CUR:相对文件读写指针的当前位置
SEEK_END:相对文件末尾
offset可取负值,表示向前移动。例如下述调用可将文件指针相对当前位置向前移动5个字节:
lseek(fd, -5, SEEK_CUR);
如何利用lseek来计算文件长度?
lseek(fd,0,SEEK_END);

⑦有时我们需要判断文件是否可以进行某种操作(读,写等),这时可以使用access函数:
 int access(const char*pathname,int mode) 
pathname:文件名称 
mode:要判断的访问权限。
可以取以下值或者是他们的组合。
R_OK:文件可读,
W_OK:文件可写,
X_OK:文件可执行,
F_OK:文件存在。
返回值:测试成功时,函数返回0,否则返回-1。

⑧fcntl函数解决文件共享问题,select函数用来处理IO复用的情况。
函数原型
 int select(int numfds, fd_set *readfds, fd_set *writefds, fd_set *exeptfds, struct timeval *timeout)
numfds:需要检查的号码最高的文件描述符加 
readfds:由 select()监视的读文件描述符集合
writefds:由 select()监视的写文件描述符集合
exeptfds:由 select()监视的异常处理文件描述符集合
timeout:
NULL:永远等待,直到捕捉到信号或文件描述符已准备好为止
具体值:struct timeval 类型的指针,若等待为 timeout 时间还没有文件描符准备好,就立即返回
0:从不等待,测试所有指定的描述符并立即返回
struct timeval {
long tv_sec; /* second */
long tv_unsec; /* and microseconds*/
}该结构在头文件中已有定义

⑨DIR *opendir(const char *name);
功能:打开目录

⑩ struct dirent *readdir(DIR *dir);
功能:读取目录

11.获取文件属性
通过stat/fstat/lstat等函数获取文件相关属性。
 int stat(const char *filename,struct stat *buf);/*通过文件名获取属性*/
 int fstat(int fd,struct stat *buf);/*通过文件描述符获取属性*/
 int lstat(const char *filename,struct stat *buf);/*类似stat,支持符号链接*/
返回值:
成功:0
失败:-1,并设置errno
12.在编写程序的时候,有时候需要得到当前路径。系统调用提供了getcwd函数来解决这个问题。
 char *getcwd(char *buffer,size_t size)
我们提供一个size大小的buffer,getcwd 会把当前的路径名copy 到buffer中.如果 buffer太小,函数会返回-1。 

13.int mkdir(char * dir, int mode) 
功能:创建一个新目录。 
返回值:0表示成功,-1表示出错。

14.时间类型 (#include <time.h>)
Coordinated Universal Time(UTC):世界标准时间,也就是大家所熟知的格林威治标准时间(Greenwich Mean Time,GMT)。
Calendar Time:日历时间,是用“从一个标准时间点(如:1970年1月1日0点)到此时经过的秒数”来表示的时间。

获取日历时间:
 time_t time(time_t *tloc) 
功能:获取日历时间,即从1970年1月1日0 点到现在所经历的秒数。
/* typedef long time_t */

获取格林威治时间:
 struct tm *gmtime(const time_t *timep)
功能:将日历时间转化为格林威治标准时间,并保存至TM结构。

获取本地时间:
 struct tm *localtime(const time_t *timep) 
功能:将日历时间转化为本地时间,并保存至TM结构。

时间结构体:
struct tm {
int tm_sec; //秒值
int tm_min; //分钟值
int tm_hour; //小时值
int tm_mday; //本月第几日
int tm_mon; //本年第几月
int tm_year; //tm_year + 1900 = 哪一年
int tm_wday; //本周第几日 
int tm_yday; //本年第几日 
int tm_isdst; //日光节约时间
};

时间的格式化输出:
 char *asctime(const struct tm *tm)
功能:将tm格式的时间转化为字符串,如:
Sat Jul 30 08:43:03 2010

 char *ctime(const time_t *timep)
功能:将日历时间转化为本地时间的字符串形式。
 
size_t strftime(char *s, size_t max, const char *format,const struct tm *tm);
功能:将tm格式的时间转化为指定格式的字符串


15.struct passwd *getpwuid(uid_t uid)
功能:获取用户ID等信息。

16.struct group *getgrgid(gid_t gid)
功能:获取同组用户ID等信息。

5.库函数(标准I/O)
①FILE *fopen(const char *filename, const char *mode)
filename:打开的文件名(包含路径,缺省为当前路径)
mode:打开模式
常见打开模式:
r, rb 只读方式打开(‘b’是针对二进制文件的,linux中可以不加)
w, wb 只写方式打开,如果文件不存在,则创建该文件 v a, ab追加方式打开,如果文件不存 在,则创建该文件 v r+, r+b, rb+读写方式打开
w+, w+b, wh+读写方式打开,如果文件不存在,则创建该文件
a+, a+b, ab+读和追加方式打开。如果文件不存在,则创建该文件


②size_t fread(void *ptr,size_t size, size_t n, FILE *stream)
功能: 从stream指向的文件中读取n个记录,每个记录的大小为size个字节,并将读取的数据放入ptr所指向的缓冲区,返回实际读取的记录数目。 

③size_t fwrite(const void *ptr, size_t size, size_t n,FILE *stream)
功能: 从缓冲区ptr所指的数组中把n个记录写到stream指向的文件中,每个记录大小为size个字节,返回实际写入的记录数目。


④int fscanf(FILE *stream, char *format[,argument...])
功能:从一个流中进行格式化输入

⑤int fprintf(FILE *stream, char* format[,arg,...])
功能:格式化输出到一个流中

⑥int fseek(FILE *stream, long offset, int whence)
功能:定位
whence :
SEEK_SET 从文件的开始处开始搜索
SEEK_CUR 从当前位置开始搜索
SEEK_END 从文件的结束处开始搜索 

6.六种COPY方式

①read/write
	#include<stdio.h>
	#include<sys/types.h>
	#include<sys/stat.h>
	#include<fcntl.h>
	#include<unistd.h>
	int main(){
		int fd1=open("c.txt",O_RDONLY);//以只读的方式打开c.txt
		//判断是否打开成功
		if(fd1!=-1){
			printf("open file success~\n");
		}else{
			perror("open file failure~");
		}
		int fd2=open("b.txt",O_WRONLY);//以只写的方式打开b.txt
		if(fd2!=-1){
				printf("open file success~\n");
			}else{
				perror("open file failure~");
			}
		int buf[10]={'\0'};//一次读多少内容
		int read_bytes=0;//表示每次读到的字节数
		//循环读写
		while(1){
			read_bytes=read(fd1,buf,sizeof(buf));
			if(read_bytes<=0)break;
			write(fd2,buf,read_bytes);
		}
		close(fd1);
		close(fd2);
		return 0;
	}
②fread/fwrite
	#include<stdio.h>
	#include<string.h>

	int main() {
		FILE* fp1 = fopen("copy2.c", "r");
		FILE* fp2 = fopen("d.txt", "w+");
		if (fp1 == NULL || fp2 == NULL) {
			perror("fopen failure");
			return -1;
		}
		char buf[8] = { '\0' };
		int bytes = 0;
		while (1) {
		bytes = fread(buf, sizeof(char), sizeof(buf), fp1);
		if (bytes <= 0)
			break;
			fwrite(buf, sizeof(char), bytes, fp2);
		}


		//③fgetc fputc(一个字节一个字节的读写)
		/*while(1){
	 		int ch=getchar();//fgetc(fp1);
	 		if(ch==EOF)break;
	 		//fputc(ch,fp2);
	 		putchar(ch);//fputc(ch,stdout);
	 	}
	 	*/


		//④fgets fputs(一行一行的读写)
		/*char buf[32]={'\0'};
		 while(fgets(buf,sizeof(buf),fp1)!=NULL)
		 fputs(buf,fp2);
	 	*/

		//⑤fscanf fprintf
		/*while (1) {
			char buf[256] = { '\0' };
			int ret = fscanf(fp1, "%s", buf);
			if(ret==EOF)break;
			fprintf(fp2, "%s", buf);
		}
		*/
		
		//⑥system
		/*system("cp copy.c a.txt");*/
		
		//⑦使用execl协议族中的函数
		/*
		char *argv[] = { "cp", "copy.c","copy.txt", NULL };
		execv("/bin/cp",argv);
		*/
		
		fclose(fp1);
		fclose(fp2);
		return 0;
	}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值