嵌入式学习——Linux操作系统——文件编程—(1)
一、文件类型:文件操作:文本文件,mp3,jpeg,png ,mp4,avi文件:一组相关数据的有序集合文件名:这组相关数据的一个名称eg:hello.c --文件名linux里面对文件的处理:思想:一切皆文件ls -l文本文件目录摄像头话筒鼠标b -- block-- 块设备文件--- 硬盘 ---- ls -l /dev/sda。
一、文件类型:
文件操作:
文本文件,mp3,jpeg,png ,mp4,avi
文件:
一组相关数据的有序集合
文件名:
这组相关数据的一个名称
eg:
hello.c --文件名
linux里面对文件的处理:
思想:
一切皆文件
everything is file!
ls -l
文本文件
目录
摄像头
话筒
鼠标
b c d - l p s
b -- block -- 块设备文件 --- 硬盘 ---- ls -l /dev/sda
c -- character -- 字符设备文件 --- 鼠标 ---- ls -l /dev/input/
d -- directory -- 目录文件
- -- regular -- 普通文件
l -- link -- 软连接文件 --- 类似windows的快捷方式
p -- pipe -- 管道文件 --- 实现操作系统中 进程间的一些 信息交换(通信)
s -- socket -- 套接字文件 --- 网络的时候 (进程间的通信)
二、linux如何操作系统
write(1, "hello world\n", 12)
1 --- 屏幕 --- 标准输出
12 --- 表示输出数据字符个数
系统调用 --- 就是操作系统提供的函数
linux操作系统编程:
实现一个 用户程序
(1).库函数 --来实现
(2).系统调用

文件编程:
1.标准IO --- 库函数的方式
2.文件IO --- linux操作系统提供的 --系统调用了
标准IO库
1. printf/scanf/gets /getchar
#include <stdio> //std--io --- input & output
三、【操作文件的基本思路及框架】//凡是文件,都可从这个思路出发进行思考
文件操作三步骤:
1.打开
2.读写
3.关闭
比如:
在linux从摄像头中拍一张照片,保存下来。
//1.摄像头是一个设备文件
怎么找到这个设备在操作系统中的对应的 文件呢?
/dev/video0 --- 之类的!
标准IO库:
根据不同的操作系统了不同的函数接口来帮助我们实现想要的功能!
1.打开 -- fopen //FILE open
2.读写 -- getchar/putchar
gets / puts
fread / fwrite
3.关闭 -- fclose
(一)打开 -- fopen //FILE open
#include <stdio.h>
FILE* fopen(const char *path, const char *mode);
功能:
流打开函数 (打开文件,并关联到一个流)
参数:
@path --要打开的文件的文件名(字符串形式)
@mode --打开文件的操作模式
r ---打开文件做读操作
注意:
文件必须存在
r+ 打开文件做读写操作
注意:
文件必须存在
w 打开文件做写操作
注意:
如果文件已经存在,则会将文件截断为0
如果文件不 存在,则会创建一个新文件。
w+ 打开文件做读写操作
注意:
如果文件已经存在,则会将文件截断为0
如果文件不 存在,则会创建一个新文件。
a 打开文件做写操作
注意:
如果文件已经存在,则在文件末尾进行写入
如果文件不存在,则会创建一个新文件。
a+
打开文件做读写操作
注意:
如果文件已经存在,则在文件末尾进行写入
如果文件不存在,则会创建一个新文件。
r Open text file for reading. The stream is positioned at the beginning of the
file.
r+ Open for reading and writing. The stream is positioned at the beginning of the
file.
w Truncate file to zero length or create text file for writing. The stream is
positioned at the beginning of the file.
w+ Open for reading and writing. The file is created if it does not exist, other‐
wise it is truncated. The stream is positioned at the beginning of the file.
a Open for appending (writing at end of file). The file is created if it does not
exist. The stream is positioned at the end of the file.
a+ Open for reading and appending (writing at end of file). The file is created if
it does not exist. The initial file position for reading is at the beginning of
the file, but output is always appended to the end of the file.
返回值:
成功 FILE *
失败 NULL 并且 设置 errno 表明错误原因
练习:
用fopen实现一个touch的功能!






FIFE *:表示已经打开的文件
(二)读写操作
标准IO
fgetc/fputc: 按字符读写
fgets/fputs: //按字符读写 fgetc - fputc
(1)//读
fgetc
int fgetc(FILE *stream);
功能:
从流中读取一个字符
参数:
stream:文件流指针
返回值:
成功返回读到字符的ASCII码值
读到文件末尾返回EOF
失败返回EOF -1
c= fgetc(stdin);
fputc(c,stdout);
获取键盘上面的输入,显示到屏幕。。
注意:文件中不存在EOF,文件结束的标志是

