嵌入式Linux C(十三)——文件操作(详)

简介: 嵌入式Linux C(十三)——文件操作(详)

一、打开、读写、关闭


1.1 fopen


image.png


一般用a+


#include <stdio.h>
#include <stdlib.h>
int main(int argc, char const *argv[])
{
    FILE *fp;
    //fp = fopen("a.txt","w+");
    fp = fopen(argv[1],"a+");
    if (NULL == fp)
    {
        printf("file a.txt error!\n");
        exit(1);
    }
    return 0;
}


加b可以以二进制打开文件,不加为字符打开


1.2 fclose


FILE *fp;
 fp = fopen(argv[1],"a+");
 fclose(fp);


1.3 fwrite


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

const void *ptr:要写入的数据指针

size_t size:每次写size字节

size_t nmemb:总共写nmemb次

FILE *stream:所写入的文件

返回值:nmemb(写了多少次)

出错是0


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char const *argv[])
{
    FILE *fp;
    //fp = fopen("a.txt","w+");
    fp = fopen(argv[1],"a+");
    //fp = fopen(argv[1],"r");
    if (NULL == fp)
    {
        printf("file a.txt error!\n");
        exit(1);
    }
    char buffer[1024] = "hello world";
    int ret = fwrite(buffer,1,strlen(buffer),fp);
    printf("ret = %d\n",ret);
    return 0;
}


1.4 fread


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

void *ptr:要写入的数据指针

size_t size:每次读size字节

size_t nmemb:总共读nmemb次

FILE *stream:所写入的文件

返回值:nmemb(读了多少次)

出错是0


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char const *argv[])
{
   FILE *fp;
   //fp = fopen("a.txt","w+");
   fp = fopen(argv[1],"a+");
   if (NULL == fp)
   {
       printf("file a.txt error!\n");
       exit(1);
   }
   char buffer[1024] = "hello world";
   int ret = fwrite(buffer,1,strlen(buffer),fp);
   printf("ret = %d\n",ret);
   memset(buffer,0,sizeof(buffer));
   ret = fread(buffer,1,ret,fp);
   buffer[ret] = '\0';
   printf("read buffer = %s\n",buffer);
   return 0;
}
//读不出来,是因为文件读写位置指针指向末尾


文件读写指针

image.png


二、fseek、feof、ftell


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


FILE *stream 目标文件

long offset 偏移量(正数是后移,负数是前移)

int whence 锁定位置(配图)

顺序:先锁定位置,再判断偏移量

0a2653c851af460fa595bd959398a8f1.png

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char const *argv[])
{
    FILE *fp;
    //fp = fopen("a.txt","w+");
    fp = fopen(argv[1],"a+");
    if (NULL == fp)
    {
        printf("file a.txt error!\n");
        exit(1);
    }
    char buffer[1024] = "hello world";
    int ret = fwrite(buffer,1,strlen(buffer),fp);
    if(0 == ret)
    {
        printf("fwrite a.txt error!\n");
        exit(1);
    }
    printf("ret = %d\n",ret);
    ret = fseek(fp,0,SEEK_SET);
    if(-1 == ret)
    {
        printf("fseek a.txt error!\n");
        exit(1);
    }
    memset(buffer,0,sizeof(buffer));
    ret = fread(buffer,1,ret,fp);
    if(0 == ret)
    {
        printf("fread a.txt error!\n");
        exit(1);
    }
    buffer[ret] = '\0';
    printf("read buffer = %s\n",buffer);
    return 0;
}


2.1 实现写读写一行


2.1.1 写


fwrite("\n",1,1,fp);


2.1.2 读(feof、ftell、rewind)


文档结尾有个隐藏字符EOF

int feof(FILE *stream);

文件结束:返回非0值;文件未结束:返回0值

ftell:用来得到文件指针离文件开头的偏移量

long ftell(FILE *stream);

rewind()用于文件指针移动到文件的开头,当移动成功时

void rewind(FILE *stream);


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char const *argv[])
{
    FILE *fp;
    //fp = fopen("a.txt","w+");
    fp = fopen(argv[1], "a+");
    if (NULL == fp)
    {
        printf("file a.txt error!\n");
        exit(1);
    }
    char buffer[1024] = "hello world";
    int ret = fwrite(buffer, 1, strlen(buffer), fp);
    fwrite("\n", 1, 1, fp);
    if (0 == ret)
    {
        printf("fwrite a.txt error!\n");
        exit(1);
    }
    printf("ret = %d\n", ret);
    ret = fseek(fp, 0, SEEK_SET);
    if (-1 == ret)
    {
        printf("fseek a.txt error!\n");
        exit(1);
    }
    memset(buffer,0,sizeof(buffer));
    char temp;
    int i = 0;
    while (!feof(fp))
    {
        if(fread(&temp, 1, 1, fp) == -1)
        {
            printf("file fread error!\n");
        }
        buffer[i] = temp;
        i++;
    }
#if 0
    ret = fread(buffer,1,ret,fp);
    if(0 == ret)
    {
        printf("fread a.txt error!\n");
        exit(1);
    }
#endif
    buffer[i] = '\0';
    printf("read buffer = %s\n",buffer);
    fclose(fp);
    return 0;
}


