博客文章

Linux C 文件管理

作者: andy.      时间: 2016-08-13 11:33:14

介绍一下Linux下C语言的文件管理。很简单,很基础的。

文件的打开操作有系统调用和标准库的调用两种,用man命令可以很清楚看到他们的用法和区别。说一下有意思的地方吧,比如fread,看看man的描述:

NAME
       fread, fwrite - binary stream input/output

SYNOPSIS
       #include <stdio.h>

       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);

DESCRIPTION
       The  function  fread()  reads  nmemb elements of data, each size bytes
       long, from the stream pointed to by stream, storing them at the  loca‐
       tion given by ptr.

       The  function  fwrite() writes nmemb elements of data, each size bytes
       long, to the stream pointed to by  stream,  obtaining  them  from  the
       location given by ptr.

       For nonlocking counterparts, see unlocked_stdio(3).

实际的读取大小为size*nmemb的量,返回的事读到的nmemb的数量。比如size = 10,nmemb = 20,但是只读到了199的数据,小于size*nmemb的200,那么返回值为19,而不是20。感觉上面的描述对这点儿的描述不是那么的清楚。蛮有意思的。

开一个简单的写日志的代码,读取时间什么的,写文件。直接看函数吧,都是一些函数的调用,没什么其他的:

void Write_Log(const char * message){
        time_t now_date;
        struct tm * now_time;
        char filename[20];
        char s_message[1024];

        time(&now_date);
        now_time = localtime(&now_date);

        char s_time[20];
        sprintf(s_time, "%4d-%d-%d %d:%d:%d", now_time->tm_year + 1900, now_time->tm_mon + 1, now_time->tm_mday, now_time->tm_hour, now_time->tm_min, now_time->tm_sec);
        sprintf(s_message, "%s %s\n", s_time, message);
        sprintf(filename, "%d%d%d.log", now_time->tm_year + 1900, now_time->tm_mon + 1, now_time->tm_mday);

        FILE * file = fopen(filename, "a+");
        if ( file == NULL ) {
                perror("Open log file error.");
                return;
        }
        fputs(s_message, file);
        fclose(file);
}

对用户输入的路径进行判断,是文件还是目录。列出目录的文件等等。都是很简单的函数调用,看代码吧:

int main(int argc, char * argv[]){
        if(argc < 2){
                Write_Log("Path is error.");
                return -1;
        }
        struct stat file_stat;
        if(stat(argv[1], &file_stat) == -1){
                Write_Log(strerror(errno));
                return -1;
        }
        if(S_ISREG(file_stat.st_mode)){
                char string[1024];
                memset(string, 0, sizeof(string));
                FILE * file = fopen(argv[1], "r");
                fread(string, 1, 1023, file);
                printf("%s\n", string);
        }
        if(S_ISDIR(file_stat.st_mode)){
                DIR * dir;
                struct dirent * dirent_pointer;
                dir = opendir(argv[1]);
                if(dir == NULL){
                        Write_Log(strerror(errno));
                        return -1;
                }

                while((dirent_pointer = readdir(dir)) != NULL){
                        printf("%c %s\n", dirent_pointer->d_type, dirent_pointer->d_name);
                }
        }
        Write_Log("Complete");
}

通过man可以看到stat函数的用法:

stat

同时,里面也有stat这个结果的结构:

struct stat {
               dev_t     st_dev;         /* ID of device containing file */
               ino_t     st_ino;         /* inode number */
               mode_t    st_mode;        /* protection */
               nlink_t   st_nlink;       /* number of hard links */
               uid_t     st_uid;         /* user ID of owner */
               gid_t     st_gid;         /* group ID of owner */
               dev_t     st_rdev;        /* device ID (if special file) */
               off_t     st_size;        /* total size, in bytes */
               blksize_t st_blksize;     /* blocksize for filesystem I/O */
               blkcnt_t  st_blocks;      /* number of 512B blocks allocated */

               /* Since Linux 2.6, the kernel supports nanosecond
                  precision for the following timestamp fields.
                  For the details before Linux 2.6, see NOTES. */

               struct timespec st_atim;  /* time of last access */
               struct timespec st_mtim;  /* time of last modification */
               struct timespec st_ctim;  /* time of last status change */

           #define st_atime st_atim.tv_sec      /* Backward compatibility */
           #define st_mtime st_mtim.tv_sec
           #define st_ctime st_ctim.tv_sec
           };

每个成员的意思,通过相应的成员我们可以得到文件大小等等信息。同时,通过相应的宏调用可以判断文件的类型:

stat

这些都是给得蛮清楚的。

运行一下上面的代码,结果如下:

[[email protected] filem]# make
gcc -o a.out 1.o
[[email protected] filem]# ./a.out 1.c 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

[[email protected] filem]# ./a.out ../filem/
 .
 test.c
 ..
 1.o
 2016812.log
 makefile
 2016813.log
 1.c
 text.txt
 a.out

如果想获取系统的相关信息,其实可以直接读取/proc下面的文件喔~~

[[email protected] proc]# cat cpuinfo 
processor       : 0
vendor_id       : AuthenticAMD
cpu family      : 21
model           : 16
model name      : AMD A