一切皆文件

---Linux


  • 头文件 <stdio.h> 中定义了文件的相关操作
#include <stdio.h>

文件操作基本流程:

打开:fopen

相关操作

关闭:fclose

fopen函数原型:FILE *fopen(const char *filename, const char *mode)

fopen函数打开filename指定的文件, 并返回一个与之相关联的流。 如果打开操作失败,则返回 NULL

访问模式mode可以为下列合法值之一:

"r"          打开文本文件用于读

"w"         创建文本文件用于写, 并删除已经存在的内容(如果有的话)

"a"          追加, 打开或创建文本文件,并向文件末尾追加内容

"r+"        打开文本文件用于更新(即读和写)

"w+"       创建文本文件用于更新, 并删除已经存在的内容(如果有的话)

"a+"        追加, 打开或创建文本文件用于更新, 写文件时追加到文件末尾

ps:如果在上述访问模式之后加上 b , 如 "rb" 或 "w+b" 等,则表示对二进制文件进行操作

fclose函数原型:int fclose(FILE *fp)

fclose函数的功能是关闭 fp 指向的文件    正常关闭返回0, 出错时返回非0

ps:文件操作结束不关闭文件可能丢失数据


  • 什么是文本文件?

在文本文件中数据是以字符形式呈现的,每个字符占用一个字节,而字节在计算机中又是以ASCII码来识别的

在存储文本文件时需要先将ASCII码转换为二进制的形式,然后进行存储

比如存储12的时候会按照字符  '1'  和  '2'  来存储

'1' 的ASCII码为49  转化为二进制为 00110001      '2' 的ASCII码为50  转化为二进制为 00110010

存储形式为   [00110001][00110010]

  • 什么是二进制文件?

二进制文件在存储数据时是直接以二进制的方式进行的, 存储方式与数据在内存中的存储方式相同

不需要进行转换

优点:不仅可以提高执行效率(比如从磁盘直接读取到内存不需要数据转换),还可以节约存储空间

比如存储char类型的数字12则会将其二进制数 00001100直接进行存储

存储i形式为   [00001100]


  • 文本文件和二进制文件的区别(Windows)

文本文件:写入的时候会将换行符 '\n'(ASCII: 10) 解析为回车符 '\r'(ASCII:13)'\n'(ASCII:10)

读取的时候又会将回车符 '\r'(ASCII:13)'\n'(ASCII:10)解析成换行符 '\n'(ASCII: 10)

二进制文件:原样写入读出

  • Linux系统下没有区别

  • 三个特殊的文件

stdin   :标准输入文件指针,系统分配为键盘

stdout :标准输出文件指针,系统分配为显示器

stderr  :标准错误输出文件指针,系统分配为显示器

在文件操作时,系统自动与3个标准设备文件联系,这3个文件无需打开和关闭

从文件中输入和向文件输出有两个对应函数:

fprintf

函数原型为

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

fscanf

函数原型为

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

例如 printf("hello world!\n");  等价于   fprintf(stdout, "hello world\n");

scanf("%d", &num);  等价于    fscanf(stdin, "%d", &num);

 #include <stdio.h>
#include <stdlib.h> int main()
{
int num;
fscanf(stdin, "%d", &num);
fprintf(stdout, "%d\n", num);
return ;
}

  • 文件型结构体

C语言提供“文件型”结构来标识记录待操作文件的信息,该结构体定义在头文件 stdio.h 中

形式为:

 typedef struct _iobuf
{
char *_ptr; /* 当前缓冲区内容指针 */
int _cnt; /* 缓冲区还有多少个字符 */
char *_base; /* 缓冲区的起始地址 */
int _flag; /* 文件流的状态,是否错误或者结束 */
int _file; /* 文件描述符 */
int _charbuf; /* 双字节缓冲,缓冲2个字节 */
int _bufsiz; /* 缓冲区大小 */
char *_tmpfname; /* 临时文件名 */
} FILE;

  • 文件基本操作