2.2 feof经典错误案例


2.2.1 原理


原理:站在光标所在位置,向后面看看有没有字符,如果有,返回0;如果没有,返回非0。它并不会读取相关信息,只会查看光标后是否有内容

功能:检测文件结束符EOF


2.2.2 判断一个文件是否为空


#include <stdio.h>
int main(int argc, char *argv[])
{
    FILE *fp;
    fp = fopen(argv[1], "a+");
#if 0
    if (feof(fp) == 0)
    {
        printf("file is empty\n");
    }
#endif
    if (feof(fp) != 0)
    {
        printf("file is empty\n");
    }
    fclose(fp);
    return 0;
}


现象:feof并不能判断空文件,返回为0

原因:当文件内部的位置指针指向文件结束时,并不会立即设置FILE结构中的文件结束标识,只有再执行一次读文件操作,才会设置结束标志,此后调用feof()才会返回为真。

解决


#include <stdio.h>
int main(int argc, char const *argv[])
{
    FILE *p;
    getc(p);
    if (feof(p))
    {
        printf("file is empty.\n");
    }
    else
    {
        rewind(p);//将光标跳回到文件开头
        int a;
        fscanf(p,"%d",&a);
        printf("%d",a);
    }
    return 0;
}


//例如,有一个文件指针fp,文件中有字符串“hello world”:
int c=0;
while( !feof(fp) )
{
    int c=fgetc(fp);
    printf("%c: %x \n", c, c);
}
//上面的代码除了输出 hello 外,还会输出一个结束字符EOF(EOF是fgetc函数的返回值,
//并不是文件中存在EOF)。其原因就是当内部位置指针指向结尾时,
//还要执行一次读操作,文件结束标识才会被设置。
//修改
int c; 
c=fgetc(fp);     
while( !feof(fp) ) 
{    
    printf("%c: %x \n", c, c); 
    c=fgetc(fp); 
}
//上面的代码只输出“hello”不输出文件结束符EOF。
//当文件内部位置指针指向结束位置时,先执行一次读操作,
//设置文件结束标识,while循环立即结束。


参考网站:C语言feof()函数:检查流上文件的结束标识(是否读到文件结尾)


2.3 实现将一个文件拷贝给另一个文件


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void isOK(FILE *fp, char *filename)
{
    if (fp == NULL)
    {
        printf("%s open error!\n", filename);
        exit(1);
    }
}
int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        printf("Please input file name!\n");
        exit(1);
    }
    FILE *to_fp;
    FILE *from_fp;
    char buffer[1024] = {0};
    from_fp = fopen(argv[1], "r");
    isOK(from_fp, argv[1]);
    to_fp = fopen(argv[2], "a+");
    isOK(to_fp, argv[2]);
    fseek(to_fp, 0, SEEK_SET); //rewind(to_fp);
    fseek(from_fp, 0, SEEK_END);
    int w_len;
    int file_size = ftell(from_fp);
    fseek(from_fp, 0, SEEK_SET);
    while (!feof(from_fp))
    {
        memset(buffer, 0, sizeof(buffer));
        fread(buffer, 1, sizeof(buffer) - 1, from_fp);
        w_len = fwrite(buffer, 1, strlen(buffer), to_fp);
        //printf("%s\n", buffer);
        file_size = file_size - w_len;
        if (file_size < 0)
        {
            break;
        }
    }
    return 0;
}


三、fgetc、fgets、getc、getchar


getchar:从终端上获取一个字符

fgetc:


头文件:#include 
原型:int fgetc(FILE *stream)
功能:从文件中获取一个字符
参数:stream 目标文件指针
返回值:该字符所对应的ASCII码,若返回`EOF`则表示到了文件尾


getc:


getc()和fgetc(),作用相同,但是getc()是宏定义,非真正的函数调用

char temp;
while ((temp = fgetc(from_fp)) != EOF)
  {
  fputc(temp, to_fp)
  }
    return 0;
}


fgets


头文件:#include 
原型:char *fgets(char *s, int size, FILE *stream)
功能:
  读取stream一行,存储到s中。当读取 (size-1) 个字符时,
  或者读取到换行符时,或者到达文件末尾时,它会停止,并加上`\0`
参数:
  s 这是指向一个字符数组的指针,该数组存储了要读取的字符串
  size 这是要读取的最大字符数(包括最后的空字符)。通常是使用以 str 传递的数组长度。
  stream 这是指向 FILE 对象的指针,该 FILE 对象标识了要从中读取字符的流。
返回值:
  如果成功,该函数返回相同的 s 指针。失败则返回`NULL`。
如果发生错误,返回一个空指针。


fgets(buffer, sizeof(buffer), from_fp);
  buffer[strlen(buffer) - 1] = '\0';  //把读取到的`\n`给去除
  printf("%s\n", buffer);
  //打印:#include <stdio.h>


四、fputc、fputs、putc、putchar


putchar:从终端上输出一个字符

fputc:


头文件:#include 
原型:int fputc(int c, FILE *stream)
功能:向stream写入一个字符c
参数:
  c 你要输入的字符(int 是其ASCII)
  stream 你要输入的文件指针
返回值:如果没有发生错误,则返回被写入的字符。如果发生错误,则返回 EOF


char temp;
while ((temp = fgetc(from_fp)) != EOF)
  {
  fputc(temp, to_fp)
  }
    return 0;
}


putc:


putc()和fputc(),作用相同,但是putc()是宏定义,非真正的函数调用


fputs


头文件:#include 
原型:int *fputs(const char *s, FILE *stream)
功能:把字符串写入到指定的流 stream 中,但不包括``\0。
参数:
  s 要写入的字符串
  stream 这是指向 FILE 对象的指针,该 FILE 对象标识了要被写入字符串的流。
返回值:
  该函数返回一个非负值,如果发生错误则返回 EOF。


while (fgets(buffer, sizeof(buffer), from_fp != NULL))
  {
  fputs(buffer, to_fp)
  memset(buffer, 0, sizeof(buffer));
  }


五、fprintf(格式化输出)


文件里面没格式,需要自己去定义


头文件:#include 
原型:int fprintf(FILE *stream, const char *format...)
功能:会根据参数format字符串来转换并格式化数据,然后将结果输出到参数stream指定的文件中,知道字符串结束(\0)为止
参数:
  stream 目标文件指针
  format 这是 C 字符串,包含了要被写入到流 stream 中的文本。
返回值:如果成功,则返回写入的字符总数,否则返回一个负数。
fprintf详见:C 库函数 - fprintf


#include <stdio.h>
int main(int argc, char const *argv[])
{
    int num = 5;
    char name[20] = "zhangsan";
    int age = 16;
    FILE *fp = fopen(argv[1], "a+");
    fprintf(fp, "%d:%s:%d\n", num, name, age); //sprintf
    // fwrite(&num, 1, sizeof(num), fp);
    // fseek(fp, 0, SEEK_SET);
    // int temp;
    // fread(&temp, 1, sizeof(temp), fp);
    fclose(fp);
    return 0;
}


五、文件操作(stdin、stdout、stderr)


文件指针:

stdin(键盘)

stdout(终端)

stderr(终端)


char buffer[1024];
fgets(buffer,sizeof(buffer),stdin); //键盘上读取数据
buffer[strlen(buffer) - 1] = '\0';
fputs(buffer,stdout);
打印错误信息或者调试信息时,用stderr
打印正常信息时,用stdout


六、随机读取数据


二进制读取文件


#include <stdio.h>
struct node
{
    int num;
    char name[20];
    int age;
};
int main(int argc, char const *argv[])
{
    FILE *fp = fopen(argv[1], "ab+");
    if (NULL == fp)
    {
        printf("error!");
        exit(1)
    }
    struct node p1 = {.num = 1, .name = "zhangsan", .age = 16};
    struct node p2 = {.num = 2, .name = "zhangsi", .age = 17};
    struct node p3 = {.num = 3, .name = "zhangwu", .age = 18};
    fwrite(&p1, 1, sizeof(p1),fp);
    fwrite(&p2, 1, sizeof(p1),fp);
    fwrite(&p3, 1, sizeof(p1),fp);
    fseek(fp, 0, SEEK_SET)
    fseek(fp, sizeof(struct node), SEEK_SET);
    struct node temp;
    fread(&temp, 1, sizeof(struct node),fp);
    printf("num = %d, name = %s, age = %d\n", temp.num, temp.name, temp.age);
    fclose(fp);
    return 0;
}

0a2653c851af460fa595bd959398a8f1.png

相关文章
|
2月前
|
Linux 数据安全/隐私保护 Windows
命令方式:window向linux传文件
【10月更文挑战第6天】本文介绍了如何在Linux系统中通过命令`ip a`获取IP地址,并在Windows系统下使用CMD命令行工具和SCP命令实现文件传输。示例展示了如何将D盘中的`mm.jar`文件上传至IP地址为192.168.163.122的Linux系统的/up/目录下,最后在Linux系统中确认文件传输结果。
271 65
|
2月前
|
运维 安全 Linux
Linux中传输文件文件夹的10个scp命令
【10月更文挑战第18天】本文详细介绍了10种利用scp命令在Linux系统中进行文件传输的方法,涵盖基础文件传输、使用密钥认证、复制整个目录、从远程主机复制文件、同时传输多个文件和目录、保持文件权限、跨多台远程主机传输、指定端口及显示传输进度等场景,旨在帮助用户在不同情况下高效安全地完成文件传输任务。
321 5
|
2月前
|
Linux Shell 数据库
Linux文件查找新姿势:总有一种你没见过
【10月更文挑战第18天】文件查找是Linux用户提升工作效率的重要技能。本文介绍了几种实用的文件查找方法,包括基础的`find`命令、快速的`locate`和`mlocate`、高效的`fd`工具、以及结合`grep`和`rg`进行内容搜索。此外,还提供了编写Shell脚本和使用图形界面工具的建议,帮助你更灵活地管理文件。
83 3
|
6天前
|
Linux Shell 网络安全
Kali Linux系统Metasploit框架利用 HTA 文件进行渗透测试实验
本指南介绍如何利用 HTA 文件和 Metasploit 框架进行渗透测试。通过创建反向 shell、生成 HTA 文件、设置 HTTP 服务器和发送文件,最终实现对目标系统的控制。适用于教育目的,需合法授权。
33 9
Kali Linux系统Metasploit框架利用 HTA 文件进行渗透测试实验
|
2天前
|
存储 监控 Linux
嵌入式Linux系统编程 — 5.3 times、clock函数获取进程时间
在嵌入式Linux系统编程中,`times`和 `clock`函数是获取进程时间的两个重要工具。`times`函数提供了更详细的进程和子进程时间信息,而 `clock`函数则提供了更简单的处理器时间获取方法。根据具体需求选择合适的函数,可以更有效地进行性能分析和资源管理。通过本文的介绍,希望能帮助您更好地理解和使用这两个函数,提高嵌入式系统编程的效率和效果。
35 13
|
27天前
|
运维 监控 网络协议
运维工程师日常工作中最常用的20个Linux命令,涵盖文件操作、目录管理、权限设置、系统监控等方面
本文介绍了运维工程师日常工作中最常用的20个Linux命令,涵盖文件操作、目录管理、权限设置、系统监控等方面,旨在帮助读者提高工作效率。从基本的文件查看与编辑,到高级的网络配置与安全管理,这些命令是运维工作中的必备工具。
110 3
|
1月前
|
Linux 开发工具 Perl
在Linux中,有一个文件,如何删除包含“www“字样的字符?
在Linux中,如果你想删除一个文件中包含特定字样(如“www”)的所有字符或行,你可以使用多种文本处理工具来实现。以下是一些常见的方法:
41 5
|
1月前
|
安全 Linux 数据安全/隐私保护
在 Linux 系统中,查找文件所有者是系统管理和安全审计的重要技能。
在 Linux 系统中,查找文件所有者是系统管理和安全审计的重要技能。本文介绍了使用 `ls -l` 和 `stat` 命令查找文件所有者的基本方法,以及通过文件路径、通配符和结合其他命令的高级技巧。还提供了实际案例分析和注意事项,帮助读者更好地掌握这一操作。
48 6
|
1月前
|
Linux
在 Linux 系统中,`find` 命令是一个强大的文件查找工具
在 Linux 系统中,`find` 命令是一个强大的文件查找工具。本文详细介绍了 `find` 命令的基本语法、常用选项和具体应用示例,帮助用户快速掌握如何根据文件名、类型、大小、修改时间等条件查找文件,并展示了如何结合逻辑运算符、正则表达式和排除特定目录等高级用法。
84 6
|
1月前
|
监控 Linux Perl
Linux 命令小技巧:显示文件指定行的内容
在 Linux 系统中,处理文本文件是一项常见任务。本文介绍了如何使用 head、tail、sed 和 awk 等命令快速显示文件中的指定行内容,帮助你高效处理文本文件。通过实际应用场景和案例分析,展示了这些命令在代码审查、日志分析和文本处理中的具体用途。同时,还提供了注意事项和技巧,帮助你更好地掌握这些命令。
62 4