当前位置: 首页 > news >正文

嵌入式 Linux 文件IO操作

 

目录

 

Linux 文件操作

1 Linux 系统环境文件操作概念

2 缓冲 IO 文件操作

1 文件的创建,打开与关闭

 fopen 函数函数

2 freopen 函数

3、fdopen函数

4、fclose函数

 5、格式化读写

6、单个字符读写

7、文件定位

8、标准目录文件

9、非缓冲IO文件操作


Linux 文件操作

1 Linux 系统环境文件操作概念

  Linux 中一切皆文件,对目录和设备的操作都是文件操作。文件分为普通文件,管道文件,目录文件,链接 文件和设备文件。

普通文件:也称磁盘文件,并且能够进行随机的数据存储(能够自由 seek 定位到某一个位置);

管道文件:是一个从一端发送数据,另一端接收数据的数据通道;

目录文件:它包含了保存在目录中文件列表的简单文件。

设备文件:Linux 下各种硬件设备都是文件,该类型的文件提供了大多数物理设备的接口。它又分为两种类 型:字符型设备和块设备。字符型设备一次只能读出和写入一个字节的数据,包括调制解调器、终端、打印机、 声卡以及鼠标;块设备必须以一定大小的块来读出或者写入数据,块设备包括 CD-ROM、RAM 驱动器和磁盘驱 动器等,一般而言,字符设备用于传输数据,块设备用于存储数据。

套接字文件:在 Linux 中,套接字也可以当作文件来进行处理。

对文件进行的操作有打开文件,关闭文件,读写文件。其中打开文件是第一步,是为后续操作做准备的。

2 缓冲 IO 文件操作

  文件指针:每打开一个文件,就返回一个指针(FILE*类型),称为文件指针。这个指针指向了这个文件相关 的所有信息,即我们就可以用这个指针代表这个文件,通过这个指针可以对这个打开的文件进行各种操作。

缓冲区:输入输出的数据并不是一下子直接到电脑内存和显示器中,输入的数据先暂时存放在键盘缓冲区中, 然后程序从该缓冲区中读取数据。输出的数据先暂时存放在输出缓冲区中,然后再把该数据输出到屏幕中。本节 介绍的输入输出相关函数都是要用到缓冲区的。

1 文件的创建,打开与关闭

相关函数声明在 stdio.h 文件中,编写程序时候需要 #include 。

 FILE *fopen(const char *path,const char *mode); //文件名模式 
FILE *fdopen(int filds,const char *mode);
FILE *freopen(const char *path,const char *mode, FILE *stream); 
int fclose(FILE *stream); 

前面三个打开文件相关的函数都有一个参数 mode,这个参数是指定打开模式,具体意义如下表所示。

表 5.1 可选模式  在 Linux 系统中,mode 里面的’b’(二进制)可以去掉,但是为了保持与其他系统的兼容性,建议不要去掉。ab 和 a+b 为追加模式,在此两种模式下,无论文件读写点定位到何处,在写数据时都将是在文件末尾添加,所以比 较适合于多进程写同一个文件的情况下保证数据的完整性。

 fopen 函数函数

原型:FILE *fopen(const char *path,const char *mode);

功能:fopen 以 mode 的方式打开或创建文件,如果成功,将返回一个文件指针,失败则返回 NULL。

参数:  path:要打开的文件

mode:打开模式,Linux 系统中有下列几种形态字符串:

r 打开只读文件,该文件必须存在。

r+ 打开可读写的文件,该文件必须存在。

w 打开只写文件,若文件存在则文件长度清为 0,即该文件内容会消失。

若文件不存在则建立该文件。

w+ 打开可读写文件,若文件存在则文件长度清为零,即该文件内容会消失。

若文件不存在则建立该文件。

a 以附加的方式打开只写文件。

若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件 尾,即文件原先的内容会被保留。

a+ 以附加方式打开可读写的文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到 文件尾后,即文件原先的内容会被保留。

上述的形态字符串都可以再加一个 b 字符,如 rb、w+b 或 ab+等组合,加入 b 字符用来告诉函数库打开的 文件为二进制文件,而非纯文字文件。

不过在 POSIX 系统,包含 Linux 都会忽略该字符。

返回: 成功:指向该流的文件指针就会被返回。 失败:则返回 NULL,并把错误代码存在 errno 中。

打开文件后可以执行文件读取或写入的动作,若开文件失败,接下来的读写动作也无法顺利进行,所以在 fopen()后请作错误判断及处理。

附加说明:由 fopen()所建立的新文件会具有 S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH(0666)权限,此文件权限也会参考 umask 值。

示例代码:打开时候创建一个不存在的文件 以下代码输入到 fopen.c 中

 #include int main(void) {FILE *fil; fil = fopen("myfirstfile.txt", "a+"); if(fil == NULL) { printf("open error!\r\n"); return; } fclose(fil); return 0; } 

终端执行:

