zoukankan      html  css  js  c++  java
  • GNU/Linux应用程序开发学习笔记(一) 文件操作

    GNU/Linux的文件操作

     
    GNU/Linux的文件操作是通过标准C库实现的,可以用同一个API创建ASCII或二进制文件,其中文件操作函数有很多个,分别对应不同方面的功能,可谓是面面具到,下面就逐一学习。
    1.Header file
    在C中 ,
    #include <stdio.h>
    在C++中,
    #include <cstdio>
    2.Open File
    一般用fopen()函数来打开文件,fclose()函数关闭文件。

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

    其中mode是文件访问模式:
    * r 打开一个已经存在的文件进行度操作
    * w 打开一个文件进行写操作
    * a 对文件进行追加操作
    * rw 对文件进行读写操作
    上面后三个模式中,如果文件不存在,则会创建一个新文件filename,而第一个返回 (FILE*)NULL.
    文件字符接口
    对文件进行逐个字符操作时,可使用如下两个函数:

    int fputc(int c, FILE* stream);
    int fgetc(FILE* stream);

    其中fputc()中是int类型,别忘了类型转换,示例:

    int func()
    {
    char str[] = "Hey, it's just a test!";
    FILE
    * fin = fopen(filename,"a");
    FILE
    * fout = fopen(filename,"r");
    if(fout == (FILE*)NULL || fin == (FILE*)NULL)
    exit(
    -1);
    int i = 0;
    // write string STR to the file every bytes
    while(str[i] != NULL)
    {
    fputc((
    int)str[i],fin);
    ++i;

    // get bytes from file through fgetc() until the end of the file
    while( (ch=fgetc(fout)) != EOF )
    {
    printf(
    "%c",ch);
    }
    fclose(fin);
    fclose(fout);
    return 0;
    }


    字符串接口
    对文件进行逐字符串的操作函数和字符操作函数类似,用法也类似
    fputs() , fgets();
    ASCII字符文件操作
    这类文件操作也是比较常见的操作,应用很广,主要以下几种:

    int fprintf(FILE* stream, const char* format, ...);
    int fscanf(FILE* stream, const char* format, ...);
    int sprintf(char* str, const char* format, ...);
    int sscanf(char* str, const char* format, ...);


    二进制文件的读写
    这类文件操作比较重要,特点是处理快,适用范围广,先看fread和fwrite

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

    其中ptr指的是所需要处理的对象组,比如字符串或者结构题数组,size代表每个对象的字节数,nmemb代表对象的数目,这里要注意:当对象组是字符串时,nmemb=str_len+1,原因是字符串最后的'\0'不能省略。

    void rewind(FILE* stream);

    重置文件流指针到文件首。

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

    这个函数是设置文件流指针,offset是偏移值,whence有几个标志:
    * SEEK_SET 将指针移到距离文件首offset个字节的位置
    * SEEK_CUR 将指针移到距离当前指针位置后offset个字节的位置
    * SEEK_END 将指针移到距离文件尾offset个字节的位置
    注意:offset为正数时表示指针向后移动,为负数时向前移动,这个地方写了程序各种测试才发现,以前以为SEEK_END是将指针向前移动offset字节....无语......
    long ftell(FILE* stream);
    此函数返回文件流的指针位置,是long型,通过这个可以方便的查看文件指针的位置。
    还有两个和上面功能一样的函数是fgetpos,fsetpos,但是使用目的也不一样,ftell和fseek函数没有对其机制的细节进行抽象,所以推荐使用fgetpos,fsetpos,原型如下:

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

    这两个函数通过对指针位置的抽象操作和细节描述达到比ftell,fseek更加直观的目的,他们返回的不是指针的绝对位置,而是抽象位置,所以就可以用fpos_t类型来对文件位置进行描述。
    上面这些是对二进制文件操作的函数,下面是示例:

    #include <iostream>
    #include
    <cstdio>
    using namespace std;

    #define MAXN_STR 40
    #define MAXN_OBJECT 3

    char file_name[] = "input";
    char str[] = "This is a test.";
    FILE
    * fout;
    FILE
    * fin;
    typedef
    struct{
    int id;
    float x;
    float y;
    char str[MAXN_STR+1];
    }TYPE_NODE;
    TYPE_NODE
    object[MAXN_OBJECT]={
    {
    1,10.2,12.2,"The earth"},
    {
    2,20.9,20.8,"The arm"},
    {
    3,12.3,12.4,"The null"}
    };
    TYPE_NODE tmp_object;

    int main()
    {
    fin
    = fopen(file_name,"w");
    if(fin == (FILE*)NULL)
    {
    exit(
    -1);
    }
    fwrite((
    void*)object,sizeof(TYPE_NODE),MAXN_OBJECT,fin);
    fwrite((
    void*)str,sizeof(str[0]),strlen(str)+1,fin);
    fclose(fin);
    fout
    = fopen(file_name,"r");
    if(fout == (FILE*)NULL)
    {
    exit(
    -1);
    }
    char ss[MAXN_STR];
    int pos;
    for(int i = 0; i < MAXN_OBJECT; ++i)
    {
    rewind(fout);
    fseek(fout,(i
    *sizeof(TYPE_NODE)),SEEK_CUR);
    pos
    = ftell(fout);
    printf(
    "cur pos %d\n",pos);
    fread(
    &tmp_object,sizeof(TYPE_NODE),1,fout);
    printf(
    "%d %f %f %s\n",tmp_object.id,tmp_object.x,
    tmp_object.y,tmp_object.str);
    }
    fread(ss,
    sizeof(ss[0]),strlen(str)+1,fout);
    printf(
    "%s\n",ss);

    fclose(fout);
    return 0;
    }


    基础API
    这里只写出两个:

    ssize_t pread(int filedes, void* buf, size_t nbyte, off_t offset);
    ssize_t pwrite(
    int filedes, void* buf, size_t nbyte, off_t offset);


    这两个函数需要设置offset来对文件进行读写,但是不会影响文件指针,比较适合随机查找的情况。

    ====== 总结之 文件操作API======

    FILE* fopen(const char* filename,const char* mode);
    FILE
    * fdopen(int filedes, const char* type);
    int fputc(int c,FILE* stream);
    int fgetc(FILE* stream);
    int fprintf(FILE* stream, const char* format, ...);
    int fscanf(FILE* stream, const char* format, ...);
    int sprintf(char* str, const char* format, ...);
    int sscanf(char* str, const char* format, ...);
    size_t fread(
    void* ptr,size_t size,size_t nmemb,FILE* stream);
    size_t fwrite(
    const void* ptr,size_t size,size_t nmemb,FILE* stream);
    void rewind(FILE* stream);
    long ftell(FILE* stream);
    int fseek(FILE* stream,long offset, int whence);
    int lseek(FILE* stream,long offset, int whence);
    int fgetpos(FILE* stream, fpos_t* pos);
    int fsetpos(FILE* stream, fpos_t* pos);
    int fclose(FILE* stream);
    int open(const char* pathname, int flags);
    int open(const char* pathname, int flags, mode_t mode);
  • 相关阅读:
    547. Friend Circles
    399. Evaluate Division
    684. Redundant Connection
    327. Count of Range Sum
    LeetCode 130 被围绕的区域
    LeetCode 696 计数二进制子串
    LeetCode 116 填充每个节点的下一个右侧节点
    LeetCode 101 对称二叉树
    LeetCode 111 二叉树最小深度
    LeetCode 59 螺旋矩阵II
  • 原文地址:https://www.cnblogs.com/lvpengms/p/1949212.html
Copyright © 2011-2022 走看看