频繁的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;
}