[root@localhost 01_fopen]# touch fopen.c 
[root@localhost 01_fopen]# gedit fopen.c& 
[1] 6145 
[root@localhost 01_fopen]# gcc -o fopen fopen.c 
[root@localhost 01_fopen]# ./fopen

2 freopen 函数

原型:FILE *freopen(const char *path,const char *mode, FILE *stream);

功能:实现重定向,把预定义的标准流文件定向到由 path 指定的文件中。

标准流文件具体是指 stdin、stdout 和 stderr。其中 stdin 是标准输入流,默认为键盘;stdout 是标准输出流,默认为屏幕;stderr 是标准错误流,一般把屏幕设为默认。

参数: path: 文件名,用于存储输入输出的自定义文件名。

mode: 文件打开的模式。和 fopen 中的模式(如 r-只读, w-写)相同。

stream: 一个文件,通常使用标准流文件。

返回: 成功:返回一个 path 所指定文件结构指针;

失败:返回 NULL。(一般可以不使用它的返回值)

 实例代码:重定向标准输入,标准输出流

以下代码输入到freopen.c当中;

#include <stdio.h> 
int main() 
{ int a,b; freopen("in.txt","r",stdin); //输入重定向,输入数据将从 in.txt 文件中读取freopen("out.txt","w",stdout); //输出重定向,输出数据将保存在 out.txt 文件中while(scanf("%d %d",&a,&b)!=EOF) printf("%d\n",a+b); fclose(stdin);//关闭文件fclose(stdout);//关闭文件return 0; 
}

编译测试:

[root@localhost 02_freopen]# touch in.txt out.txt freopen.c
[root@localhost 02_freopen]# echo 1 2 3 4 5 6 7 8 9 10 >in.txt 
[root@localhost 02_freopen]# cat in.txt 
1 2 3 4 5 6 7 8 9 10
[root@localhost freopen]# gedit freopen.c &
[1] 6474
[root@localhost freopen]# gcc freopen.c 
[1]+ Done gedit freopen.c
[root@localhost freopen]# ./a.out 
[root@localhost freopen]# cat out.txt 
3 <-- a=1,b=2 ,即从 in.txt 中读取第 1 和第 2 个字节
7 <-- a=3,b=4 ,即从 in.txt 中读取第 3 和第 4 个字节
11
15
19
[root@localhost freopen]#

3、fdopen函数

原型:FILE *fdopen(int filds,const char *mode);

功能:函数说明 fdopen()会将参数 fildes 的文件描述词,转换为对应的文件指针后返回。参数 mode 字符串 则代表着文件指针的流形态,此形态必须和原先文件描述词读写模式相同。关于 mode 字符串格式请参考 fopen()。

返回值: 成功:返回指向该流的文件指针。 失败:NULL,并把错误代码存在 errno 中。 说明:这个函数比较少用,一般用来打开某些不能直接用 fopen 方式打开的文件,比如管道和网络套接字文 件。

例子:把标准输出文件描述符0转换成文件流

#include<stdio.h>
int main(void)
{FILE * fp =fdopen(0,"w+");fprintf(fp,"%s\n","hello!");fclose(fp);
return 0;
}

终端测试:

[root@localhost 03_fdopen]# touch fdopen.c
[root@localhost 03_fdopen]# gedit fdopen.c &
[1] 3400
[root@localhost 03_fdopen]# gcc -o fdopen fdopen.c
[1]+ Done gedit fdopen.c
[root@localhost 03_fdopen]# ./fdopen 
hello!
[root@localhost 03_fdopen]#

4、fclose函数

int fclose(FILE *stream); 功能:关闭 stream 指向的文件。

1 判断文件结尾函数 feof

原型:int feof(FILE * stream);

功能:feof 函数检查文件流是否读到了文件尾

参数:stream 文件指针

返回:返回非零值代表已到达文件尾

2 数据块写函数 fwrite

原型:size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

功能:以二进制形式对文件进行操作,从 ptr 指向的内存中读取 nmemb 个元素,每个元素 size 个字节,写 到文件流 stream 中。

参数:

ptr:这是一个 void 型指针,指出要将写入数据存放在其中的存储区首地址

size:指出一个数据块的字节数,即一个数据块的大小尺寸

nmemb:指出一次写入多少个数据块(size)

stream:输出数据流指针

返回: 正常:实际写入数据块的个数,即 nmemb 。 异常:如果文件中剩下的数据块个数少于参数中 size 指出的个数,或者发生了错误,返回 0 值。此时可以用 feof()和 ferror()来判定到底出现了什么情况。 说明:写入到文件的哪里? 这个与文件的打开模式有关,如果是 w+,则是从文件指针指向的地址开始写, 替换掉之后的内容,文件的长度可以不变,stream 的位置移动 size 个数;如果是 a+,则从文件的末尾开始添加, 文件长度加大。

3 数据块读函数 fread

原型:size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

功能:以二进制形式对文件进行操作,从文件流 stream 中读取 nmemb 个元素,每个元素 size 个字节,存放 到 ptr 指向的数据缓冲区中。

参数:

ptr:这是一个 void 型指针,指出要将读入数据存放在其中的存储区首地址

