Linux 文件流与目录流管理

2023-05-16

Linux 应用开发_04 文件流与目录流管理

本课目标

(1)编程目标:

(a)实现磁盘文件的拷贝操作。

(b)缓冲区类型对磁盘真正写入操作的影响。

(2)理解文件流操作以及缓冲区概念。

(3)掌握ansi c 文件流相关操作函数。

(4)理解与掌握目录流操作。

主要知识点

(1)流的基本原理及作用,与文件描述符的关系。标准输入输出流基本概念,文件流结构体。

(2)缓冲区类型以及缓冲区作用。如何修改缓冲区。setbuf,setvbuf

(3)文件流操作。

(4)流的效率与可移植性。

(5)目录流操作与编程。

课程内容

文件流概念

FILE *fp = fopen();

typedef struct _IO_FILE FILE;

struct _IO_FILE {

int _flags; /* High-order word is _IO_MAGIC; rest isflags. */

#define _IO_file_flags _flags

/* The following pointers correspond to the C++ streambufprotocol. */

/* Note: Tk uses the _IO_read_ptr and _IO_read_end fieldsdirectly. */

char* _IO_read_ptr; /* Current read pointer */

char* _IO_read_end; /* End of get area. */

char* _IO_read_base; /* Start of putback+get area. */

char* _IO_write_base; /* Start of put area. */

char* _IO_write_ptr; /* Current put pointer. */

char* _IO_write_end; /* End of put area. */

char* _IO_buf_base; /* Start of reserve area. */

char* _IO_buf_end; /* End of reserve area. */

/* The following fields are used to support backing upand undo. */

char *_IO_save_base; /* Pointer to start of non-currentget area. */

char *_IO_backup_base; /* Pointer to first validcharacter of backup area */

char *_IO_save_end; /* Pointer to end of non-current getarea. */

struct _IO_marker *_markers;

struct _IO_FILE *_chain;

int _fileno; //关联的文件描述符

#if 0

int _blksize;

#else

int _flags2;

#endif

_IO_off_t _old_offset; /* This used to be _offset butit's too small. */

#define __HAVE_COLUMN /* temporary */

/* 1+column number of pbase(); 0 is unknown. */

unsigned short _cur_column;

signed char _vtable_offset;

char _shortbuf[1];

/* char* _save_gptr; char* _save_egptr; */

_IO_lock_t *_lock;

#ifdef _IO_USE_OLD_IO_FILE

};

流是在用户空间在文件描述符基础上进行的封装,添加了如下信息,使功能更强。

(1)缓冲区

(2)读写位置。

流的一个重要提高效率的方法是使用缓冲区,将多次的系统调用合并成一次系统调用,节约执行的

时间。

流和缓冲区:

(1)全缓冲。只有当数据量达到某个限制后(不同的平台有差异4096),或者主动的要求刷新缓冲

区(fclose/fflush),才真正执行一次系统调用操作。常见的哪些流是全缓冲:文件流,即以fopen 打开的

文件。

(2)行缓冲。只有当数据量达到某个限制(128,1024)或者遇到换行,或者主动要求(fclose/fflush)

刷新缓冲区后,才真正执行一次系统调用操作。常见的是终端命令行。

printf(“step 1\n”);

printf(“step 2\n”);

(3)无缓冲。需要实时显示信息的,例如标准的错误输出。fprintf(stderr,);

默认的三个打开的文件对应的流

/* Standard streams. */

extern struct _IO_FILE *stdin; /* Standard input stream.*/

extern struct _IO_FILE *stdout; /* Standard outputstream. */

extern struct _IO_FILE *stderr; /* Standard error outputstream. */

如果要修改缓冲的类型或者自己指定对应缓冲区的位置。可以使用 setbuf,setvbuf

#include <stdio.h>

void setbuf(FILE *stream, char *buf);

void setbuffer(FILE *stream, char *buf, size_t size);

void setlinebuf(FILE *stream);

int setvbuf(FILE *stream, char *buf, int mode, size_tsize);

 

_IONBF unbuffered

_IOLBF line buffered

_IOFBF fully buffered

通过程序来验证缓冲区的问题:

文件流的操作:编程中用到的函数,ANSI C 库函数。open/read/write/close 是系统调用函数。

1.打开/关闭

fopen

fclose

FILE *fopen(const char *path, const char *mode);

