嵌入式Linux系统编程学习之八基于文件指针的文件操作
文章目录
- 前言
- 一、文件的创建、打开与关闭
- 二、读写文件
- 三、文件定位
- 四、标准输入/输出流
- 五、目录操作
前言
对文件进行操作有打开文件、关闭文件、读写文件。
文件指针:每打开一个文件,就返回一个指针(FILE *类型),称为文件指针。这个指针指向了这个文件相关的所有信息,可以用这个指针代表这个文件,通过这个指针可以对这个打开的文件进行各种操作。
缓冲区:输入输出的数据并不是直接到电脑内存和显示器中,输入的数据先暂时存放在键盘缓冲区中,然后程序从该缓冲区中读取数据。输出的数据先暂时存放在输出缓冲区中,然后再把该数据输出到屏幕。
Linux中一切文件,对目录和设备的操作都是文件操作;文件分为普通文件、管道文件、目录文件、链接文件和设备文件。
普通文件:也称磁盘文件,能够进行随机数据存储;
管道文件:从一端发送数据,另一端接收数据的数据通道;
目录文件:包含了保存在目录中文件列表的简单文件;
设备文件:Linux下各种硬件设备都是文件,该类型的文件提供了大多数物理设备的接口。分为两种类型:字符型设备和块设备。字符型设备一次只能读出和写入一个字节的数据,包括调制解调器、终端、打印机、声卡及鼠标;块设备必须以一定大小的块来读出或写入数据,块设备包括CD-ROM、RAM驱动器和磁盘驱动器等。一般字符设备用于传输数据,块设备用于存储数据。
套接字文件:在Linux中,套接字也可以当作文件来进行处理。
一、文件的创建、打开与关闭
文件的创建、打开与关闭命令为:
#include <stdio.h> //头文件包含
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 close(FILE *stream);
fopen以mode方式打开或创建文件,成功将返回一个文件指针,失败返回NULL。
fopen创建的文件的访问权限将以0666与当前umask结合来确定。
mode的可选模式列:
模式 | 读 | 写 | 位置 | 截断原内容 | 创建 |
---|---|---|---|---|---|
rb | Y | N | 文件头 | N | N |
r+b | Y | Y | 文件头 | N | N |
wb | N | Y | 文件头 | Y | Y |
w+b | Y | Y | 文件头 | Y | Y |
ab | N | Y | 文件尾 | N | Y |
a+b | Y | Y | 文件尾 | N | Y |
fdopen函数用来打开某些不能直接用fopen方式打开的文件,如管道文件和网络套接字文件。
freopen打开一个特定的文件(由path指定),并将打开后的文件与指定的流(由fp指定)关联起来。一般用来将一个指定文件打开为一个指定的流:标准输入、标准输出、标准出错。
在Linux系统中,mode中的’b’(二进制)可以去掉,但为了保持与其他系统的兼容性,建议保留。ab和a+b为追加模式,在此两种模式下,无论文件读写点定位到何处,在写数据时都将在文件末尾添加,所以比较适合多进程写同一个文件的情况下保证数据完整性。
二、读写文件
基于指针的读写函数较多,可分为数据块读写、格式化读写、单个字符读写、字符串读写。
数据块读写:
#include <stdio.h> //头文件包含
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite(void *ptr, size_t size, size_t nmemb, FILE *stream);
fread从文件流stream中读取nmemb个元素,写到ptr指向的内存中,每个元素具有size个字节。
fwrite从ptr指向的内存中读取nmemb个元素,写到文件流stream中,每个元素具有size个字节。
所有的文件读写函数都是从文件的当前读写点开始读写,读写完成后,当前读写点自动往后移动size *nmemb个字节。
代码如下(示例):
#include <stdio.h>
int main()
{char buf[50] = {'h','e','l','l','o'};FILE *p; //定义一个FILE结构体类型的指针p = fopen("a.txt", "r+b"); //p这个指针此时就和文件a.txt关联起来fwrite(buf, 1, 5, p); //把buf里面的内容写到p指向的文件中char buf1[50] = {0};fread(buf1, 1, 5, p);printf("buf1:%s\n", buf1);fclose(p); //关闭p代表的文件a.txtreturn 0;
}
格式化读写函数原型:
#include <stdio.h>
int printf(const char *format, ... );
int scanf(const char *format, ... );
int fprintf(FILE *stream, const char *format, ... );
int fscanf(FILE *stream, const char *format, ... );
int sprintf(char *str, const char *format, ... );
int sscanf(char *str, const char *format, ... );
以f开头的将格式化后的字符串写入到文件流stream中;
以s开头的将格式化后的字符串写入到字符串str中。
读:也就是输入,表示数据从其他地方传输到内存;
写:也就是输出,表示数据从内存传输到其他地方。
单个字符读写函数(一次读写一个字符):
#include <stdio.h>
int fgetc(FILE *stream);
int fputc(int c, FILE *stream);
int getc(FILE *stream);
int putc(int c, FILE *stream);
int getchar(void);
int putchar(int c);
fgetc从文件中读取一个字符,成功后返回这个字符,读完返回EOF,失败返回-1;
getchar和putchar从标准输入/输出流中读写数据,其他函数从文件流stream中读写数据。
字符串读写的原型为:
char *fgets(char *s, int size, FILE *stream);
int fputs(const char *s, FILE *stream);
int puts(const char *s);
char *gets(char *s);
fgets和fputs从文件流stream中读写一行数据;puts和gets从标准输入输出流中读写一行数据。
fgets可以指定目标缓冲区的大小,所以相对于gets安全,但是fgets调用时,如果文件中当前行的字符个数大于size,则下一次fgets调用时,将继续读取该行剩下的字符,fgets读取一行字符时,保留行尾的换行符。
fputs不会在行尾自动添加换行符,但是puts会在标准输出流中自动添加换行符。
三、文件定位
文件定位指读取或设置文件当前读写点,所有的通过文件指针读写数据的函数都是从文件当前读写点读写数据的。
常用函数:
#include <stdio>
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(文件当前位置1)
SEEK_END(文件末尾2)
ftell获取当前的读写点。
rewind将文件当前读写点移动到文件头。
四、标准输入/输出流
系统为每个进程预先打开了3个特殊的文件,对应的3个文件指针分别为:stdin(标准输入)、stdout(标准输出)、stderr(标准出错);定义在头文件<stdio.h>中。
stdin具有可读属性,默认情况下是指从键盘的读取输入,stdout和stderr具有可写属性,默认情况下是指像屏幕输出数据。
五、目录操作
改变目录或文件的访问权限为:
#include <sys/stat.h>
int chmod(const char *path, mode_t mode); //mode形如:0777
path参数指定的文件被修改为具有mode参数给出的访问权限。
获取、改变当前目录的原型为:
#include <unistd.h> //头文件
char *getcwd(char *buf, size_t size); //获取当前目录,相当于pwd命令
int chdir(const char *path); //修改当前目录,即切换目录,相当于cd命令
getcwd()函数将当前的工作目录绝对路径复制到参数buf所指的内存空间,参数size为buf的空间大小;在调用此函数时,buf所指的内存空间要足够大,若工作目录绝对路径的字符串长度超过参数size大小,则返回NULL,errno的值为ERANGE;若参数buf为NULL,getcwd()函数会依size的大小自动配置内存(使用malloc函数);若参数size也为0,则getcwd()函数会依工作目录绝对路径的字符串长度来决定所分配内存的大小,进程可以在使用完此字符串后自动利用free()函数来释放此空间;常用形式为"getcwd(NULL,0);"。
chdir()函数用来将当前的工作目录改成参数path所指的目录。
创建和删除目录的原型为:
#include <sys/stat.h> //头文件
#include <sys/types.h>
#include <unistd.h>
int mkdir(const char *pathname, mode_t mode); //创建目录,mode是目录权限
int rmdir(const char *pathname); //删除目录
获取目录信息的原型为:
#include <sys/types.h> //头文件
#include <dirent.h>
DIR *opendir(const char *name); //打开一个目录
struct dirent *readdir(DIR *dir); //读取目录的一项信息,并返回该项信息的结构体指针
void rewinddir(DIR *dir); //重新定位到目录文件的头部
void seekdir(DIR *dir, off_t offset); //用来设置目录流目前的读取位置
off_t telldir(DIR *dir); //返回目录流当前的读取位置
int closedir(DIR *dir); //关闭目录文件
读取目录信息的步骤为:
- 用opendir()函数打开目录;
- 使用readdir()函数迭代读取目录的内容,如果已经读取到目录末尾,又想重新开始都,则可以使用rewinddir()函数将文件指针重新定位到目录文件的起始位置;
- 用closedir()函数关闭目录。
opendir()函数用来打开参数name指定的目录,并返回DIR *形式的目录流,对目录的读取和搜索都要使用此返回值。失败返回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()函数用来返回目录流当前的读取位置。
嵌入式Linux系统编程学习之八基于文件指针的文件操作相关推荐
- 嵌入式Linux系统编程学习之二常用命令
嵌入式Linux系统编程学习之二常用命令 文章目录 嵌入式Linux系统编程学习之二常用命令 前言 一.常用命令 1.su(用户切换) 2.useradd(添加用户) 3.passwd(修改密码) 4 ...
- 嵌入式Linux系统编程学习之一目录结构
嵌入式Linux系统编程学习之一目录结构 文章目录 嵌入式Linux系统编程学习之一目录结构 前言 一.Linux目录结构 前言 Linux目录结构 一.Linux目录结构 /bin:存放Linux的 ...
- 嵌入式Linux系统编程学习之九基于文件描述符的文件操作
文章目录 前言 一.文件描述符 二.打开.创建和关闭文件 三.读写文件 四.改变文件大小 五.文件定位 六.原子操作 七.进一步理解文件描述符 八.文件描述符的复制 九.文件的锁定 十.获取文件信息 ...
- 嵌入式Linux系统编程学习之二十二内存映射
文章目录 前言 一.mmap函数 二.munmap函数 三.补充 前言 内存映射函数包括 mmap.munmap 和 msync,其原型为: #include <unistd.h>#i ...
- 嵌入式Linux系统编程学习之五gcc/g++编译器
文章目录 前言 一.gcc/g++编译过程 二.静态库和动态库 三.gcc警告和优化选项 1.gcc警告 2.gcc优化选项 前言 对于.c格式的C文件,可以采用gcc或g++编译,对于.cc.. ...
- 嵌入式Linux系统编程学习之四Shell编程
文章目录 前言 一.Shell变量 1.创建变量 2.引用变量 3.删除变量 4.设置变量为只读变量 5.显示上条命令执行结果或函数返回值 6.表达式计算 二.标准变量 三.特殊变量 四.变量赋值 五 ...
- 嵌入式Linux系统编程学习之三vi编辑器
文章目录 前言 一.插入文本 二.删除与修改 三.光标的移动 四.查找与替换 五.块操作 六.结束编辑 前言 在Linux下编程,使用编辑器vi(vim).gedit或Emacs,编译链接器gcc,调 ...
- 嵌入式Linux系统编程学习之二十一命名管道(FIFO)
文章目录 前言 一.创建.删除FIFO文件 1. 用函数创建和删除 FIFO 文件 2. 用命令创建和删除 FIFO 文件 二.打开.关闭FIFO文件 三.读写FIFO 前言 无名管道只能在有亲缘 ...
- 嵌入式Linux系统编程学习之三十三网络相关概念
文章目录 一.网络相关名词的概念 1.套接口 2.端口号 3.IP 地址 二.Socket 概念 三.Socket 类型 四.Socket 的信息数据结构 五.数据存储优先顺序的转换 六.地址转格式转 ...
最新文章
- LeetCode:144_Binary Tree Preorder Traversal | 二叉树的前序遍历 | Medium
- 竞赛中如何做特征工程
- vs中调试中的命令行参数
- springMVC如何接收和发送json数据对象
- GDI+中发生一般性错误的解决办法 from http://www.cnblogs.com/winzheng/archive/2008/12/23/1360440.html...
- 2020 年了,WPF 还有前途吗?
- Windows更新补丁下载、批量安装的几种方法
- 一个抓取豆瓣图书的开源爬虫的详细步骤
- 40岁的程序员还能找到工作吗_学会了Vue就能找到前端工作吗
- twisted学习资料
- nginx伪静态php如何配置文件,nginx实现thinkphp伪静态的配置例子
- Powershell————2、Powershell交互式
- 计算机网络 如何算 子网号,计算机网络的划分以及主机号子网号的计算方法
- 以太网交换机MAC地址表格式 IVL和SVL
- SCRCPY与Android操作流程(华为手机) 原创超详细
- 2023最新苹果APP上架App Store流程(超详细)
- Thor UI - 轻量简洁的免费开源移动端 UI 组件库,支持原生小程序和 uni-app
- 蓝牙解码格式哪个最好_让有源音箱飞起来,让汽车音响硬起来,飞傲BTR5蓝牙HiFi解码品评...
- SEO优化:自建站图片优化攻略
- android手电筒
热门文章
- 解决Hbase报错java.lang.IllegalStateException: The procedure WAL relies on the ability to hsync for....
- Vmware拓展虚拟机硬盘容量
- xadmin删除数据后出现ValueError报错
- java重载中this的作用_Java2:构造方法、方法重载和this关键字
- create显示中文乱码 qt_Ubuntu下Qt串口助手接收中文乱码问题
- python解析sql语句表名_python正则表达式匹配sql语句中的表名
- Spring Boot 导出Excel表格
- Unity枚举和字符串的相互转换
- WEB服务器技术名词
- hihocoder #1617 : 方格取数(dp)