size:指出一个数据块的字节数,即一个数据块的大小尺寸

nmemb:指出一次读入多少个数据块(size)

stream:输入数据流指针

返回: 正常:大于 0,返回真实读取的元素数

异常:小于 nmemb,此时可以用 feof()和 ferror()来判定到底出现了什么情况。

4、读写文件块实例:

#include <stdio.h>
#include <stdlib.h>
int main(void)
{char buf1[50] = {0};char buf[50] = {'h','e','l','l','o'};FILE *p; //定义一个 FILE 结构体类型的指针 pp = fopen("a.txt", "r+b"); //p 这个指针此时就和文件 a.txt 关联起来了。if(!p){perror("fopen");exit(0);}fwrite(buf, 1, 5, p); //把 buf 里面的内容写到 p 指向的文件中。fseek(p,0,SEEK_SET); //移动光标到文件开头fread(buf1, 1, 5, p); //读出上一步写入的数据printf("buf1:%s\n", buf1);fclose(p); //关闭 p 代表的文件 a.txtreturn 0;
}

 5、格式化读写

fprintf 函数

原型:int fprintf(FILE *stream, const char *format, ...);

功能:格式化数据输出到一个文件中 stream 指向的文件

参数:

stream 一个 FILE 型的指针

format 输出格式,和 printf 函数的参数一样

返回: 正数:成功格式化的字节数

负数:格式化转换失败

实例:使用fprintf格式化数据输出到文件

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int ret;int i = 10;double fp = 1.5;char *s = "this is a string";char c = '\n';FILE* stream;stream = fopen("fprintf.out", "w");if(!stream){perror("fopen");return -1;}ret = fprintf(stream, "%s%c", s, c);
printf("ret=%d\r\n",ret);ret = fprintf(stream, "%d\n", i);
printf("ret=%d\r\n",ret);ret = fprintf(stream, "%f\n", fp);
printf("ret=%d\r\n",ret);fclose(stream);return 0;
}

 fscanf函数

原型:int fscanf(FILE *stream, const char *format, …);

功能:从一个流中执行格式化输入,fscanf 遇到空格和换行时结束,注意空格时也结束。这与 fgets 有区别, fgets 遇到空格不结束。

参数: stream 一个 FILE 型的指针

format 输出格式,和 printf 函数的参数一样

返回: 正数:成功则返回参数数目(不是字节数) -1 :失败,错误原因存于 errno 变量中

示例:使用 fscanf 从特定数据格式的文件中读取内容到内存变量中

#include <stdio.h>
#include <stdlib.h>
int main(void)
{int ret = 0;char name[100]={0};double price;FILE* stream;stream = fopen("data.in", "r");if(!stream){perror("fopen");return -1;}while(!feof(stream)){ret = fscanf(stream, "%s%lf\n",name,&price);printf("ret:%d\r\n",ret);printf("name:%s,price:%0.2lf\r\n",name,price);}fclose(stream);return 0;
}

6、单个字符读写

单字符读函数

使用下列函数可以一次读一个字符:

int fgetc(FILE *stream);

int getc(FILE *stream);

功能: fgetc 从这个流中读取下一个字符,读取成功后文件读写位置值增 1,并把读取到的字符以 int 类型的值返回 发生了错误或者已经位于文件尾部,fgetc 返回 EOF。在这种情况下,程序员应使用 feof 函数来判断是否真 正的达到了文件尾。

getc 的功能与 fgetc 相同,但为了提高效率,它一般被实现为宏。

参数:stream 文件结构指针

返回: 正数:读取的字符 ASIIC 值

负数:读取失败,值为 EOF,程序员应使用 feof 函数来判断是否真正的达到了文件尾。

单字符写函数

使用下列函数可以一次写一个字符:

int fputc(int c, FILE *stream);

int putc(int c, FILE *stream);

功能:这两个函数作用相同,用于向 stream 所指向的文件的当前读写位置写入一个字符,成功写入一个字 符后,文件读写位置指针向后移动一个字节。

参数:

c 要写入的字符

stream 文件指针

返回: 正数:写入的字符 ASIIC 值

负数:写入失败,值为 EOF 

单字符读写函数实例:

使用单字符读写函数实现文件复制功能

#include<stdio.h>
//测试时候先自己创建 data.in,并且 输入测试内容
int main (void)
{FILE * pFile;FILE * pOut;int n = 0;int ch;pFile = fopen ("data.in","rb"); //源文件if (pFile==NULL){perror ("Error opening file");}pOut = fopen ("data.out","w+"); //目标文件if (pOut==NULL){perror ("Error opening file");}while ( (ch=fgetc(pFile)) != EOF) {++n;fputc(ch,pOut);}if (feof(pFile)) {//when EOFputs ("End-of-File reached.");printf ("Total number of bytes read: %d\n", n);} else { //when error puts ("End-of-File was not reached.");}fclose (pFile);fclose (pOut);return 0;
}

 字符串读取函数

原型:char *fgets(char * string, int size, FILE *stream);