打开与关闭文件   fopen   fclose

 #include <stdio.h>
#include <stdlib.h>
#define FILE_NAME "./1.txt" /* 存在的文件 */
#define FILE_NAME_NO "./2.txt" /* 不存在的文件 */
int main()
{
FILE *fp = fopen(FILE_NAME, "r");
if(!fp){
perror("|open file failed");
return ;
}
printf("|open the file %s successfully\n", FILE_NAME);
int i = fclose(fp); /*关闭成功返回 0*/
printf("|%d\n", i); FILE *fp_no = fopen(FILE_NAME_NO, "r");
if(!fp_no){
perror("|open file failed");
return ;
}
printf("|open the file %s successfully\n", FILE_NAME_NO);
int j = fclose(fp_no);
printf("|%d\n", j);
return ;
}

输出

|open the file ./1.txt successfully
|0
|open file failed: No such file or directory

字符读写函数   fgetc   fputc

函数原型

 int    fgetc (FILE *);

 int    fputc (int, FILE *);

 #include <stdio.h>
#include <stdlib.h>
#define FILE_NAME "./1.txt" /* 存在的文件 */
int main()
{
FILE *fp = fopen(FILE_NAME, "r");
if(!fp){
perror("|open file failed");
return ;
}
printf("|open the file %s successfully\n", FILE_NAME);
char c = fgetc(fp);
printf("|%c\n", c);
fclose(fp);
return ;
}

输出

|open the file ./1.txt successfully
|h
 #include <stdio.h>
#include <stdlib.h>
#define FILE_NAME "./2.txt" /* 不存在的文件 */
int main()
{
FILE *fp = fopen(FILE_NAME, "w");
if(!fp){
perror("|open file failed");
return ;
}
printf("|open the file %s successfully\n", FILE_NAME);
fputc('h', fp);
fclose(fp);
return ;
}

新建了 2.txt文件 并写入一个字符 h

后续的函数相关操作类似,列出了函数原型,不举代码示例啦(偷懒ing)


字符串读写函数  fgets      fputs

函数原型

 int    fputs (const char *, FILE *);

 char * fgets (char *, int, FILE *);

格式化读写函数   fprintf     fscanf

函数原型

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

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

数据块读写函数   fread      fwrite

函数原型

 size_t fread (void *, size_t, size_t, FILE *);

 size_t fwrite (const void *, size_t, size_t, FILE *);

这两个函数用于读写数据块,成功返回 块数, 出错或到文件尾返回 0

第一个参数:  指向要输入/输出数据块的首地址的指针

第二个参数:  每个要读/写的数据块的大小(字节数)

第三个参数:   要读/写的数据块的个数

第四个参数:   要读/写的文件指针

fread 和 fwrite 函数一般用于 数组  结构体等块的读写(多为二进制形式)

比如

 #include <stdio.h>
#include <stdlib.h>
#define FILE_NAME "./3.txt" /* 不存在的文件 */ int main(){ int num[] = {};
for(int i = ; i < ; ++i){
num[i] = i;
}
FILE *fp = fopen(FILE_NAME, "w+b");
fwrite(num, sizeof(int), , fp);
printf("指针到达:%d\n", (int)ftell(fp));
rewind(fp);
printf("指针到达:%d\n", (int)ftell(fp));
int newnum[] = {};
fread(newnum, sizeof(int), , fp);
for(int i = ; i < ; ++i){
printf(" %d", newnum[i]);
}
printf("\n");
fclose(fp);
return ;
}

得到 3.txt文件 内容:

可以看到一个int类型占有4个字节,并且存储方式是低位在前高位在后

输出结果:


判断文件是否结束    feof

函数原型

int feof (FILE *);

feof函数用来判断文件是否结束, 文件结束返回一个 非0值, 未结束则返回 0


文件出错检验         ferror

函数原型

int ferror (FILE *);

