标准I/O
一、标准I/O概述
1.文件指针
FILE指针:每个被使用的文件都在内存中开辟一个区域,用来存放文件的有关信息,这些信息保存在一个结构体类型的变量中,该结构体类型是由系统定义的,取名为FILE。
2.标准I/O库的所有操作都是围绕流(stream)来进行的,在标准I/O中流用FILE*来描述;
3.流(stream):所有I/O操作仅是简单的从程序移进或者移出,这种字节流就称为流;
4.标准I/O提供三种类型的缓存:
- 全缓冲:当填满I/O缓存后才进行实际I/O操作;
- 行缓存:当输入和输出中遇到符号('\n')时,才进行I/O操作;
- 不带缓存:标准I/O库不对字符进行缓存,例如:stderr
5.使用setbuf()和setvbuf()可以更改缓存的类型;
6.刷新(fflush):标准I/O的写操作;在任何时刻都可以使用fflush强制刷新一个数据流(此函数使该流所有未写的数据都被传递至内核);
#include<stdio.h>
int main (void)
{
static char buf[1024];
//setbuf(stdout, buf);
printf("aaaaaaaaaa");
fflush(stdout); //没有将不会打印aaaaaaa
while (1);
return 0;
}
- 标准输入 0 stdin
- 标准输出 1 stdout
- 标准错误输出 2 stderr
二、标准I/O的函数
(一)打开一个标准I/O流
#include <stdio.h>
FILE *fopen(const char *path, const char *mode);
path --- 打开文件的路径mode --- 打开文件的方式:r,r+,w,w+,a,a+
#include<stdio.h>
int main()
{
FILE *fp;
fp = fopen("test.c","r+");
if(fp == NULL)
{
perror("fopen");
return -1;
}
printf("success\n");
if(EOF == fclose(fp))
{
perror("fclose");
return -1;
}
}
(二)一次读写一个字符
#include <stdio.h>
int fgetc(FILE *stream);
int fputc(int c, FILE *stream);
返回值:成功则为下一次字符
出错 --- EOF
int main()
{
int ch;
while(EOF != (ch = fgetc(stdin)))
{
fputc(ch,stdout);
}
return 0;
}
(三)一次输入/输出一行
#include <stdio.h>
char *fgets(char *s, int size, FILE *stream); //stream->s
int fputs(const char *s, FILE *stream); //s -> stream
返回值:成功则为bufEOF --- 出错
int main()
{
char buf[1024];
while(1)
{
if(NULL != fgets(buf,sizeof(buf),stdin))
fputs(buf,stdout);
}
return 0;
}
示例代码:
#include<stdio.h>
#include<string.h>
int main(int argc,char *argv[])
{
if(argc<3)
{
fprintf(stderr,"Usage: %s <file1name> <file2name>\n",argv[0]);
return -1;
}
FILE *fp = fopen(argv[1],"r+");
if( fp == NULL)
{
perror("fopen");
return -1;
}
FILE *fp1 = fopen(argv[2],"w+");
if( fp1 == NULL)
{
perror("fopen");
return -1;
}
char buf[100];
while(fgets(buf,sizeof(buf),fp) != NULL)
{
fputs(buf,fp1);
}
return 0;
}
(四)整体读写
#include <stdio.h>
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); //stream->ptr,大小->nmemb
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); //ptr->stream
#include<stdio.h>
#include<string.h>
int main(int argc,char *argv[])
{
if(argc<3)
{
fprintf(stderr,"Usage: %s <file1name> <file2name>\n",argv[0]);
return -1;
}
FILE *fp = fopen(argv[1],"r+");
if( fp == NULL)
{
perror("fopen");
return -1;
}
FILE *fp1 = fopen(argv[2],"w+");
if( fp1 == NULL)
{
perror("fopen");
return -1;
}
char buf[100];
int ret;
while(1)
{
ret = fread(buf,1,sizeof(buf),fp);
if(ret<0)
{
perror("fread");
break;
}
else if(ret == 0)
{
printf("read file end\n");
break;
}
fwrite(buf,1,ret,fp1);
}
fclose(fp);
fclose(fp1);
return 0;
}
(五)定位流fseek()
#include <stdio.h>
int fseek(FILE *stream, long offset, int whence);
offset ---> 偏移的字节数whence ---> SEEK_SET --- 文件头
SEEK_CUR --- 当前位置
SEEK_END --- 文件尾
返回值:0 --- 成功
-1 --- 失败
if(0>fseek(fp,,100,SEEK_SET))
{
perror("fseek");
return -1;
}
文件I/O
一、文件I/O的性质
- 不带缓冲;
- 通过文件描述符来访问文件(fd),是一个非负整数;
二、文件I/O的函数
(一)打开文件
#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);flags --- 打开方式
mode --- 权限
O_RDONLY 只读 O_WRONLY 可写 O_RDWR 读写 O_CREAT 不存在新建,并设置权限 O_TRUNC 存在删除原有数据 O_APPEND 追加 返回值:成功返回文件描述符
失败返回-1,并设置errno
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
int main(int argc,char *argv[])
{
int fd;
fd = open("test.c",O_WRONLY|O_CREAT|O_EXCCL,0644);
if(fd<0)
{
perror("open");
return -1;
}
printf("open success!\n");
close(fd);
return 0;
}
(二)读写数据
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count); //fd -> buf
ssize_t write(int fd, const void *buf, size_t count); //buf -> fd
返回值:成功 --- 字节数0 --- 表示达到文件末尾
-1 --- 出错,并设置erron
示例代码1:
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
int main(int argc,char *argv[])
{
if(argc < 3)
{
fprintf(stdout,"Usage: %s <file1name> <file2name>",argv[0]);
return -1;
}
int fd1;
int fd2;
fd1 = open(argv[1],O_RDONLY);
fd2 = open(argv[2],O_WRONLY);
if( fd1 < 0)
{
perror("open");
return -1;
}
char buf[100];
int ret;
/* while(1)
{
ret = read(fd1,buf,sizeof(buf));
if(ret < 0)
{
perror("read");
break;
}
else if(ret = 0)
{
perror("read");
break;
}
write(fd2,buf,ret);
}
*/
while(read(fd1,buf,sizeof(buf)) > 0)
{
write(fd2,buf,sizeof(buf));
}
close(fd1);
close(fd2);
return 0;
}
示例代码2:
/*************************************************************************
> File Name: open.c
> Author:
> Mail:
> Created Time: 2017年08月08日 星期二 11时41分42秒
************************************************************************/
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
int main(int argc,char *argv[])
{
if(argc<2)
{
fprintf(stdout,"Usage: %s <filename>",argv[0]);
return -1;
}
int fd;
fd = open(argv[1],O_WRONLY);
if(fd<0)
{
perror("fd");
return -1;
}
char buf[100];
int ret;
while(1)
{
ret = read(fd,buf,sizeof(buf));
if(ret<0)
{
break;
}
write(fd,buf,ret);
}
close(fd);
return 0;
}
(三) 定位
#include <sys/types.h>
#include <unistd.h>off_t lseek(int fd, off_t offset, int whence);
offset --- 偏移字节数whence ---> SEEK_SET --- 头
SEEK_CUR --- 当前位置
SEEK_END --- 文件末尾
获取文件/目录的属性信息
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>int stat(const char *path, struct stat *buf);
int fstat(int fd, struct stat *buf);
int lstat(const char *path, struct stat *buf);
返回值 :0 --- 成功-1 --- 出错,并设置errno
目录操作相关函数
chdir()/opendir()/readdir()
#include <stdio.h>
#include <dirent.h>
int main()
{
DIR *dirp = opendir(".");
struct dirent *file;
while (file = readdir(dirp)) {
printf("filename: %s\n", file->d_name);
}
closedir(dirp);
return 0;
}