默认的流指针:
stdin --- 标准输入
stdout --- 标准输出
stderr --- 标准出错 --- 屏幕

实现cat的功能:

(2)fputc
//写
fputc
int fputc(int c, FILE *stream);
功能:
向流中写入一个字符
参数:
c:要写入的字符
stream:文件流指针
返回值:
成功返回写入的字符ASCII码值
失败返回EOF
cp 1 2
$?
cat 2
注意:
系统默认打开了三个文件
stdin --- 标准输入 -----------> Ctrl + d 是EOF
stdout --- 标准输出
stderr --- 标准出错 --- 屏幕


char *fgets(char *s, int size, FILE *stream);
功能:
从stream流对象关联的文件中获取size大小字节的文本数据
并存储到s对应的本地内存(栈区数组,堆区内存)
参数: s 要存储数据的本地内存
size 要获取的数据长度,单位字节。
stream 要获取的目标文件流对象,
可以是stdin ,程序会阻塞等待
如果是普通文件fp 则指向文件第一行数据
返回值:成功 返回指向有效数据的首地址,一般等于s的地址
失败 或者 文件末尾 NULL;
fgets读取结束的条件:
1.EOF 文件结束
2.\n 读到 "换行符" 则读取结束
注意:
会被保存到 buffer(保存数据的这块内存中)
3.size-1 个字符
'\0' //按字符串读写
12345
buf[] = '1''2''3''4''5''\n''0'


练习:在文件中打印日历日期。
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
int lineCnt(FILE *fp)
{
int cnt = 0;
char buf[10];
while (fgets(buf,sizeof(buf),fp) != NULL)
{
if (buf[strlen(buf) - 1] == '\n')
cnt++;
}
return cnt;
}
void do_log(FILE *fp)
{
//1.统计行数
int lines = lineCnt(fp);
//2.输出数据
while (1)
{
time_t t = time(NULL);
struct tm *ptm = localtime(&t);
lines++;
fprintf(stdout,"%d,%04d-%02d-%02d %02d:%02d:%02d\n",lines,ptm->tm_year+1900,ptm->tm_mon+1,ptm->tm_mday,ptm->tm_hour,ptm->tm_min,ptm->tm_sec);
fprintf(fp,"%d,%04d-%02d-%02d %02d:%02d:%02d\n",lines,ptm->tm_year+1900,ptm->tm_mon+1,ptm->tm_mday,ptm->tm_hour,ptm->tm_min,ptm->tm_sec);
fflush(fp);
sleep(1);
}
}
//./a.out 1.txt
int main(int argc, const char *argv[])
{
if (argc != 2)
{
printf("Usage: %s <filename>\n",argv[0]);
return -1;
}
FILE *fp = fopen(argv[1],"a+");
if (fp == NULL)
{
perror("fopen fail");
return -1;
}
do_log(fp);
fclose(fp);
return 0;
}
缓冲区:
程序一直进行会存在缓存缓冲区问题。



若想查看缓冲区的长度:
可以用 IO_end - IO_base
查看标准输出的大小
int fputs(const char *s, FILE *stream);
功能:
从s所在的本地内存中获取一行数据,
并写入stream对应的文件流对象。
参数: s 要写的信息,一般是固定的字符串或者有数据的数组。
stream 要写入的目标文件流对象
返回值:成功 nonnegative number on success
失败 -1;
练习:实现copy的代码
#include <stdio.h>
void do_copy(FILE *fp_s, FILE *fp_d)
{
char buf[100];
while (fgets(buf,sizeof(buf),fp_s) != NULL)
{
fputs(buf,fp_d);
}
}
int main(int argc, const char *argv[])
{
if (argc != 3)
{
printf("Usage: %s <src> <dest>\n",argv[0]);
return -1;
}
FILE *fp_s = fopen(argv[1],"r");
FILE *fp_d = fopen(argv[2],"w");
if (fp_s == NULL || fp_d == NULL)
{
perror("fopen fail");
return -1;
}
do_copy(fp_s,fp_d);
fclose(fp_s);
fclose(fp_d);
return 0;
}
注意:
文本文件——文件中放的全是文本字符,字符这种数据——对应的是某个固定的文本的编码格式、
二进制文件——主要放的不是字符这种数据,而是二进制数据、
所以1、fgets与fputs实现拷贝文件拷贝
不能操作二进制文件
原因是fputs遇见‘\0’就输出结束,这会导致大量的数据丢失。
二进制文件读写: fread()/fwrite()
int a = 2 ;
vim -t size_t
读:
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
功能:从指定的stream流对象中获取nmemeb个大小为size字节的数据块到ptr
所在的本地内存中。
参数:ptr 要存储数据的本地内存一般是数组或者结构体指针
size 单个数据块的元数据大小。最小单元的大小
nmemb 要获取的数据块的个数,拷贝的数据块个数。
stream 要获取数据的源文件流对象,如果是stdin表示从
键盘获取数据,如果是fp文件则表示从普通文件获取。
返回值:
成功 小于等于nemeb的整数,表示获取的数据长度
失败 小于0,结尾 0;