第一个参数为打开文件的路径(字符串),第二参数为打开的方式(字符串)。

r:只读。open O_RDONLY

w:只读。 open->O_WRONLY|O_CREAT|O_TRUNC

a:追加。open->O_APPEND|O_CREAT|O_WRONLY

X+:可读可写。open O_RDWR

FILE *fdopen(int fd, const char *mode);//将一个文件描述符封装成一个流

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

使用完成后,全用flose 关闭这个流对象,期间会刷新流的缓冲区。

2、读写

一个字符一个字符的读写

fgetc/fputc

int fgetc(FILE *stream); //返回的是这个字符的sacii 值

int getc(FILE *stream); //类似于fgetc

int getchar(void);//从标准的输入流中读取一个字符。返回其Ascii 值

int ungetc(int c, FILE *stream);

int fputc(int c, FILE *stream); //将c 写入到stream流所指向的文件中

int putc(int c, FILE *stream);

int putchar(int c); //将c 字符写入到标准的输出流。

一行一行的读写

char *fgets(char *s, int size, FILE *stream);

//从stream 流中期望读取大小为 size 个byte 的字符串,存储在s 指向的内存空间中,返回字符的位

置。

int fputs(const char *s, FILE *stream);

将s 指向的内存空间字符串写入到stream流中,返回写入的数据量。

char *gets(char *s); //从标准的输入流读取一行。

int puts(const char *s); //将一行字符串写入到标准的输出流中。

任意的大小读写

fread/fwrite

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

期望从stream 流所指向的文件读取nmemb 个大小为size 的数据,并存储在ptr 所指向的内存空间

中。返回是真正读出的个数。

size_t fwrite(const void *ptr, size_t size, size_t nmemb,

FILE *stream);

将存储在ptr 开始的内存空间中 nmemb 个大小为size 的数据写入到stream 流所指向的文件。

强调一下,read 函数返回的和write 返回的值是真正读写的字节数,而fread/fwrite 返回的是真正读

写的个数。字节数= size* nmemb。

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

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

3. 文件流状态的检测和设置

(1)读写出错的状态:

void clearerr(FILE *stream);

int ferror(FILE *stream);

如果读写出错,ferror 返回非0 值,可以全用clearerr 函数清除这个错误。

(2)读写结束的状态:feof(stream);

int feof(FILE *stream);,如果流的读写位置已经在文件尾部,返回非0 值.

文件流的读写位置

在流读写相关函数操作流时,文件的读写位置会自动的跟着移动。

文件的读写位置有三个参考点

int fseek(FILE *stream, long offset, int whence);

long ftell(FILE *stream);//返回当前的读写位置距离文件头的字节数。

void rewind(FILE *stream); //将文件读写位置置到文件开头。

int fgetpos(FILE *stream, fpos_t *pos);

int fsetpos(FILE *stream, fpos_t *pos);

4. 写一个简单拷贝程序,从一个文件拷贝到另一个文件,分别用字节读,行读,任意大小读的方

式。

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

int main(int argc,char *argv[])//argv[1]:src file,argv[2]:dst file

