linux基础io
C语言文件io
C语言打开文件
打开/关闭文件函数fopen/fclose:
FILE * fopen(const char* filename, const char* mode);
int fclose (FILE* stream );
文件打开方式:
C语言库函数
fputc/fgetc函数
int fputc( int c,//字符(或者对应ASCII码值)
FILE *stream //文件指针(或者流)
);
//https://www.runoob.com/cprogramming/c-function-fputc.html
int fgetc( FILE *stream );
//https://www.runoob.com/cprogramming/c-function-fgetc.html
C 库函数 int fputc(int char, FILE *stream) 把参数 char 指定的字符(一个无符号字符)写入到指定的流 stream 中,并把位置标识符往前移动。
https://www.runoob.com/cprogramming/c-function-fputc.html
C 库函数 int fgetc(FILE *stream) 从指定的流 stream 获取下一个字符(一个无符号字符),并把位置标识符往前移动。
https://www.runoob.com/cprogramming/c-function-fgetc.html
每当函数运行一次后,流(标准输入流或者文件流)的指针就会指向读取内容后一个空间的首地址
fpunc示例:
#include <stdio.h>
int main ()
{
FILE *fp;
int ch;
fp = fopen("file.txt", "w+");
for( ch = 33 ; ch <= 100; ch++ )
{
fputc(ch, fp);
}
fclose(fp);
return(0);
}
fgetc示例:
#include <stdio.h>
int main ()
{
FILE *fp;
int c;
int n = 0;
fp = fopen("file.txt","r");
if(fp == NULL)
{
perror("打开文件时发生错误");
return(-1);
}
do
{
c = fgetc(fp);
if( feof(fp) )
{
break ;
}
printf("%c", c);
}while(1);
fclose(fp);
return(0);
}
fputs/fgets函数
char *fgets( char *string, int n, FILE *stream );
//https://www.runoob.com/cprogramming/c-function-fgets.html
int fputs( const char *string, FILE *stream );
//https://www.runoob.com/cprogramming/c-function-fputs.html
C 库函数 char *fgets(char *str, int n, FILE *stream) 从指定的流 stream 读取一行,并把它存储在 str 所指向的字符串内。当读取 (n-1) 个字符时,或者读取到换行符时,或者到达文件末尾时,它会停止,具体视情况而定。
C 库函数 int fputs(const char *str, FILE *stream) 把字符串写入到指定的流 stream 中,但不包括空字符。
fgets示例:
#include <stdio.h>
int main()
{
FILE *fp;
char str[60];
/* 打开用于读取的文件 */
fp = fopen("file.txt" , "r");
if(fp == NULL) {
perror("打开文件时发生错误");
return(-1);
}
if( fgets (str, 60, fp)!=NULL ) {
/* 向标准输出 stdout 写入内容 */
puts(str);
}
fclose(fp);
return(0);
}
fputs示例:
#include <stdio.h>
int main ()
{
FILE *fp;
fp = fopen("file.txt", "w+");
fputs("这是 C 语言。", fp);
fputs("这是一种系统程序设计语言。", fp);
fclose(fp);
return(0);
}
fscanf/fprintf-格式化读写函数
int fscanf( FILE *stream, const char *format [, argument ]... );
//https://www.runoob.com/cprogramming/c-function-fscanf.html
int fprintf( FILE *stream, const char *format [, argument ]...);
//https://www.runoob.com/cprogramming/c-function-fprintf.html
fscanf示例:
下面的实例演示了 fscanf() 函数的用法。
#include <stdio.h>
#include <stdlib.h>
int main()
{
char str1[10], str2[10], str3[10];
int year;
FILE * fp;
fp = fopen ("file.txt", "w+");
fputs("We are in 2014", fp);
rewind(fp);
fscanf(fp, "%s %s %s %d", str1, str2, str3, &year);
printf("Read String1 |%s|\n", str1 );
printf("Read String2 |%s|\n", str2 );
printf("Read String3 |%s|\n", str3 );
printf("Read Integer |%d|\n", year );
fclose(fp);
return(0);
}
让我们编译并运行上面的程序,这将产生以下结果:
Read String1 |We|
Read String2 |are|
Read String3 |in|
Read Integer |2014|
fprintf示例:
下面的实例演示了 fprintf() 函数的用法。
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE * fp;
fp = fopen ("file.txt", "w+");
fprintf(fp, "%s %s %s %d", "We", "are", "in", 2014);
fclose(fp);
return(0);
}
让我们编译并运行上面的程序,这将创建文件 file.txt,它的内容如下:
We are in 2014
sscanf/sprintf函数
int sprintf( char *buffer, const char *format [, argument] ... );
//https://www.runoob.com/cprogramming/c-function-sprintf.html
int sscanf( const char *buffer, const char *format [, argument ] ... );
//https://www.runoob.com/cprogramming/c-function-sscanf.html
sscanf示例:
下面的实例演示了 sprintf() 函数的用法。
#include <stdio.h>
#include <math.h>
int main()
{
char str[80];
sprintf(str, "Pi 的值 = %f", M_PI);
puts(str);
return(0);
}
让我们编译并运行上面的程序,这将产生以下结果:
Pi 的值 = 3.141593
scanf/printf、fscanf/fprintf、sscanf/sprintf函数对比
函数 | 对比 |
---|---|
scanf/printf | 格式化的I/O函数,针对的是标准输入流和输出流 |
fscanf/fprintf | 格式化的I/O函数,针对的是所有输入流和输出流 |
sscanf/sprintf | 在字符串中提取可格式化的数据输入,把格式化的数据转化为字符串输出 |
stdin/stdout/stderr
extern FILE *stdin;
extern FILE *stdout;
extern FILE *stderr;
任何C程序运行都会默认打开三个输入输出流,分别是:stdin, stdout, stderr
分三个文件流分别对应键盘文件,显示器文件,显示器文件
实际上几乎所有的语言都会打开这三个文件
系统文件io
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);
pathname: 要打开或创建的目标文件
flags: 打开文件时,可以传入多个参数选项,用下面的一个或者多个常量进行“或”运算,构成flags
mode_t:如果没有对应文件需要进行创建的话,就需要指定创建文件的八进制访问权限值
参数选项 | 含义 |
---|---|
O_RDONLY | 以只读的方式打开文件 |
O_WRNOLY | 以只写的方式打开文件 |
O_APPEND | 以追加的方式打开文件 |
O_RDWR | 以读写的方式打开文件 |
O_CREAT | 当目标文件不存在时,创建文件 |
这里的参数选项是依靠不同的比特位来标识对应的功能设定,所以这里的异或操作就是将对应比特位置为1,同时函数也是通过对每个比特位进行与操作检查是否该比特位置为了1
#define O_RDONLY 00
#define O_WRONLY 01
#define O_RDWR 02
#define O_CREAT 0100
示例:
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<assert.h>
int main()
{
FILE* fp=fopen("bite","w+");
if(fp==NULL)
{
perror("fopen");
}
const char *ptr="linux so easy!";
fwrite(ptr,strlen(ptr)+1,1,fp);
char buffer[64];
fseek(fp,0,SEEK_SET);
fread(buffer,strlen(ptr),1,fp);
printf("buffer:%s\n",buffer);
return 0;
}
int main()
{
int fd=open("bite",O_RDWR | O_CREAT | O_TRUNC, 0666);
if(fd<0)
{
perror("open");
return 1;
}
const char* ptr="i like linux";
write(fd,ptr,strlen(ptr));
lseek(fd,0,SEEK_SET);
char buffer[64];
read(fd,buffer,32);
printf("buffer:%s\n",buffer);
close(fd);
return 0;
}
文件描述符
0 & 1 & 2
Linux进程默认情况下会有3个缺省打开的文件描述符,分别是标准输入0, 标准输出1, 标准错误2.
0,1,2对应的物理设备一般是:键盘,显示器,显示器
所以输入输出还可以采用如下方式:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
int main()
{
char buf[1024];
ssize_t s = read(0, buf, sizeof(buf));
if(s > 0)
{
buf[s] = 0;
write(1, buf, strlen(buf));
write(2, buf, strlen(buf));
}
return 0;
}
文件描述符的分配规则
在files_struct数组当中,找到当前没有被使用的最小的一个下标,作为新的文件描述符
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
int fd = open("myfile", O_RDONLY);
if(fd < 0)
{
perror("open");
return 1;
}
printf("fd: %d\n", fd);
close(fd);
return 0;
}
输出:fd: 3
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
close(0);
//close(2);
int fd = open("myfile", O_RDONLY);
if(fd < 0)
{
perror("open");
return 1;
}
printf("fd: %d\n", fd);
close(fd);
return 0;
}
输出: fd: 0 或者 fd 2
重定向
重定向输出
在 Linux 系统中,使用 > 字符表示重定向输出。例如,将 ls 命令的输出重定向到一个文件中:
$ ls > list.txt
执行此命令不会在显示器上输出信息而是将信息重定向至list.txt
我们也可以使用c语言进行重定向:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
int main()
{
close(1);
int fd = open("myfile", O_WRONLY|O_CREAT, 00644);
if(fd < 0)
{
perror("open");
return 1;
}
printf("fd: %d\n", fd);
fflush(stdout);
close(fd);
exit(0);
}
和使用bash的效果是一样的
从上述示例来看,输出重定向是将进程中的文件指针数组中的标准输出stdout文件给关闭(并非真正关闭,而是将指针数组对应下标的内容置空),再将新打开文件分配到标准输出文件对应的下标上,再输出时,系统不知道文件已经替换,依旧输出到stdout文件对应的数组下标为1的文件上,但是此时文件已经被替换了
dup2
#include <unistd.h>
int dup2(int oldfd, int newfd);//将文件地址oldfd替换到newfd上
其中newfd是被oldfd替代的
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
umask(0);
int fd = open("log.txt", O_RDONLY);
if(fd < 0)
{
perror("open");
return 1;
}
dup2(fd, 0); //输入重定向
char line[64];
while(1)
{
printf("> ");
if(fgets(line, sizeof(line), stdin) == NULL) break; //stdin->0
printf("%s", line);
}
close(fd);
return 0;
}