• 基于文件指针的文件操作


    基于文件指针的文件操作(缓冲)

    linux的文件和文件描述符

    linux中对目录和设备的操作都是文件操作,文件分为普通文件,目录文件,链接文件和设备文件

    普通文件:也称磁盘文件,并且能够进行随机的数据存储(能够自由seek定位到某一个位置)

    管道:是一个从一端发送数据,另一端接收数据的数据通道;

    目录:也称为目录文件,它包含了保存在目录中文件列表的简单文件。

    设备:该类型的文件提供了大多数物理设备的接口。它又分为两种类型:字符型设备和块设备。

    字符型设备一次只能读出和写入一个字节的数据,包括调制解调器、终端、打印机、声卡以及鼠标;

    块设备必须以一定大小的块来读出或者写入数据,块设备包括CD-ROMRAM驱动器和磁盘驱动器等,一般而言,字符设备用于传输数据,块设备用于存储数据。

     链接:类似于Windows的快捷方式和Linux里的别名,指包含到达另一个文件路径的文件。

    套接字:Linux,套接字也可以当作文件来进行处理。

    基于文件指针的文件操作函数是ANSI标准函数库的一部分。

    1文件的创建,打开与关闭

    原型为:

    #include <stdio.h>  //头文件包含

    FILE *fopen(const char *pach,const char *mode);  //文件名  模式

    int fclose(FILE *stream);

    fopen以mode的方式打开或创建文件,如果成功,将返回一个文件指针,失败则返回NULL.

    fopen创建的文件的访问权限将以0666与当前的umask结合来确定。 

    mode的可选模式列表

    模式

    位置

    截断原内容

    创建

    rb

    Y

    N

    文件头

    N

    N

    r+b

    Y

    Y

    文件头

    N

    N

    wb

    N

    Y

    文件头

    Y

    Y

    w+b

    Y

    Y

    文件头

    Y

    Y

    ab

    N

    Y

    文件尾

    N

    Y

    a+b

    Y

    Y

    文件尾

    N

    Y

    在Linux系统中,mode里面的’b’(二进制)可以去掉,但是为了保持与其他系统的兼容性,建议不要去掉。aba+b为追加模式,在此两种模式下,无论文件读写点定位到何处,在写数据时都将是在文件末尾添加,所以比较适合于多进程写同一个文件的情况下保证数据的完整性。

    2 读写文件

    基于文件指针的数据读写函数较多,可分为如下几组:

    数据块读写:

    #include <stdio.h>

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

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

    fread从文件流stream 中读取nmemb个元素,写到ptr指向的内存中,每个元素的大小为size个字节。

    fwrite从ptr指向的内存中读取nmemb个元素,写到文件流stream中,每个元素size个字节。

    所有的文件读写函数都从文件的当前读写点开始读写,读写完以后,当前读写点自动往后移动size*nmemb个字节。

    格式化读写:

    #include <stdio.h>

    int printf(const char *format, ...);                   //相当于 fprintf(stdout,format,…);

    int scanf(const char *format, …);

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

    int fscanf(FILE *stream, const char *format, …);

    int sprintf(char *str, const char *format, ...);          // eg:   sprintf(buf,”the string is;%s”,str);

    int sscanf(char *str, const char *format, …);

    f开头的将格式化后的字符串写入到文件流stream中 

    s开头的将格式化后的字符串写入到字符串str

    单个字符读写:

    使用下列函数可以一次读写一个字符

    #include <stdio.h>

    int fgetc(FILE *stream);

    int fputc(int c, FILE *stream);

     

    int getc(FILE *stream);    //等同于 fgetc(FILE* stream)

    int putc(int c, FILE *stream);   // 等同于 fputc(int c, FILE* stream)

     

    int getchar(void);    //等同于 fgetc(stdin);

    int putchar(int c);    // 等同于 fputc(int c, stdout);

    getcharputchar从标准输入输出流中读写数据,其他函数从文件流stream中读写数据

    字符串读写:

    char *fgets(char *s, int size, FILE *stream);

    int fputs(const char *s, FILE *stream);

    int puts(const char *s);// 等同于 fputs(const char *s, int size, stdout);

    char *gets(char *s);     // 等同于 fgets(const char *s, int size,stdin);

    fgetsfputs从文件流stream中读写一行数据;

    putsgets标准输入输出流中读写一行数据。

    fgets可以指定目标缓冲区的大小,所以相对于gets安全,但是fgets调用时,如果文件中当前行的字符个数大于size,则下一次fgets调用时,将继续读取该行剩下的字符,fgets读取一行字符时,保留行尾的换行符

    fputs不会在行尾自动添加换行符,但是puts会在标准输出流中自动添加一换行符

     

    文件定位:

    文件定位指读取或设置文件当前读写点,所有的通过文件指针读写数据的函数,都是从文件的当前读写点读写数据的。

    常用的函数有:

    #include <stdio.h>

    int feof(FILE * stream);   //通常的用法为while(!feof(fp))

    int fseek(FILE *stream, long offset, int whence);//设置当前读写点到偏移whence 长度为offset

    long ftell(FILE *stream); //用来获得文件流当前的读写位置

    void rewind(FILE *stream); //把文件流的读写位置移至文件开头 fseek(fp, 0, SEEK_SET);

    feof判断是否到达文件末尾的下一个(注意到达文件末尾之后还会做一次)

    fseek设置当前读写点到偏移whence 长度为offset处,whence可以是:

    SEEK_SET (文件开头  ->0)

    SEEK_CUR (文件当前位置  ->1)

    SEEK_END (文件末尾  ->2)

    ftell获取当前的读写点

    rewind将文件当前读写点移动到文件头

     

    注:基于文件指针的文件操作请参考《C语言文件操作常用函数详解.doc

    3目录操作

    改变目录或文件的访问权限

    #include <sys/stat.h>

    int chmod(const char* path, mode_t mode); //mode形如:0777

    path参数指定的文件被修改为具有mode参数给出的访问权限。

     

    获取、改变当前目录:

    原型为:

    #include <unistd.h>   //头文件

    char *getcwd(char *buf, size_t size); //获取当前目录,相当于pwd命令

    int chdir(const char *path); //修改当前目录,即切换目录,相当于cd命令

    其中getcwd()函数:将当前的工作目录绝对路径复制到参数buf所指的内存空间,参数size为buf的空间大小. 在调用此函数时,buf所指的内存空间要足够大,若工作目录绝对路径的字符串长度超过参数size大小,则回值NULL,errno的值则为ERANGE。

    倘若参数buf为NULL,getcwd()会依参数size的大小自动配置内存(使用malloc()),如果参数size也为0,则getcwd()会依工作目录绝对路径的字符串程度来决定所配置的内存大小,进程可以在使用完此字符串后自动利用free()来释放此空间。所以常用的形式:getcwd(NULL, 0);

    chdir()函数:用来将当前的工作目录改变成以参数path所指的目录

    Example:

    1 #include<unistd.h>
    2 int main()
    3 {
    4 
    5   chdir(“/tmp”);
    6   printf(“current working directory: %s
    ”,getcwd(NULL,0));
    7       return 0;
    8 
    9 }
    View Code

    创建和删除目录:

    原型为:

    #include <sys/stat.h>

    #include <sys/types.h>

    #include <unistd.h>

    int mkdir(const char *pathname, mode_t mode); //创建目录,mode是目录权限,没用

    int rmdir(const char *pathname); //删除目录

     

    获取目录信息:

    原型为:

    #include <sys/types.h>

    #include <dirent.h>

    DIR *opendir(const char *name); //打开一个目录,返回一个目录流

    struct dirent *readdir(DIR *dir); //读取目录的一项信息,并返回该项信息的结构体指针

    void rewinddir(DIR *dir); //重新定位到目录文件的头部

    void seekdir(DIR *dir,off_t offset);//用来设置目录流目前的读取位置

    off_t telldir(DIR *dir); //返回目录流当前的读取位置

    int closedir(DIR *dir); //关闭目录文件

     

    读取目录信息的步骤为:

    1 用opendir函数打开目录;

    2使用readdir函数迭代读取目录的内容,如果已经读取到目录末尾,又想重新开始读,则可以使用rewinddir函数将文件指针重新定位到目录文件的起始位置;

    3 用closedir函数关闭目录

    opendir()用来打开参数name指定的目录,并返回DIR*形态的目录流,和文件操作函数open()类似,接下来对目录的读取和搜索都要使用此返回值。函数失败则返回NULL;

    readdir()函数用来读取目录的信息,并返回一个结构体指针,该指针保存了目录的相关信息。有错误发生或者读取到目录文件尾则返回NULL;dirent结构体如下:

    struct dirent

    {

      ino_t  d_ino;           /* inode number(此目录进入点的inode) */

      off_t  d_off;             /* offset to the next dirent(目录开头到进入点的位移 */

      unsigned short d_reclen;  /* length of this record(目录名的长度) */

      unsigned char d_type;     /* type of file(所指的文件类型) */

      char   d_name[256];       /* filename(文件名) */

    };

    seekdir()函数用来设置目录流目前的读取位置,再调用readdir()函数时,便可以从此新位置开始读取。

    参数offset代表距离目录文件开头的偏移量。

    telldir()函数用来返回目录流当前的读取位置。

    示例:返回指定目录下的文件

     1 #include <stdio.h>
     2 
     3 #include <sys/types.h>
     4 
     5 #include <dirent.h>
     6 
     7  
     8 
     9 int main(int argc,char *argv[])
    10 
    11 {
    12 
    13     struct dirent *pDirInfo;
    14 
    15     DIR *pDir;
    16 
    17     if(argc < 2)
    18 
    19         pDir = opendir(".");
    20 
    21     else
    22 
    23         pDir = opendir(argv[1]);
    24 
    25 if(NULL == pDir)
    26 
    27 {
    28 
    29         perror("open dir fail!");
    30 
    31         return -1;
    32 
    33     }
    34 
    35     while( (pDirInfo = readdir(pDir)) != NULL )
    36 
    37         printf("%s
    ",pDirInfo->d_name);
    38 
    39       closedir(pDir);
    40 
    41         return 0;
    42 
    43 }
    View Code

    Example:以树形结构的形式输出指定目录下面的所有文件

     1 #include <unistd.h>
     2 
     3 #include <stdio.h>
     4 
     5 #include <dirent.h>
     6 
     7 #include <string.h>
     8 
     9 #include <sys/stat.h>
    10 
    11 #include <stdlib.h>
    12 
    13 void printdir(char *dir, int depth)//depth为缩进空格数
    14 
    15 {
    16 
    17     DIR *dp = opendir(dir);
    18 
    19    if(NULL == dp) 
    20 
    21    {
    22 
    23         fprintf(stderr,"cannot open directory: %s
    ", dir);
    24 
    25         return;
    26 
    27     }
    28 
    29   chdir(dir);
    30 
    31     struct dirent *entry;
    32 
    33     struct stat statbuf;
    34 
    35 while((entry = readdir(dp)) != NULL) 
    36 
    37 {
    38 
    39         stat(entry->d_name,&statbuf);
    40 
    41         if(S_ISDIR(statbuf.st_mode)) //是目录
    42 
    43 {
    44 
    45             if(strcmp(".",entry->d_name) == 0 || strcmp("..",entry->d_name) == 0)
    46 
    47                 continue; 
    48 
    49             printf("%*s%s/
    ",depth,"",entry->d_name);
    50 
    51             printdir(entry->d_name,depth+4);//递归
    52 
    53         }
    54 
    55         else //是文件
    56 
    57     printf("%*s%s
    ",depth,"",entry->d_name);
    58 
    59     //printf(“%*s”,4,”*”); 该函数表示输出“___*”,前面输出3个空格。
    60 
    61     //如果是printf(“%*s”,4,“**”);则表示输出“__**”,前面输出2个空格。
    62 
    63     }
    64 
    65     chdir("..");
    66 
    67     closedir(dp);
    68 
    69 }
    70 
    71  
    72 
    73 int main(int argc, char* argv[])
    74 
    75 {
    76 
    77     char *topdir, pwd[2]=".";
    78 
    79     if (argc < 2)
    80 
    81         topdir=pwd;
    82 
    83     else
    84 
    85         topdir=argv[1];
    86 
    87     printf("Directory scan of %s
    ",topdir);
    88 
    89     printdir(topdir,0);
    90 
    91     printf("done.
    ");
    92 
    93     exit(0);
    94 
    95 }
    View Code

    4标准输入/输出流

    在进程一开始运行,就自动打开了三个对应设备的文件,它们是标准输入、输出、错误流,分别用全局文件指针stdin、stdout、stderr表示,stdin具有可读属性,缺省情况下是指从键盘的读取输入,stdout和stderr具有可写属性,缺省情况下是指向屏幕输出数据。

    示例:

     1 #include <stdio.h>
     2 
     3 #include <unistd.h>
     4 
     5 int main()
     6 
     7 {
     8 
     9     char szBuf[32];
    10 
    11     printf("Input string:");     //向屏幕输出一字符串
    12 
    13     fgets(szBuf,sizeof(szBuf),stdin);//从键盘读入一行字符串
    14 
    15     fprintf(stdout,"The string is:%s",szBuf);//向屏幕输出一行字符串
    16 
    17     return 0;
    18 
    19 }
    View Code
  • 相关阅读:
    Thread与Handler
    开始机顶盒的生涯
    解决布局被键盘顶的难题
    自动滚动的Textview
    2-解决粘包问题
    1-socket编程
    zipfile模块
    subprocess模块
    day31-异常处理
    collections模块
  • 原文地址:https://www.cnblogs.com/cpsmile/p/4377991.html
Copyright © 2020-2023  润新知