FileUtil.h——文件工具类

这个文件有两个类:

  1. AppendFile
    这个类主要是将数据写入到文件
  2. ReadSmallFile
    这个类主要是将文件内容读取出来

AppendFile

成员变量

  1. FILE* _fp
    打开的流
  2. char _buffer[64*1024]
    打开流的缓冲区
  3. size_t wtirrenBytes
    已经添加的长度

构造函数

该类的构造函数代开一个文件流,并为这个流设置缓冲区。

AppendFile(StringArg filename)
  :_fp(fopen(filename.c_str(), "ae")),
  _writtenBytes(0)  
{
    assert(fp_);
  ::setbuffer(_fp, _buffer, sizeof _buffer);
}

这里fopen的mode使用的aea表示以添加的方式打开流。
e书上没有,代码中注释以O_CLOEXEC打开文件,说是当exce()以后,文件流自动关闭,还是原子操作。
不懂。

fopen的打开的文件,如果不存在,那么直接会创建一个。

setbuffer()和setbuf():后者少一个参数,缓冲区的长度。
这两个函数都是设置缓冲为全缓冲。也就是当缓冲区被填满以后才会实际写到文件中。
还有一个setvbuf()这个函数参数更多,通过mode可以设置缓冲的类型。

write()

该函数执行向流中写数据的操作,但不直接调用该函数

size_t write(const char* log, size_t len)
{
  return fwrite_unlocked(log, 1, len, _fp);
}

fwrite_unlocked(void *, size_t , size_t , FILE )和fwrite()是相同的函数,前者不是线程安全的。
作用是,一次读写一个结构,而且可以包含有NULL。
第一个参数是一个void
,通常是数组,之类的。
第二个参数是,一个结构体的大小,第三个参数是写多少个结构体
第四个参数是要写入的流。
总是从头开始写,如果要指定从哪一个开始写,可以在第一个参数转换前加上偏移量。

append()

该函数执行实际的写操作,同时确保数据完全写入

int append(const char * log, size_t len)
{
  size_t n=write(log,len);
  size_t remain=len-n;
  //如果没有写完,那么循环往里写入
  while(remain>0)  
  {
    size_t nRe=write(log+n,remain);  //加偏移量
    if(nRe=0)
    {
        int err=ferror(_fp);
        if(err)
        {//输出错误信息,继续执行}
        break;
    }
    n+=nRe;
     remain=len-n;
  }
   _writtenBytes+=len;
}

该函数想文件流中写数据,让有数据没写完时,使用循环向流中写入,当剩余为0时没判断是否出错。
在循环中,使用指针+偏移量的方式指定从第几个结构体开始写。

最后,将总写入的累加。

flush()

该函数提供手动将缓冲区数据写入到文件

void flush()
{
  ::fflush(_fp);
}

还有析构函数关闭流
以上就是该类的全部。

ReadSmallFile

该类提供从文件中读取数据的功能

成员变量

  1. char _buf[]
    缓冲区
  2. int _fd
    文件描述符
  3. int _err
    错误代码

构造函数

构造函数打开文件,只读打开同时也是o_CLOEXCE。并将缓冲区第一个元素设置为\0。为啥要设置?

ReadSmallFile(StringArg filename)
  :fd_(::open(filename.c_str(), O_RDONLY | O_CLOEXEC)),
    err_(0)
{
  _buf[0]='\0';      //这里为什么要设置?
  if(fd<0){ _err=errno;}
}

析构函数

关闭文件描述符

readToString()

该函数读取文件内容,并想和窜入的参数填充数据,文件内容,创建时间等信息。

int readToString(int maxSize, String *content, int64_t *fileSize, int64_t *modifyTime, int64_t *createTime)
{
    //除了前两个,后面的都可以为NULL
    assert(content != NULL);
    if (_fd > 0)
    {
        struct stat statbuf;
        //填充文件信息
        if (::fstat(_fd, &statbuf) == 0)
        {
            //如果是普通文件。
            if (S_ISREG(statbuf.st_mode))
            {
                *fileSize = statbuf.st_size;
                //调整容器的大小到文件的大小
                content->reserve(static_cast(std::min(implicit_cast(maxSize), *fileSize)));
            }
            //如果是文件夹
            else if (S_ISDIR(statbuf.st_mode))
            {
                err = EISDIR;
            }
            //如果传入了,那么就填充
            if (modifyTime)
            {
                *modifyTime = statbuf.st_mtime;
            }
            if (createTime)
            {
                *createTime = statbuf.st_ctime;
            }
        }
        else
        {
            err = errno;
        }

        //文件信息填充好以后,开始将文件的内容读取到给定的结构context中。

        while (context.size() < maxSize)
        {
                         //每次读取的大小是,剩余最大和缓冲区的大小。
            size_t toRead = std::min(maxSize - context.size(), sizeof(_buf));
            size_t n = read(_fd, _buf, toRead);
            if (n > 0)
            {
                context.append(_buf, n);
            }
            else
            {c_
                if (n < 0)
                {
                    err = errno;
                }
                break;
            }
        }
    }
    return err;
}

第一个参数的意义应该是给定,最大要读取的大小。
函数前半部分,读取文件信息,然后对给定的参数进行填充。
同时设置context的大小为,maxSize和文件大小中较小的那个。

然后后面同样使用while循环进行填充数据。

readToBuffer()

这个函数只是读取_buf大小的数据。同样使用循环。


int readToBuffer(int* size)
{
    int err=0;
    if(_fd>0)
    {
        size_t n=pread(_fd,_buf,size(_buf)-1,0);
        if(n>=0)
        {
            if(size)
            {
                *size=n;
            }
            buf[n]='\0';    
        }else{
            err=errno;
        }
    }
    return err;
}

pread函数和read函数是同一个功能,但是pread函数多一个参数,是一个偏移量。同时还是一个原子操作。

这个文件夹中还有一些函数。范型的,没有定义,没看。

这里使用的参数stringArg全都是muduo自己封装的类。
类中,只有构造函数,拷贝复制函数,c_str(),同时还有一个成员变量char *
为了效率不择手段啊。

你可能感兴趣的:(FileUtil.h——文件工具类)