写:
size_t fwrite(const void *ptr, size_t size,size_t nmemb, FILE *stream);
功能:从ptr所在本地内存中取出nmemb个大小为size的数据块写入到stream流对应
的文件流对象中。
参数:ptr 要写的数据块地址,一般是数组或者结构体指针
size 要写的数据块元数据大小,单位是字节
nmemb 要写的数据块的个数
stream 要写的目标文件流对象。如果是stdout则表示数据会
写到终端屏幕显示,如果是fp的普通文件则会写入到文件中。
返回值:成功 小于等于nmemb 的个数。
失败 <0
int a =10;
#include<stdio.h>
typedef struct
{
char name[20];
int sno;
float score;
}stu_t;
int main(int argc, const char *argv[])
{
FILE *fp=fopen(argv[1],"w+");
stu_t s={"xiaomingh",123,90};
fwrite(&s,sizeof(stu_t),1,fp);
rewind(fp);
stu_t s1;
fread(&s1,sizeof(stu_t),1,fp);
printf("-name = %s\n",s1.name);
printf("-sno = %d\n",s1.sno);
printf("-score=%.2f\n",s1.score);
fclose(fp);
return 0;
}
//定位操作:
标准IO之文件定位:
fseek() ftell() rewind()
int fseek(FILE *stream, long offset, int whence);
功能:将stream流文件中的文件指针从whence位置开始
偏移offset字节的长度。
参数:stream 要移动文件指针的目标文件流对象。
注意:不支持设备文件,一般用于普通文件。
offset 要在文件内偏移的距离,单位字节。
如果值为整数,则向文件末尾偏移
如果值为负数,则向文件开头偏移
whence 偏移的起始位置,由系统定义的三个宏开始。
SEEK_SET 文件的开头位置
SEEK_CUR 文件的当前位置
SEEK_END 文件的末尾位置
返回值:
成功: 返回 0
失败: -1;
注意:
SEEK_SET ooffset不能是负的
SEEK_CUR 如果不是文件开头 offset可正可负
SEET_END:
如果从文件的指定位置向后偏移过程中已经超过了文件
的当前末尾位置,则会自动以'\0'来填充文件内容,从
而形成一种被称为"空洞文件" 的特殊文件。
空洞文件:
downloading ——临时文件 抢占磁盘空间
作用 :
a:偏移 ——不会i抢占空间
b: 做了写操作,才会开辟新的空间
假如说百度下载文件:
1.先获取源文件大小fseek(fp_s,0,SEEK END)://定位到文件末尾long len = ftell(fp_s);//获得文件的大小
2.偏移 出 len-1个偏移量
fseek(fp d,len-1,SEEK END):
3.做一次写操作fputc( o',fp_d);
#include<stdio.h>
int main(int argc, const char *argv[])
{
FILE *fp_s=fopen(argv[1],"r");
FILE *fp_d=fopen(argv[2],"w");
fseek(fp_s,0,SEEK_END);
long len = ftell(fp_s);
fseek(fp_d,len-1,SEEK_END);
fputc('\0',fp_d);
return 0;
}
rewind() 等效于:
fseek(stream,0L,SEEK_SET);
long ftell(FILE *stream);
rewind(fp);
功能:
获取当前文件流指针的具体位置,
一般以文件开头到当前指针的字节数为返回值。
参数:stream 要返回指针距离的文件流对象
返回值:成功 获取到的距离长度,单位是字节
失败 -1;
#include<stdio.h>
typedef struct
{
char name[20];
int sno;
float score;
}stu_t;
int main(int argc, const char *argv[])
{
FILE *fp=fopen(argv[1],"w+");
stu_t s={"xiaomingh",123,90};
fwrite(&s,sizeof(stu_t),1,fp);
rewind(fp);
stu_t s1;
fread(&s1,sizeof(stu_t),1,fp);
printf("-name = %s\n",s1.name);
printf("-sno = %d\n",s1.sno);
printf("-score=%.2f\n",s1.score);
fclose(fp);
return 0;
}
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐




所有评论(0)