当前位置: 首页 > 工具软件 > Klib > 使用案例 >

C语言-使用klib/kseq.h高效读取行

蒋阳华
2023-12-01

使用klib的kseq.h进行缓冲的行读取,http://attractivechaos.github.io/klib/#Kseq%3A%20stream%20buffer%20and%20FASTA%2FQ%20parser
给的使用案例为

#include <zlib.h>
#include <stdio.h>
#include <stdlib.h>
#include "kseq.h"
KSTREAM_INIT(gzFile, gzread, 16384)

int main(int argc, char *argv[])
{
    gzFile fp; //初始化gz文件
    kstream_t *ks; //初始化流对象
    kstring_t str = {0,0,0}; //初始化字符串结构
    if (argc == 1) {
        fprintf(stderr, "Usage: %s <in.txt>\n", argv[0]);
        return 1;
    }
    fp = gzopen(argv[1], "r");
    ks = ks_init(fp); //将fp赋值给流对象
    while (ks_getuntil(ks, '\n', &str, 0) >= 0) //读取一行, 通过指针将内容传递给str
        printf("%s\n", str.s);
    ks_destroy(ks); //释放内存
    gzclose(fp); //关闭文件
    free(str.s); //释放内存
    return 0;
}

KSTREAM_INIT接受三个参数,文件类型,读取函数__read,缓冲大小,其中读取函数对应的宏为__read(ks->f, ks->buf, __bufsize),也就是__read的第一个参数是文件类型,第二个参数是字符串,第三个是缓冲大小。

kstream_t结构如下,其中type_tKSTREAM_INIT的第一个参数,这里就是gzFile.

typedef struct __kstream_t {
        unsigned char *buf;
        int begin, end, is_eof; 
        type_t f;
    } kstream_t

kstring_t结构包括三个元素,分别是l,m,s.

typedef struct __kstring_t {
    size_t l, m;
    char *s;
} kstring_t

m的用于重新动态的确定char *s的内存大小

if (str->m - str->l < (size_t)(i - ks->begin + 1)) {
    str->m = str->l + (i - ks->begin) + 1;
    kroundup32(str->m);
    str->s = (char*)realloc(str->s, str->m);    
}

l的作用是从将缓冲里内容复制到上一段未完段落字符串的末尾。

memcpy(str->s + str->l, ks->buf + ks->begin, i - ks->begin)

s就是最终的字符串。

ks_getuntil的函数声明为

static inline int ks_getuntil(kstream_t *ks, int delimiter, kstring_t *str, int *dret)

接受四个输入,kstream_t结构地址,分隔符,kstring_t结构地址和返回元素大小。

如果没有zlib,可以用更加底层的open, read, closer

#include <fcntl.h>  //定义了open
#include <unistd.h> //定义了 read, close
#include <stdio.h>
#include <stdlib.h>
#include "klib/kseq.h"


KSTREAM_INIT(int, read, 1000)

int main(int argc, char *argv[])
{
    int fd; // file descriptor
    kstream_t *ks; //初始化流对象
    kstring_t str = {0,0,0}; //初始化字符串结构
    if (argc == 1) {
        fprintf(stderr, "Usage: %s <in.txt>\n", argv[0]);
        return 1;
    }
    fd = open(argv[1], O_RDONLY);
    ks = ks_init(fd); //将fp赋值给流对象
    while (ks_getuntil(ks, '\n', &str, 0) >= 0) //读取一行, 通过指针将内容传递给str
        printf("%s\n", str.s);
    ks_destroy(ks); //释放内存
    close(fd); //关闭文件
    free(str.s); //释放内存
    return 0;
}

推荐阅读:

https://attractivechaos.wordpress.com/2008/10/11/a-generic-buffered-stream-wrapper/

 类似资料: