嵌入式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

相关文章
|
1天前
|
Linux
Linux查看文件的行数,字数,字节数
Linux查看文件的行数,字数,字节数
|
5天前
|
Linux
Linux 中经常见到的 gz 文件
Linux 中经常见到的 gz 文件
|
1天前
|
Ubuntu Java Linux
查看Linux系统中日志文件
查看Linux系统中日志文件
|
14天前
|
网络协议 Unix Linux
Linux 多种方式实现文件共享(三)NFS 6
【8月更文挑战第6天】NFS 即网络文件系统,是一种使用于分布式文件系统的协议,NFS 功能是通过网络让不同的机器,不同的操作系统能够彼此分享各自的数据,让应用程序在客户端通过网络访问位于服务器磁盘中的数据
49 13
|
4天前
|
存储 Linux Windows
Linux zip命令:压缩文件或目录
我们经常会在 Windows 系统上使用 “.zip”格式压缩文件,其实“.zip”格式文件是 Windows 和 Linux 系统都通用的压缩文件类型,属于几种主流的压缩格式(zip、rar等)之一,是一种相当简单的分别压缩每个文件的存储格式,本节要讲的 zip 命令,类似于 Windows 系统中的 winzip 压缩程序,其基本格式如下: [root@localhost ~]#zip [选项] 压缩包名 源文件或源目录列表 注意,zip 压缩命令需要手工指定压缩之后的压缩包名,注意写清楚扩展名,以便解压缩时使用。 下面给大家举几个例子。 【例 1】zip 命令的基本使用。 [r
18 0
Linux zip命令:压缩文件或目录
|
7天前
|
Linux Shell 数据库
【绝技大公开】Linux文件查找新招式:打破常规,探索那些鲜为人知的技巧,让你成为真正的文件追踪大师!
【8月更文挑战第13天】文件查找是Linux用户必备技能,能大幅提升工作效率。本文介绍几种高效查找方法,包括使用`column`美化`find`输出、利用`locate`和`mlocate`快速搜索、编写脚本自动化任务、采用`fd`现代工具提升查找体验,以及结合`grep`和`rg`搜索文件内容。此外,还推荐了`Gnome Search Tool`和`Albert`等图形界面工具,为用户提供多样选择。掌握这些技巧,让你的工作更加得心应手。
22 2
|
14天前
|
Linux 数据安全/隐私保护 Perl
解锁Linux高手秘籍:文件操作+命令解析大揭秘,面试场上让你光芒万丈,技术实力惊艳四座!
【8月更文挑战第5天】Linux作为服务器与嵌入式系统的基石,其文件管理和命令行操作是技术人员必备技能。本文从文件操作和基础命令两大方面,深入浅出地解析Linux核心要义,助你在面试中脱颖而出。首先探索文件系统的树状结构及操作,包括使用`ls -la`浏览文件详情、`touch`创建文件、`rm -r`慎删目录、`cp`与`mv`复制移动文件、以及利用`find`搜索文件。接着掌握命令行技巧,如用`cat`、`more`和`less`查看文件内容;借助`grep`、`sed`与`awk`处理文本;运用`ps`、`top`和`kill`管理进程;并通过`chmod`和`chown`管理文件权限。
53 8
|
13天前
|
存储 网络协议 Linux
Linux 多种方式实现文件共享(四)iSCSI 磁盘共享服务 7
【8月更文挑战第7天】iSCSI技术是一种新储存技术, iSCSI 提供了在 IP 网络封装 SCSI 命令,且以TCP/IP协议传输.
35 5
|
11天前
|
Linux
Linux专栏07:Linux基本指令之文件搜索指令
Linux专栏07:Linux基本指令之文件搜索指令
34 2
|
14天前
|
存储 Linux 开发工具
Linux 多种方式实现文件共享(二)Samba 5
【8月更文挑战第5天】Samba 文件共享
40 5