功能:该函数从 stream 所指的文件中读取以'\n'结尾的一行(包括'\n'在内)存到缓冲区 string 中,并且在该 行末尾添加一个'\0'组成完整的字符串。

参数:

string 为一个字符数组,用来保存读取到的字符。

size 为要读取的字符的个数。如果该行字符数大于 size-1,则读到 size-1 个字符时结束,并在最后补充' \0'; 如果该行字符数小于等于 size-1,则读取所有字符,并在最后补充 '\0'。即,每次最多读取 size-1 个字符。

stream 为文件结构指针。

返回: 非 NULL:成功,读取到的字符串,即参数 string 的值;

NULL:失败或读到文件结尾。必须通过 feof()函数或者 ferror()函数来判断是错误还是到文件结尾了

fgets 读取一行字符时,保留行尾的换行符。

fputs 不会在行尾自动添加换行符,但是 puts 会在标准输出流中自动添加一换行符。

字符串读写函数

原型:int fputs(char * string, FILE * stream);

功能:用于将指定的字符串写入到文件流中,缓冲区 string 中保存的是以'\0'结尾的字符串,fputs 将该字符 串写入文件 stream,但并不写入结尾的'\0'。与 fgets 不同的是,字符串中可以有'\n'也可以没有'\n'。

参数:

string 为将要写入的字符串

stream 为文件流指针

返回:>0 成功返回非负数,失败返回 EOF。 

字符串读取函数实例:

示例 1:测试 data.in 文件中读取最多少于一行的字符以及多于 1 行的字符的效果。 

//测试时候先自己创建 data.in,并且 输入测试内容
#include <stdio.h>
int main()
{FILE * pFile;char buf [100];pFile = fopen ("data.in" , "r");if (pFile == NULL){perror ("Error opening file");
}printf("-6------------------------\r\n");if ( fgets (buf , 6 , pFile) != NULL )puts (buf);//注意,这里没有移动文件指针,接着上面的位置读取printf("-50------------------------\r\n");if ( fgets (buf , 50 , pFile) != NULL )puts (buf);fclose (pFile);return 0;
}

7、文件定位

文件定位指读取或设置文件当前读写点,所有的通过文件指针读写数据的函数,都是从文件的当前读写点读 写数据的。

常用的函数有:

#include

int feof(FILE * stream); //通常的用法为 while(!feof(fp))

int fseek(FILE *stream, long offset, int whence);//设置当前读写点到偏移 whence 长度为 offset 处 long ftell(FILE *stream); //用来获得文件流当前的读写位置

void rewind(FILE *stream); //把文件流的读写位置移至文件开头 fseek(fp, 0, SEEK_SET);

feof 判断是否到达文件末尾的下一个(注意到达文件末尾之后还会做一次)

fseek 设置当前读写点到偏移 whence 长度为 offset 处,whence 可以是:

SEEK_SET (文件开头 0)