{

if(argc!=3)

{

printf("pls usage:%s src_filedst_file\n",argv[0]);

exit(EXIT_FAILURE);

}

FILE *fp_src = fopen(argv[1],"r");

if(NULL == fp_src)

{

printf("fopen error\n");exit(EXIT_FAILURE);

}

FILE *fp_dst = fopen(argv[2],"w");

if(NULL == fp_dst)

{

printf("fopen dst error\n");exit(EXIT_FAILURE);

}

/*

char ch;

while(1)

{

ch = fgetc(fp_src);

if(feof(fp_src))

{

break;

}

fputc(ch,fp_dst);

}

char buf[128];

while(1)

{

memset(buf,'\0',128);

fgets(buf,127,fp_src);

fputs(buf,fp_dst);

if(feof(fp_src))

break;

}

fclose(fp_src);

fclose(fp_dst);

}

5. 流的格式化输入输出的问题

printf/scanf 这一类函数的实现相当的复杂。

int printf(const char *format, ...);

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

int sprintf(char *str, const char *format, ...);

int snprintf(char *str, size_t size, const char *format,...);

返回值:返回真正打印字符的字节数。

printf 是fprintf 的特例。

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

将列表中的数据以指定的格式format 写入到stream 所指向的流中。printffprintf(stdout,format….);

格式化串的标准格式:具体可以参阅手册。

%[标志 ] [最小字段宽度] .[精度 ] [参数长度] [转换类型]

标志

-:表示左对齐

+

空格

#

0

最小字段宽度表示输出数据最小宽度,如果不够,空格补充。

精度表示最少输出数据的位数,浮点数转为小数后最小位数,字符串转换后的最大字符数。

参数长度

hh

h

l

l

L

转换类型:

d

o

u

x

f

e

c

s

p

int scanf(const char *format, ...);是fscanf 的特例,fscanf(stdio,format,,)

int fscanf(FILE *stream, const char *format, ...);

int sscanf(const char *str, const char *format, ...);

可变参数为存放数据的地址列表。

format 串的格式是

%[*][最大宽度][转换类型]

[*]抑制转换,按这个格式输入但不存入后面的内存空间。

sprint/sscanf 将数据输入/输入到字符串中。

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux 文件流与目录流管理 的相关文章

  • 使用 cmake 和 opencv 对符号“gzclose”的未定义引用[关闭]

    Closed 这个问题是无法重现或由拼写错误引起 help closed questions 目前不接受答案 我尝试构建该项目 doppia https bitbucket org rodrigob doppia 但发生链接错误 我想这是一
  • 在大型文本文件中查找重复记录

    我在一台 Linux 机器 Redhat 上 并且有一个 11GB 的文本文件 文本文件中的每一行包含单个记录的数据 并且该行的前 n 个字符包含该记录的唯一标识符 该文件包含略多于 2700 万条记录 我需要验证文件中不存在具有相同唯一标
  • CMake:不要为链接中使用的单个库设置 rpath

    我想要做的是配置我的 CMakeLists 文件 以便在构建我的项目时 链接器使用驻留在我的构建树中的共享库 so 的副本来链接可执行文件 但不会在中设置 rpath链接的可执行文件 以便系统必须在加载程序请求时提供该库 具体来说 我想在构
  • Azure Nvidia 中的 apt-update 出现公钥错误

    我在 AZURE 上启动了 NVIDIA VM 并尝试使用进行更新sudo apt update但给出错误 Hit 2 http azure archive ubuntu com ubuntu focal InRelease Hit 3 h
  • 启动jetty服务器时出现NoClassDefFoundError

    我正在尝试在码头服务器中托管我的网络应用程序 spring 我将 war 文件复制到 jetty 服务器中的 webapp 文件夹中 我并不是想嵌入jetty服务器 而是试图在jetty内托管应用程序 如tomcat 我没有安装jetty
  • Bash 变量:区分大小写?

    Bash shell 脚本区分大小写吗 是可变的date与DATE 是的 它区分大小写 就像 UNIX 的其余部分一样 date and DATE是两个不同的变量 makefile and Makefile是两个不同的文件 h and H是
  • POSIX:FreeBSD 与 Linux 中的管道系统调用

    在 Linux 2 6 35 22 generic 中 man pipe指出 pipeline 创建一个管道 一个可用于进程间通信的单向数据通道 在 FreeBSD 6 3 RELEASE p5 中 man pipe指出 pipeline
  • Linux 缓冲区溢出环境变量

    我一直在审查不同类型的缓冲区溢出 并遇到了一个我不记得为什么会发生的问题 下面的代码是我尝试执行缓冲区溢出的程序 include
  • 将 -1 作为文件描述符传递给 mmap

    我对 FC17 Linux 中的 ls 命令进行了 strace 以下是输出 execve usr bin ls ls 48 vars 0 brk 0 0x27c1000 mmap NULL 4096 PROT READ PROT WRIT
  • 在 Ubuntu 上运行独立的 ASP.NET Core 应用程序

    我已经发布了一个 ASP NET Core 应用程序作为针对 Ubuntu 的独立应用程序 发布似乎工作正常 我已将这些文件复制到一台漂亮的 Ubuntu 机器上 现在 我如何运行我的应用程序 我的理解是 因为它是一个独立的 NET Cor
  • 为什么 Solaris 汇编器生成的机器代码与 GNU 汇编器在这里不同?

    我为 amd64 编写了这个小汇编文件 对于这个问题来说 代码的作用并不重要 globl fib fib mov edi ecx xor eax eax jrcxz 1f lea 1 rax ebx 0 add rbx rax xchg r
  • Linux 中如何获取内存修改通知

    在Linux的用户空间程序中 我通过从堆中分配来获取一块内存 然后将指针分发给在其他线程中运行的许多其他组件来使用 当上述内存被修改时我想收到通知 我当然可以开发一个自定义用户空间解决方案 供其他组件在尝试修改内存时使用 我的情况的问题是这
  • 当模式在范围内时使用 sed 打印范围?

    我有一个充满查询的日志文件 我只想查看有错误的查询 日志条目类似于 path to file executing query QUERY SIZE ROWS MSG DURATION 我想打印所有这些东西 但只有当MSG 包含一些有趣的内容
  • 安全地记住 bash 脚本中的 ssh 凭据[重复]

    这个问题在这里已经有答案了 假设我有一个 bash 脚本 它通过 ssh 在远程计算机上执行命令 Do something here ssh otheruser host command1 Do something else ssh oth
  • 远程 ssh 命令:第一个回显输出丢失

    我试图通过 ssh 1 liner 调用在远程机器上运行多个命令 方法是将它们指定为传递给 bash c 的分号分隔字符串 它适用于某些情况 但不适用于其他情况 看一下这个 Note the echo 1 output is lost ba
  • Linux 源代码中的哪个位置会识别特定的 USB 设备?

    我有一个特定的 USB 设备 我想检查其 Linux 驱动程序源代码 我的理解是 USB 驱动程序执行的第一步是注册自己能够处理具有特定供应商 ID 和产品 ID 的设备 就我而言 供应商 ID 是0BDA产品 ID 是8187 有了这些信
  • 无法在 R 中安装插入符号包(在我的 Linux 机器中)

    我在尝试在 R 中安装插入符号包时遇到以下错误 g error tmp Rtmp2Tos7n R INSTALL2e6e30153a74 nloptr nlopt 2 4 2 lib libnlopt cxx a No such file
  • Linux 的 gcc __attribute__((selectany)) 替代方案?

    我想知道是否有替代方案 attribute selectany 在Linux中 我想定义这样的东西 char a qwe zxc 并将其包含在许多链接在一起的 c 文件中 因此链接器将看到 a 的多个定义 因此不会链接 我读过这个属性 se
  • 使用无效命令进行 fork 会导致 valgrind 中的内存泄漏

    我有以下代码 它在分叉内执行无效命令 以下代码在 valgrind 中返回内存泄漏 include
  • 从 Java 读取 /dev/input/js0

    我正在尝试阅读 dev input js0来自Java 但我不断得到 java io IOException Invalid argument at java io FileInputStream read0 Native Method a

随机推荐

  • XTDrone 视觉SLAM环境配置

    基于XTDrone的视觉SLAM章节 xff0c 进行环境配置 中途遇到了一些问题 xff0c 一一解决后成功完成了 xff0c 记录该流程 一 遇到的问题与参考链接 XTDrone相关参考连接 xff1a 链接依赖安装教程 xff1a O
  • XTDrone 视觉惯性里程计(VIO)配置

    XTDrone 视觉惯性里程计 xff08 VIO xff09 配置 参考XTDron进行配置 xff0c 对于依赖的配置写成文档 xff0c 参考主要为 xff1a XTDrone Ceres Solver 2 0 0 1 下载2 0 0
  • ros realsense D435i摄像头配置

    ros realsense D435i摄像头配置 之前在ubunut18中配置了ROS环境 xff0c 现在需要在此基础上 xff0c 配置D435i相机的SDK和ROS包 一 参考 https github com IntelRealSe
  • 树莓派4B(ubuntu mate系统)使用d435i运行vins

    树莓派4B xff08 ubuntu mate系统 xff09 使用d435i运行vins 提示本文为随手笔记 xff0c 并不严谨 xff0c 可参考 xff1a 博客和博客进行配置 树莓派 ubuntu mate 20系统安装ros的步
  • 树莓派3B+增加虚拟内存

    普通ubuntu系统增加虚拟内存参考 xff1a https blog csdn net weixin 42405819 article details 117886557 编译opencv时 xff0c 卡在了91 不动 xff0c 按照
  • ROS主机从机设置

    ROS主机从机设置 在ROS基础上 xff0c 配置主机和从机 xff0c 实现主机和从机的话题联通 配置hosts 在主机和从机的 etc hosts文件中 xff0c 配置如下内容 xff08 也许主机只需要写入 master xff1
  • VINS、MAVROS等的坐标系统一(草稿,未得出明确结果)

    由于不同算法之间的坐标系不同 xff0c 导致计算的结果混乱 xff0c 该博客的目的是记录和统一不同算法之间的坐标系 xff0c 保证坐标系的统一 一 VINS算法 vins算法 xff0c 使用D435I相机 该坐标方向为 xff1a
  • ROS学习笔记9-创建ros消息和服务

    该节内容主要来自于官方文档的两个小节 xff1a 1 使用rosed来编辑 2 创建ros消息的服务 先来看rosed xff1a rosed rosed命令是rosbash的一部分 xff0c 使用rosed可以直接编辑包中的一个文件 x
  • CUAV RTK初步使用体验和感受

    记录使用RTK进行无人机定位并操作的使用体验 一 RTK定位设置 使用的是CUAV制作发售的RTK xff0c 型号为C9P xff0c 目前该产品已经下架 xff0c 上新了C9PS 并不需要太多的设置 xff0c 在飞控接入RTK后 x
  • 记录一次WIN11开机在登录页面循环的问题

    记录一次由于未进行win密码设置 xff0c 导致开机后卡在登录界面无法登录进去的问题 最后完美解决了 1 背景 开机后 xff0c 显示用户登录界面 xff0c 但是和以往不同 xff0c 没有了密码输入框 xff0c 只有一个 登录 按
  • Ubuntu中增加串口的缓冲区

    增加串口缓冲区 xff0c 用于尝试解决px4 ros中显示TX溢出的问题 以下大部分代码和内容均有CHATGPT生成 xff0c 代码已经通过验证 一 通信溢出问题 PX4和ROS的通信溢出可能是由于几个原因造成的 以下是一些建议 xff
  • GRBL代码使用与修改

    下载官方grbl代码 xff0c 并进行修改使其正确 1 问题 xff1a 购买了328p单片机 xff0c 购买了grbl的底板 xff0c 但是烧录之后无法正常使用 问题发现 xff1a 引脚错误了 xff0c 官方代码中的引脚需要修改
  • ubuntu使用rc.local开机自启USB设备读写权限

    无人机飞控为ACM0 xff0c 串口USB为USB0 xff0c 使用rc为其开机自启给与权限 大部分由chagpt生成 xff0c 已验证 首先 xff0c 创建一个新的 etc rc local 文件 xff08 如果尚不存在 xff
  • Friendlycore增加inodes数量

    背景 xff1a 为Nanopim1安装了core系统 xff0c tf卡大小64G xff0c 安装后正常扩展到了整个tf卡 xff0c 但是在安装hass的docker显示磁盘空间不够 xff0c 最终发现是inode被用完了 其ino
  • UORB

    转载地址 xff1a http blog arm so armteg pixhawk 183 0503 html Pixhawk 飞控 系统是基于ARM的四轴以上飞行器的飞行控制器 xff0c 它的前身是PX4 IMU xff0c Pixh
  • rCS启动脚本分析

    转载地址 xff1a http wellmakers com p 61 401 还有一篇很重要的文章 xff0c 讲述了整个系统的大致启动过程 xff1a http blog chinaunix net uid 29786319 id 43
  • PID通俗解释

    转载地址 xff1a http blog gkong com liaochangchu 117560 ashx PID是比例 积分 微分的简称 xff0c PID控制的难点不是编程 xff0c 而是控制器的参数整定 参数整定的关键是正确地理
  • Kali Linux中安装Xfce的步骤2-1

    Kali Linux默认安装的是桌面环境是Gnome xff0c 可以通过以下方法在Kali Linux中安装Xfce xff0c 从而修改其桌面环境 1 Xfce介绍 Xfce是XForms Common Enviroment的简写 其可
  • STM32CubeMX教程之简介及基本使用

    STM32CubeMX是意法半导体推出的图形化配置工具 xff0c 通过傻瓜化的操作便能实现相关配置 xff0c 最终能够生成C语言代码 xff0c 支持多种工具链 xff0c 比如MDK IAR For ARM TrueStudio等 尤
  • Linux 文件流与目录流管理

    Linux 应用开发 04 文件流与目录流管理 本课目标 1 编程目标 xff1a a 实现磁盘文件的拷贝操作 b 缓冲区类型对磁盘真正写入操作的影响 2 理解文件流操作以及缓冲区概念 3 掌握ansi c 文件流相关操作函数 4 理解与掌