文件频繁读写优化函数

频繁的io读写容易降低程序的效率,避免的此类情况的核心思路是减少io次数,从io中读取足够长度的数据缓存到缓冲区,从缓冲区读取。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define PPS_BUFFER_FILE_NAME_LEN    128

typedef struct file_buffer_t {
    char file_name[128];
    char *buffer;
    int buffer_size;
    int buffer_len;
    int file_start_pos;
    int file_end;
    int offset;
} FILE_BUF;


FILE_BUF *pps_buf_init(char *file_name, int buffer_size)
{
    FILE_BUF *p = NULL;
    int file_name_len = 0;

    file_name_len = strlen(file_name);
    if (file_name == NULL || file_name_len == 0 || buffer_size <= 0) {
        printf("invalid parameters!\n");
        return NULL;
    }

    p = calloc(sizeof(FILE_BUF), 1);
    if (p == NULL) {
        printf("Apply struct memory failed!\n");
        return NULL;
    }

    if (file_name_len > PPS_BUFFER_FILE_NAME_LEN) {
        printf("buffer file name can't exceed %d\n", PPS_BUFFER_FILE_NAME_LEN);
        free(p);
        return NULL;
    }

    strncpy(p->file_name, file_name, file_name_len);
    p->buffer_size = buffer_size;

    p->buffer = calloc(buffer_size, 1);
    if (p->buffer == NULL) {
        printf("Apply buffer memory failed!\n");
        free(p);
        return NULL;
    }
    return p;
}

int pps_buf_deinit(FILE_BUF *fbp)
{

    if (fbp == NULL)
        return -1;

    if (fbp->buffer != NULL) {
        free(fbp->buffer);
        fbp->buffer = NULL;
    }

    free(fbp);
    return 0;
}

int pps_buf_read(char *buf, int size, int count, FILE_BUF *fbp)
{
    int ret = -1, readlen = 0;

    if (fbp == NULL || fbp->buffer == NULL) {
        printf("error FILE_BUF pointer, pelease init first!\n");
        return -1;
    }

    readlen = size * count;
    if (readlen > fbp->buffer_size) {
        printf("read len can't exceed buffer size!\n");
        return -1;
    }

    if (fbp->file_end && fbp->offset == fbp->buffer_len)
        return -1;

    if (fbp->buffer_len == 0 || fbp->offset + readlen > fbp->buffer_size) {
        FILE *fp = NULL;
        fp = fopen(fbp->file_name, "r");
        if (fp == NULL) {
            printf("open file [%s] failed", fbp->file_name);
            return -1;
        } else {
            printf("open and read file %s\n", fbp->file_name);
        }

        ret = fseek(fp, fbp->file_start_pos + fbp->offset , SEEK_SET);
        if (ret) {
            printf("seek file pos filed!\n");
            fclose(fp);
            return -1;
        }
        ret = fread(fbp->buffer, 1, fbp->buffer_size, fp);
        if (ret != fbp->buffer_size) {
            if (feof(fp)) {
                fbp->file_start_pos = fbp->file_start_pos + fbp->offset;
                fbp->offset = 0;
                fbp->buffer_len = ret;
                fbp->file_end = 1;
            } else {
                printf("read file [%s] filed!\n", fbp->file_name);
                fclose(fp);
                return -1;
            } 
        } else {
            fbp->file_start_pos = fbp->file_start_pos + fbp->offset;
            fbp->offset = 0;
            fbp->buffer_len = ret;
        }
        fclose(fp);
    }

    if (fbp->offset + readlen > fbp->buffer_len) {
        readlen = fbp->buffer_len - fbp->offset;
    }
    memcpy(buf, fbp->buffer + fbp->offset, readlen);
    fbp->offset += readlen;
    return readlen;
}

int main(int argc, char *argv[])
{
    int ret = -1;
    FILE_BUF *fbp = NULL;
    char str[256];

    fbp = pps_buf_init("data.txt", 32*1024);
    if (fbp == NULL) {
        printf("error init\n");
        return -1;
    }
    while (pps_buf_read(str, 1, 128, fbp) != -1) {
        printf("[ %s ]\n", str);
    }

    pps_buf_deinit(fbp);
    printf("Hello World!\n");

    return 0;
}

猜你喜欢

转载自blog.csdn.net/u014436243/article/details/80283681