SEEK_CUR (文件当前位置

SEEK_END (文件末尾 2)

ftell 获取当前的读写点

rewind 将文件当前读写点移动到文件头

实例:

#include <stdio.h>
int main()
{char buf[50] = {'h','e','l','l','o'};FILE *p;p = fopen("a.txt", "r+b");fwrite(buf, 1, 5, p);
char buf1[50] = {0};fseek(p, 0, SEEK_SET);fread(buf1, 1, 5, p);printf("buf1:%s\n", buf1);fclose(p);return 0;
}

 标准输入输出流

系统为每个进程预先打开了三个特殊的文件,对应的三个文件指针分别为:stdin(标准输入)、stdout(标准输 出)、stderr(标准出错)。定义在头文件中。

在进程一开始运行,就自动打开了三个对应设备的文件,它们是标准输入、输出、错误流,分别用全局文件 指针 stdin、stdout、stderr 表示,它们都是 FILE *类型。stdin 具有可读属性,缺省情况下是指从键盘的读取输入, stdout 和 stderr 具有可写属性,缺省情况下是指向屏幕输出数据。

 实例:操作stdin,stdout,stderr以及缓冲效果

#include <stdio.h>
int main(void)
{char szBuf[1024];printf("Input string:"); fread(szBuf, 1, 5, stdin);printf("stdout--------------------\r\n"); fwrite(szBuf, 1, 5, stdout);printf("stderr--------------------\r\n"); fwrite(szBuf, 1, 5, stderr);printf("--------------------\r\n"); //演示缓冲效果,上面如果输入超过 5 字符,超过部分会流在缓冲中,下次会读到fread(szBuf, 1, 1, stdin);fwrite(szBuf, 1, 1, stdout);return 0;
}

8、标准目录文件

获取当前工作目录getcwd函数

原型:char *getcwd(char *buf, size_t size);

头文件:#include

功能:getcwd()会将当前工作目录的绝对路径复制到参数 buffer 所指的内存空间中,参数 size 为 buffer 的空间 大小。

参数: buf::存放工作路径缓冲区指针 size:size 为 buf 的空间大小

补充说明:

  1.  buf 所指的内存空间要足够大,则当前路径被复制到 buf 中
  2. 当前工作目录绝对路径的字符串长度超过参数 size 大小,则回值 NULL,errno 的值则为 ERANGE。
  3. buf 为 NULL,getcwd()会依参数 size 的大小自动配置内存(使用 malloc()),
  4. buf,size 都为 0,则 getcwd()会依工作目录绝对路径的字符串长度来决定所配置的内存大小,进程可以

在使用完此字符串后自动利用 free()来释放此空间。所以常用的形式:getcwd(NULL, 0); 返回值:成功则返回当前工作目录字符串指针,失败返回 NULL。

改变目录chdir函数

原型:int chdir(const char *path);

头文件:#include

功能:修改当前工作路径,相当于 cd

参数:path 新工作路径

返回: 0:成功; -1:

失败,并且把失败错误码保存在全局变量 erron 中

实例:

#include<unistd.h>
main()
{
chdir("/tmp");
printf("current working directory: %s\n",getcwd(NULL,0));
}

 改变目录或文件的访问权限chrmod函数

原型:int chmod(const char* path, mode_t mode); /

头文件:#include

功能:修改一个目录或文件的访问权限

参数:path 目录或文件路径字符串指针

mode:使用数字表示的权限值,mode 形如:0777

创建目录 mkdir 函数

原型:int mkdir(const char *pathname, mode_t mode); //创建目录,

mode 是目录权限,

头文件: #include #include #include

功能:创建一个指定权限的目录

删除目录 rmdir 函数

原型为: int rmdir(const char *pathname);

 打开目录

原型:DIR *opendir(const char *name); //打开一个目录

头文件: #include #include

功能:打开一个目录

返回:非 NULL:成功打开的目录流,NULL:打开失败

重定位到目录 rewinddir 函数

void rewinddir(DIR *dir); //重新定位到目录文件的头部

设置目录流目前的读取位置

void seekdir(DIR *dir,off_t offset);//用来设置目录流目前的读取位置

获得目录流当前的读取位置 telldir 函数

off_t telldir(DIR *dir); //返回目录流当前的读取位置

关闭目录 closedir 函数

int closedir(DIR *dir); //

读取目录信息的步骤为: 用 opendir 函数打开目录;

使用 readdir 函数迭代读取目录的内容,如果已经读取到目录末尾,又想重新开始读,则可以使用 rewinddir 函数将文件指针重新定位到目录文件的起始位置;

用 closedir 函数关闭目录 opendir()用来打开参数 name 指定的目录,并返回 DIR*形态的目录流,和文件操作函数 open()类似,接下来 对目录的读取和搜索都要使用此返回值。函数失败则返回 NULL;

readdir()函数用来读取目录的信息,并返回一个结构体指针,该指针保存了目录的相关信息。有错误发生或 者读取到目录文件尾则返回 NULL;dirent 结构体如下:

struct dirent
{
ino_t d_ino; /* inode number(此目录进入点的 inode) */
off_t d_off; /* offset to the next dirent(目录开头到进入点的位移 */
unsigned short d_reclen; /* length of this record(目录名的长度) */
char d_name[256]; /* filename(文件名) */
};

 seekdir()函数用来设置目录流目前的读取位置,再调用 readdir()函数时,便可以从此新位置开始读取。参数 offset 代表距离目录文件开头的偏移量。 telldir()函数用来返回目录流当前的读取位置。

实例:

#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
int main(int argc, char * argv[])
{
struct dirent * pDirInfo;
DIR * pDir;
if (argc < 2)
pDir = opendir(".");
else
pDir = opendir(argv[1]);
if (NULL == pDir)
{
perror("open dir fail!");
return -1;
}
while ((pDirInfo = readdir(pDir)) != NULL)
printf("%s\n", pDirInfo->d_name);
closedir(pDir);
return 0;
}

9、非缓冲IO文件操作

文件描述符

一个程序(进程)可以在运行的过程中同时打开多个文件,每个程序运行起来后,系统中就有一个记录表专门 记录这个程序打开的各个文件。每打开一个文件,记录表就会用一个新的结构体变量来保存这个文件的相关信息。 如果打开多个文件,记录表中就会有多个这样的结构体变量分别保存多个文件的相关信息,它们构成了一个结构 体数组,而数组的每一个元素的下标就是所谓的文件描述符。 所以文件描述符是一个较小的非负整数(0—1023),它代表记录表的一项,即上面说的数组中的某个元素的 下标。通过文件描述符和一组基于文件描述符的文件操作函数,就可以实现对文件的打开、关闭、读写、删除等 操作。常用基于文读、写、创建、文件描述符的函数有 open(打开)、creat(创建)、close(关闭)、read(读取)、 write(写入)、ftruncate(改变文件大小)、lseek(定位)、fsync(同步)、fstat(获取文件状态)、fchmod(权限)、 flock(加锁)、fcntl(控制文件属性)、dup(复制)、dup2、select 和 ioctl。基于文件描述符的文件操作并非 ANSI C(标准 C)的函数,而是 Linux 的系统调用,即 Linux 下的 API 函数。 如果不清楚某个函数的具体实现形式,可以通过下面的方式查询 man 函数名,即可查看该函数的帮助信息。 如果要复制里面的内容,按 Ctrl+Insert 键,再粘贴的话用:Shift+Insert 键。

打开、创建、关闭文件

open 和 creat 都能打开和创建文件,原型为 #include //头文件 #include #include int open(const char *pathname, int flags); //文件名 打开方式 int open(const char *pathname, int flags, mode_t mode);//文件名 打开方式 权限 int creat(const char *pathname, mode_t mode); //文件名 权限 //现在已经不常用了 creat 函数等价于open(pathname,O_CREAT|O_TRUNC|O_WRONLY,mode); int close(int fd);//fd 表示文件描述符 open 和 creat 函数出错时返回-1,成功则返回一个整数,这个整数就是和这个打开的文件相对应的文件描述 符。通过这个返回的文件描述符我们可以对这个文件进行读写等各种操作。 相关参数如下: flags 和 mode 都是一组掩码的合成值,flags 表示打开或创建的方式,mode 表示文件的访问权限。 对于 open 函数来说,第三个参数 mode 仅当创建新文件时(即使用了 O_CREAT 时)才使用,即只有在建 立新文件时才会生效,用于指定文件的访问权限位。如果打开一个已有的文件,但是又使用了第三个参数指定了 权限,那第三个参数将不会生效,等于没有。

 

 mode 的可选项有:

  1. S_IRWLRY 00700 权限,代表该文件所有者具有可读、可写及可执行的权限。
  2. S_IRUSR 或 S_IREAD,00400 权限,代表该文件所有者具有可读取的权限。
  3. S_IWUSR 或 S_IWRITE,00200 权限,代表该文件所有者具有可写入的权限。
  4. S_ILRYSR 或 S_IEXEC,00100 权限,代表该文件所有者具有可执行的权限。
  5. S_IRWXG 00070 权限,代表该文件用户组具有可读、可写及可执行的权限。
  6. S_IRGRP 00040 权限,代表该文件用户组具有可读的权限。
  7. S_IWGRP 00020 权限,代表该文件用户组具有可写入的权限。
  8. S_IXGRP 00010 权限,代表该文件用户组具有可执行的权限。
  9. S_IRWXO 00007 权限,代表其他用户具有可读、可写及可执行的权限
  10. S_IROTH 00004 权限,代表其他用户具有可读的权限 S_IWOTH 00002 权限,代表其他用户具有可写入的权限。 S_IXOTH 00001 权限,代表其他用户具有可执行的权限。

读写文件

读写文件的函数原型为:

#include ssize_t read(int fd, void *buf, size_t count);//文件描述词 缓冲区 长度

ssize_t write(int fd, const void *buf, size_t count);

对于 read 和 write 函数,出错返回-1,读取完了之后,返回 0, 其他情况返回读写的个数

实例:

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{int fd;char buf[32] = {0};fd = open("a.txt", O_RDWR);read(fd, buf, 6);printf("%s\n", buf);strcpy(buf, "hello");write(fd, buf, 6);close(fd);return 0;
}

改变文件大小

#include int ftruncate(int fd, off_t length);

函数 ftruncate 会将参数 fd 指定的文件大小改为参数 length 指定的大小。

参数 fd 为已打开的文件描述词,而 且必须是以写入模式打开的文件。如果原来的文件大小比参数 length 大,则超过的部分会被删去。

返回值 执行成功则返回 0,失败返回-1。

实例:

int main()
{int fd = open("a.txt", O_WRONLY);ftruncate(fd, 1000);close(fd);return 0;
}

文件定位

函数 lseek 将文件指针设定到相对于 whence,偏移值为 offset 的位置 #include #include off_t lseek(int fd, off_t offset, int whence);//fd 文件描述词 whence 可以是下面三个常量的一个 SEEK_SET 从文件头开始计算 SEEK_CUR 从当前指针开始计算 SEEK_END 从文件尾开始计算 利用该函数可以实现文件空洞(对一个新建的空文件,可以定位到偏移文件开头 1024 个字节的地方,在写 入一个字符,则相当于给该文件分配了 1025 个字节的空间,形成文件空洞)通常用于多进程间通信的时候的共 享内存。

 

int main()
{int fd = open("c.txt", O_WRONLY | O_CREAT);lseek(fd, 1024, SEEK_SET);write(fd, "a", 1);close(fd);return 0;
}

相关文章:

嵌入式 Linux 文件IO操作

目录 Linux 文件操作 1 Linux 系统环境文件操作概念 2 缓冲 IO 文件操作 1 文件的创建&#xff0c;打开与关闭 fopen 函数函数 2 freopen 函数 3、fdopen函数 4、fclose函数 5、格式化读写 6、单个字符读写 7、文件定位 8、标准目录文件 9、非缓冲IO文件操作 Linux 文…...

植物大战 二叉搜索树——C++

这里是目录标题二叉排序树的概念模拟二叉搜索树定义节点类insert非递归Finderase(重点)析构函数拷贝构造(深拷贝)赋值构造递归FindRInsertR二叉搜索树的应用k模型KV模型二叉排序树的概念 单纯的二叉树存储数据没有太大的作用。 搜索二叉树作用很大。 搜索二叉树的一般都是用…...

[MatLab]矩阵运算和程序结构

一、矩阵 1.定义 矩阵以[ ]包含&#xff0c;以空格表示数据分隔&#xff0c;以&#xff1b;表示换行。 A [1 2 3 4 5 6] B 1:2:9 %1-9中的数&#xff0c;中间是步长(不能缺省) C repmat(B,3,2) %将B横向重复2次&#xff0c;纵向重复2次 D ones(2,4) …...

【Leedcode】栈和队列必备的面试题(第四期)

【Leedcode】栈和队列必备的面试题&#xff08;第四期&#xff09; 文章目录【Leedcode】栈和队列必备的面试题&#xff08;第四期&#xff09;一、题目二、思路图解1.声明结构体2.循环链表开辟动态结构体空间3.向循环队列插入一个元素4.循环队列中删除一个元素5. 从队首获取元…...

Windows Server 2016搭建文件服务器

1&#xff1a;进入系统在服务器管理器仪表盘中添加角色和功能。 2&#xff1a;下一步。 3&#xff1a;继续下一步。 4&#xff1a;下一步。 5&#xff1a;勾选Web服务器(IIS) 6&#xff1a;添加功能。 7&#xff1a;下一步。 8&#xff1a;下一步。 9&#xff1a;下一步。 10&a…...

零基础学SQL(十一、视图)

目录 前置建表 一、什么是视图 二、为什么使用视图 三、视图的规则和限制 四、视图的增删改查 五、视图数据的更新 前置建表 CREATE TABLE student (id int NOT NULL AUTO_INCREMENT COMMENT 主键,code varchar(255) NOT NULL COMMENT 学号,name varchar(255) DEFAULT NUL…...

web,h5海康视频接入监控视频流记录三(后台node取流)

前端vue&#xff0c;接入ws视频播放 云台控制 &#xff0c;回放预览&#xff0c;都是需要调对应的海康接口。相当于&#xff0c;点击时&#xff0c;请求后台写好的接口&#xff0c;接口再去请求海康的接口 调用云台控制是&#xff0c;操作一次&#xff0c;不会自己停止&#x…...

网络安全从入门到精通:30天速成教程到底有多狠?你能坚持下来么?

毫无疑问&#xff0c;网络安全是当下最具潜力的编程方向之一。对于许多未曾涉足计算机编程的领域「小白」来说&#xff0c;深入地掌握网络安全看似是一件十分困难的事。至于一个月能不能学会网络安全&#xff0c;这个要看个人&#xff0c;对于时间管理不是很高的&#xff0c;肯…...

世界上最流行的编程语言,用户数超过Python,Java,JavaScript,C的总和!

世界上最流行的编程语言是什么&#xff1f; Python? Java? JavaScript? C&#xff1f;都不是&#xff0c;是Excel&#xff01;外媒估计&#xff0c;全球有12亿人使用微软的Office套件&#xff0c;其中估计有7.5亿人使用Excel&#xff01;可是Excel不就是能写点儿公式&#x…...

杂谈:created中两次数据修改,会触发几次页面更新?

面试题&#xff1a;created生命周期中两次修改数据&#xff0c;会触发几次页面更新&#xff1f; 一、同步的 先举个简单的同步的例子&#xff1a; new Vue({el: "#app",template: <div><div>{{count}}</div></div>,data() {return {count…...

原生JS实现拖拽排序

拖拽&#xff08;这两个字看了几遍已经不认识了&#xff09; 说到拖拽&#xff0c;应用场景不可谓不多。无论是打开电脑还是手机&#xff0c;第一眼望去的界面都是可拖拽的&#xff0c;靠拖拽实现APP或者应用的重新布局&#xff0c;或者拖拽文件进行操作文件。 先看效果图&am…...

Coredump-N: corrupted double-linked list

文章目录 问题安装debuginfo之后分析参数确定确定代码逻辑解决问题 今天碰到一例: #0 0xf7f43129 in __kernel_vsyscall () #1 0xf6942b16 in raise () from /lib/libc.so.6 #2 0xf6928e64 in abort () from /lib/libc.so.6 #3 0xf6986e8c in __libc_message () from /lib/li…...

5个好用的视频素材网站

推荐五个高质量视频素材网站&#xff0c;免费、可商用&#xff0c;赶紧收藏起来&#xff01; 1、菜鸟图库 视频素材下载_mp4视频大全 - 菜鸟图库 网站素材非常丰富&#xff0c;有平面、UI、电商、办公、视频、音频等相关素材&#xff0c;视频素材质量很高&#xff0c;全部都是…...

使用码匠连接一切|二

目录 Elasticsearch Oracle ClickHouse DynamoDB CouchDB 关于码匠 作为一款面向开发者的低代码平台&#xff0c;码匠提供了丰富的数据连接能力&#xff0c;能帮助用户快速、轻松地连接和集成多种数据源&#xff0c;包括关系型数据库、非关系型数据库、API 等。平台提供了…...

3.1.1 表的相关设计

文章目录1.表中实体与实体对应的关系2.实际案例分析3.表的实际创建4.总结1.表中实体与实体对应的关系 一对多 如一个班级对应多名学生&#xff0c;一个客户拥有多个订单等这种类型表的建表要遵循主外键关系原则&#xff0c;即在从表创建一个字段&#xff0c;此字段作为外键指向…...

Vue3 企业级项目实战:认识 Spring Boot

Vue3 企业级项目实战 - 程序员十三 - 掘金小册Vue3 Element Plus Spring Boot 企业级项目开发&#xff0c;升职加薪&#xff0c;快人一步。。「Vue3 企业级项目实战」由程序员十三撰写&#xff0c;2744人购买https://s.juejin.cn/ds/S2RkR9F/ 越来越流行的 Spring Boot Spr…...

Swagger2实现配置Header请求头

效果 实现 大家使用swagger肯定知道在代码中会写一个 SwaggerConfig 配置类&#xff0c;如果没有这个类swagger指定也用不起来&#xff0c;所以在swagger中配置请求头也是在这个 SwaggerConfig 中操作。 1、要实现配置请求头在配置swagger的Docket的bean实例中添加一个 globa…...

4-1 SpringCloud快速开发入门:RestTemplate类详细解读

RestTemplate类详细解读 RestTemplate 的 GET 请求 Get 请求可以有两种方式&#xff1a; 第一种&#xff1a;getForEntity 该方法返回一个 ResponseEntity对象&#xff0c;ResponseEntity是 Spring 对 HTTP 请求响应的封装&#xff0c;包括了几个重要的元素&#xff0c;比如响…...

【IDEA】【工具】幸福感UP!开发常用的工具 插件/网站/软件

IDEA 插件 CodeGlance Pro —— 代码地图 CodeGlance是一款非常好用的代码地图插件&#xff0c;可以在代码编辑区的右侧生成一个竖向可拖动的代码缩略区&#xff0c;可以快速定位代码的同时&#xff0c;并且提供放大镜功能。 使用:可以通过Settings—>Other Settings—&g…...

【蓝桥杯集训·每日一题】AcWing 1562. 微博转发

文章目录一、题目1、原题链接2、题目描述二、解题报告1、思路分析2、时间复杂度3、代码详解三、知识风暴宽搜BFS一、题目 1、原题链接 1562. 微博转发 2、题目描述 微博被称为中文版的 Twitter。 微博上的用户既可能有很多关注者&#xff0c;也可能关注很多其他用户。 因此&am…...

网络编程(Modbus进阶)

思维导图 Modbus RTU&#xff08;先学一点理论&#xff09; 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议&#xff0c;由 Modicon 公司&#xff08;现施耐德电气&#xff09;于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...

蓝桥杯 2024 15届国赛 A组 儿童节快乐

P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡&#xff0c;轻快的音乐在耳边持续回荡&#xff0c;小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下&#xff0c;六一来了。 今天是六一儿童节&#xff0c;小蓝老师为了让大家在节…...

Spring AI 入门:Java 开发者的生成式 AI 实践之路

一、Spring AI 简介 在人工智能技术快速迭代的今天&#xff0c;Spring AI 作为 Spring 生态系统的新生力量&#xff0c;正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务&#xff08;如 OpenAI、Anthropic&#xff09;的无缝对接&…...

Java面试专项一-准备篇

一、企业简历筛选规则 一般企业的简历筛选流程&#xff1a;首先由HR先筛选一部分简历后&#xff0c;在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如&#xff1a;Boss直聘&#xff08;招聘方平台&#xff09; 直接按照条件进行筛选 例如&#xff1a…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

Spring是如何解决Bean的循环依赖:三级缓存机制

1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间‌互相持有对方引用‌,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA

浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求&#xff0c;本次涉及的主要是收费汇聚交换机的配置&#xff0c;浪潮网络设备在高速项目很少&#xff0c;通…...

音视频——I2S 协议详解

I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议&#xff0c;专门用于在数字音频设备之间传输数字音频数据。它由飞利浦&#xff08;Philips&#xff09;公司开发&#xff0c;以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...

Netty从入门到进阶(二)

二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架&#xff0c;用于…...

Razor编程中@Html的方法使用大全

文章目录 1. 基础HTML辅助方法1.1 Html.ActionLink()1.2 Html.RouteLink()1.3 Html.Display() / Html.DisplayFor()1.4 Html.Editor() / Html.EditorFor()1.5 Html.Label() / Html.LabelFor()1.6 Html.TextBox() / Html.TextBoxFor() 2. 表单相关辅助方法2.1 Html.BeginForm() …...