C语言I/O操作
(只写了文件调用的,C库自己看吧)
1、系统调用
定义:指操作系统提供给用户程序的调用的一组“特殊接口”,用户程序可以通过这组特殊接口来获得操作系统内核提供的服务
2、Linux文件描述符
当某个程序打开程序时,操作系统会返回相应的文件描述符,(相当于文件的别名,打开之后就只用这个fd来表示这个文件,和C库函数文件指针fd一样),这个描述符是一个正整数,012都被默认打开的三个文件使用了(标准输入、标准输出、标准出错处理)
3、带不带缓冲的I/O操作
1、不带I/O缓冲操作(系统调用),主要用到6个函数,ctreat、open、read、write、lseek、close,这里指的不带缓冲是指每个函数都只调用系统中的一个函数,这些函数虽然不是ANSI C的组成部分,但确是POSIX的组成部分。
2、带缓冲I/O操作(标准IO提供)。标准I/O库提供缓冲的目的的是尽可能减少调用read函数和write函数的次数,它也对每个I/O流自动的进行缓冲管理,从而避免应用程序需要考虑这一点带来的麻烦。
全缓冲:只有等填满IO缓冲区后在进行实际IO操作,对于驻留在磁盘上的文件,通常都是标准IO库实施全缓冲的。
行缓冲:当在输出输入中遇到换行符是,标准IO库执行IO操作,允许我们一次输出一个字符,但只有在写了一行之后才进行实际IO操作,当流涉及一个终端时,通常使用缓冲。
不带缓冲:标准IO库 不对字符进行缓冲存储,标准出错流stderr通常是不带缓冲的,使出错信息可以尽快显示出来,不管他们是有含有一个换行符。
4、int creat(const char *filename, mode_t mode )
1、包涵头文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
2、filename :创建的文件名 (包含路径,缺省为当前路径) mode:创建模式 mode(相当于权限,其实改变的也只有用户自己的权限,别人的权限他也改不了)S_IRUSR 可读 S_IWUSR可写 S_IXUSR 可执行 S_IXRWU可读可写可执行,可以选这些宏也可以 用数字表示
3、返回文件描述词,有错误会返回-1,错误代码存入errno(系统全局变量)中
5、int open(const char *pathname, int flags)//打开或者是要创建的名字,mode创造新文件的权限参数
int open(const char *pathname, int flags,mode_t mode);
flags:打开方式常用方式如下
O_RDONLY O_WRONLY O_RDWR :只读只写读写
O_CREAT:要打开的文件不存在就自动创建该文件
O_EXCL:检查文件是否存在,不存在就创建,否则打开文件错误
O_TRUNC:若文件存在以写的方式打开,会使文件长度清零
O_NONBLOCK:以不可阻断的方式打开文件,也就是无论有无数据读取或等待,都会立即返回进程之中。
close(int fd):对应关闭文件。
6、int read(int fd, const void *buf, size_t length)
int write(int fd, const void * buf, size_t length)
1、包含头文件:#include<unistd.h>
2、读从文件描述符fd所指定的文件中读取length个字节到buf所指向的缓冲区中,返回值为实际读取的字节数。写把length个字节从buf指向的缓冲区中写到文件描述符fd所指向的文件中,返回值为实际写入的字节数。
不保证读写的是指定字节数,所有应该有错误判断
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
//#include <error.h>
int main(int argc,char *argv[])
{
int fd;
int i;
char buffer[] = "hello";
char *ptr = NULL;
int bytes_write;
int bytes = 5;
if(argc != 2)
{
printf("please input the flie name :");
exit(0);
}
if((fd = open(argv[1],O_WRONLY | O_CREAT| O_TRUNC,0644)) == -1)
{
perror("open file error");
exit(-1);
}
for( i = 0;i < 3;i++)
{
ptr = buffer;
while(bytes_write = write(fd,ptr,bytes))
{
if(-1 == bytes_write)
{
perror("write error");
}
else if(bytes_write == bytes)
{
break;
}
else
{
bytes -= bytes_write;
ptr += bytes_write;
}
}
if(-1 == bytes_write)
{
break;
}
write(fd,"\n",1);
}
close(fd);
return 0;
}
7、int lseek(int fd, offset_t offset, int whence)
将文件读写指针相对whence移动offset个字节。操作成功时,返回文件指针相对于文件头的位置。文件里都有类似于文件指针读写的东西,读取时移动,当写入结束想读取的时候,这时候(文件指针读写)在文件末尾,所以读不到数,需要重置(文件指针读写)。
whence 可使用的值:SEEK_SET相对文件开头,SEEK_CUR相对文件读写指针的当前位置,SEEK_END相对于文件末尾。offset可取负值,表示向前移动
8、使用lseek计算文件长度
由于lseek函数的返回值为文件指针相对于文件头的位置,因此下面调用的返回值就是文件的长度: lseek(fd, 0, SEEK_END),用这个也可以判断文件内容是否写完。
9、hello回车符三行
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define MAX 100
int read_line(int fd, char *buf, int count)
{
int i;
char ch;
for(i = 0; i < count; i++)
{
if((read(fd,&ch,1)) < 0)
{
perror("read error!\n");
exit(1);
}
if(ch == '\n')
{
buf[i] = '\0';
return i;
}
buf[i] = ch;
}
buf[i - 1] = '\0';
return count;
}
int main()
{
int i;
int fd;
int w_count;
int r_count;
char filename[MAX];
char r_buf[MAX];
char w_buf[MAX];
printf("Please input filename:\n");
scanf("%s",filename);
if((fd = open(filename, O_CREAT | O_RDWR, 0755)) < 0)
{
perror("open error!\n");
exit(1);
}
for(i = 0; i < 3; i++)
{
memset(w_buf,0,sizeof(w_buf));
scanf("%s",w_buf);
if((w_count = write(fd,w_buf,strlen(w_buf))) < 0)
{
perror("write error!\n");
exit(1);
}
else
{
write(fd,"\n",1);
}
}
lseek(fd,0,SEEK_SET);
#if 0
if((r_count = read(fd,r_buf,sizeof(r_buf))) < 0)
{
perror("read error!\n");
exit(1);
}
else
{
r_buf[w_count * 3 + 3] = '\0';
printf("read data: %s\n",r_buf);
}
#endif
for(i = 0; i < 3; i++)
{
memset(r_buf,0,sizeof(r_buf));
read_line(fd,r_buf,100);
printf("read data: %s\n",r_buf);
}
close(fd);
return 0;
}

浙公网安备 33010602011771号