ferror函数用来测试文件是否出错, 未出错返回 0, 出错返回一个 非0值


文件定位       rewind    fseek   ftell

函数原型

 int    fseek (FILE *, long, int);  /*根据参考位置灵活移动指针到目的地*/

 long   ftell (FILE *);             /*用来告诉我指针距离文件头的字符数*/

 void   rewind (FILE *);            /*将指针重新移动到文件头*/

其中 fseek函数第一个参数操作的文件指针(fp), 第二个参数是偏移量(offset) 第三个参数是参考点:0---文件开始    2---文件末尾   1---当前位置


刷新缓冲区    fflush

函数原型

int    fflush (FILE *);

对于输出流来说, fflush函数将已经写到缓冲区但尚未写入文件的所有数据写到文件中

对输入流来说, 其结果是未定义的

如果在写的过程中发生错误,则返回EOF, 否则返回 0, fflush(NULL)将清洗所有的输出流


文件删除      remove

函数原型

int    remove (const char *);

remove函数删除指定的文件, 操作成功返回 0, 操作失败返回一个 非0值


文件重命名    rename

函数原型

int    rename (const char *, const char *);

修改文件名成功返回 0 , 操作失败返回 非0值


创建临时文件    tmpfile

函数原型

FILE * tmpfile (void);

tmpfile函数以 "wb+" 模式创建一个临时文件(二进制的形式-->临时文件当然读写更快),该文件在被关闭或程序正常结束时将被自动删除

创建操作成功 函数返回一个流(文件的指针), 创建文件失败返回NULL


创建一个临时文件名   tmpnam

函数原型

char * tmpnam (char *);

tmpnam函数创建一个与现有文件名不同的字符串,并返回一个指向一内部静态数组的指针,tmpnam(s)函数把创建的字符串保存到数组s中,并将它作为函数返回值返回

要注意的是数组s要具有足够的空间来存储这个文件名字符串

示例

 #include <stdio.h>

 int main()
{
char s[] = {};
tmpnam(s);
printf("%s\n", s);
return ;
}

输出

\s804.

这是一个随机的文件名(只要不与现有的冲突就OK)


后记:

-- 在进行文件操作的时候根据情况选择合适的读写方式以及读写格式

-- 要灵活使用 feof    fflush (!!!!切记缓冲问题)    ftell      fseek     rewind     等函数

-- 文件使用结束切记 fclose 关闭文件, 避免出错

文件基本操作 (C语言)的更多相关文章

  1. java之文件基本操作

    java之文件基本操作 1 使用 BufferedReader 在控制台读取字符 public static void readChar() throws IOException{ char c; I ...

  2. 基于gSOAP使用头文件的C语言版web service开发过程例子

    基于gSOAP使用头文件的C语言版web service开发过程例子 一服务端 1 打开VS2005,创建一个工程,命名为calcServer. 2 添加一个头文件calc.h,编辑内容如下: 1// ...

  3. Linux - 文件基本操作管理

    文件基本操作管理   复制文件和目录 格式: Cp 源文件(文件夹) 新目标文件名(文件夹) 相同目录下,指定文件名. 不同目录下,不需要指定文件名. 参数: –r:递归复制整个目录树. –v:再复制 ...

  4. (大数据工程师学习路径)第一步 Linux 基础入门----目录结构及文件基本操作

    Linux 目录结构及文件基本操作 介绍 1.Linux 的文件组织目录结构. 2.相对路径和绝对路径. 3.对文件的移动.复制.重命名.编辑等操作. 一.Linux 目录结构 在讲 Linux 目录 ...

  5. Linux 01 Liunx目录结构及文件基本操作

    Linux目录结构及文件基本操作 1.Linux的文件组织目录结构(遵循FHS标准) FHS(Filesystem Hierarchy Standard)标准:多数Linux版本采用这种文件组织形式, ...

  6. Linux 目录结构及文件基本操作

    Linux 目录结构及文件基本操作 实验介绍 1.Linux 的文件组织目录结构. 2.相对路径和绝对路径. 3.对文件的移动.复制.重命名.编辑等操作. 一.Linux 目录结构 在讲 Linux ...

  7. NO.4day LINUX centos 文件基本操作

    LINUX centos 文件基本操作 1 LINUX简介 Linux的定义:Linux是一套免费使用和自由传播的类Unix操作系统,是一个基于POSIX和UNIX的多用户.多任务.支持多线程和多CP ...

  8. 实验楼学习linux第一章第四节linux目录结构及文件基本操作

    linux目录结构及文件基本操作 常用命令 切换目录 cd 当前目录 . 上一级目录 .. (.和..开头的都是隐藏文件) 查看隐藏文件 ls -a 上一级所在目录 - 当前用户home目录 ~ 获取 ...

  9. 从零开始的Python学习Episode 7——文件基本操作

    文件基本操作 一.打开文件 f = open('11','r')#open('file path','mode') 创建一个文件对象 文件有多种打开模式: 1. 'r':新建一个文件对象以只读方式打开 ...

随机推荐

  1. 【uoj34】 多项式乘法

    http://uoj.ac/problem/34 (题目链接) 题意 求两个多项式的乘积 Solution 挂个FFT板子. 细节 FFT因为要满足$n$是$2$的幂,所以注意数组大小. 代码 // ...

  2. Libre 6005 「网络流 24 题」最长递增子序列 / Luogu 2766 最长递增子序列问题(网络流,最大流)

    Libre 6005 「网络流 24 题」最长递增子序列 / Luogu 2766 最长递增子序列问题(网络流,最大流) Description 问题描述: 给定正整数序列x1,...,xn . (1 ...

  3. 函数和常用模块【day04】:内置函数分类总结(十一)

    重点掌握 字符串格式化format() 字符串格式化百分号 判断 转换 数据类型 帮助信息 map和filter()函数 局部变量全局变量 计算内置函数 常用内置函数(其他) 后续会讲 不常用

  4. [转]Python numpy函数hstack() vstack() stack() dstack() vsplit() concatenate()

    Python numpy函数hstack() vstack() stack() dstack() vsplit() concatenate() 觉得有用的话,欢迎一起讨论相互学习~Follow Me ...

  5. bzoj千题计划272:bzoj4557: [JLoi2016]侦察守卫

    http://www.lydsy.com/JudgeOnline/problem.php?id=4557 假设当前到了x的子树,现在是合并 x的第k个子树 f[x][j] 表示x的前k-1个子树该覆盖 ...

  6. bzoj千题计划233:bzoj 1304: [CQOI2009]叶子的染色

    http://www.lydsy.com/JudgeOnline/problem.php?id=1304 结论1:根节点一定染色 如果根节点没有染色,选择其子节点的一个颜色,那么所有这个颜色的子节点都 ...

  7. poj 1776 Task Sequences

    http://poj.org/problem?id=1776 题意: 有一个机器要完成N个作业, 给你一个N*N的矩阵, M[i][j]=1,表示完成第i个作业后不用重启机器,继续去完成第j个作业 M ...

  8. C++ map & set

    山东第六届ACM省赛B题 超时代码: #include<iostream> #include<cstdio> #include<string.h> #include ...

  9. Kubernetes之解决从k8s.gcr.io拉取镜像失败问题

    前言 因谷歌网络限制问题,国内的K8ser大多数在学习Kubernetes过程中因为镜像下载失败问题间接地产生些许失落感,笔者也因此脑壳疼,故翻阅资料得到以下解决方式: 在应用yaml文件创建资源时, ...

  10. Miller_Rabin 素数测试

    费马定理的逆定理几乎可以用来判断一个数是否为素数,但是有一些数是判断不出来的,因此,Miller_Rabin测试方法对费马的测试过程做了改进,克服其存在的问题. 推理过程如下(摘自维基百科): 摘自另 ...