使用gzbuffer快速读取GZ的文件,然后按行划分内容
Use gzbuffer to read gzipped file quickly and then split content line by line
我想要一个作为输入文件名和字符串向量的函数,并且通过有效读取文件来填充矢量。这是我到目前为止所做的:
/** brief Read the whole file in a vector of lines
*/
int
readFile(
const string & pathToFile,
vector<string> & lines)
{
gzFile stream;
openFile(pathToFile, stream, "rb");
int errnum;
const char * error_msg = NULL;
size_t nb_bytes_to_read = 256000; // 8192 is default for gzbuffer
if(gzbuffer(stream, nb_bytes_to_read) == -1){
error_msg = gzerror(stream, &errnum);
if(errnum != Z_OK){
cerr << "ERROR: gzbuffer failed with " << nb_bytes_to_read
<< " bytes" << endl;
cerr << error_msg << endl;
exit(EXIT_FAILURE);
}
}
size_t buf_len = nb_bytes_to_read;
char * buf = (char *) malloc(buf_len);
if(buf == NULL){
cerr << "ERROR: can't allocate " << nb_bytes_to_read
<< " bytes" << endl;
exit(EXIT_FAILURE);
}
size_t nb_bytes_read = 0, tot_nb_bytes_read = 0;
while(! gzeof(stream)){
nb_bytes_read = gzread(stream, buf + tot_nb_bytes_read,
nb_bytes_to_read);
tot_nb_bytes_read += nb_bytes_read;
if(nb_bytes_read < nb_bytes_to_read && ! gzeof(stream)){
error_msg = gzerror(stream, &errnum);
if(errnum != Z_OK){
cerr << "ERROR: gzread failed on " << pathToFile << endl;
cerr << error_msg << endl;
exit(EXIT_FAILURE);
}
}
if(tot_nb_bytes_read == buf_len){
buf_len += nb_bytes_to_read;
buf = (char*) realloc(buf, buf_len);
if(buf == NULL){
cerr << "ERROR: can't allocate " << nb_bytes_to_read
<< " bytes" << endl;
exit(EXIT_FAILURE);
}
}
}
closeFile(pathToFile, stream);
lines = split(buf, "n", lines);
free(buf);
return 0;
}
gzread
的Zlib文档提到:"如果Gzip流以Gzip流遇到了GZIP流以外的其他内容,则忽略了剩下的落后垃圾(不会返回错误)"。但是,对于某些文件,我上面的代码读为"一行太远"。更具体地说,输出"线"向量具有N元素,而输入文件具有N-1行。结果,"线"向量的最后一个元素可以是" 223(305ŀV"。
我该如何解决?
这是上面代码中使用的其他功能:
void
openFile(
const string & pathToFile,
gzFile & fileStream,
const char * mode)
{
fileStream = gzopen(pathToFile.c_str(), mode);
if(fileStream == NULL){
cerr << "ERROR: can't open file " << pathToFile
<< " with mode " << *mode
<< " (errno=" << errno << ")" << endl;
exit(EXIT_FAILURE);
}
}
void
closeFile(
const string & pathToFile,
gzFile & fileStream)
{
int ret = gzclose(fileStream);
if(ret != Z_OK){
cerr << "ERROR: can't close the file " << pathToFile
<< ", gzclose() returned " << ret << endl;
exit(EXIT_FAILURE);
}
}
vector<string> &
split(
char * buf,
const char * delim,
vector<string> & tokens)
{
tokens.clear();
char * pch;
pch = strtok(buf, delim);
while(pch != NULL){
tokens.push_back(string(pch));
pch = strtok(NULL, delim);
}
return tokens;
}
(由于我不是专业程序员,欢迎其他建议!)
strtok()
在null终止的字符串上操作。您正在提供一个缓冲区,大概是文本文件。没有空。因此,strtok()
正在读取缓冲区的末端,直到在内存中发现意外零为止。
顺便说一句,strtok()
有问题,甚至没有再入侵。阅读strtok
和strsep
的男人页面。
相关文章:
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 如何声明特征矩阵,然后通过嵌套循环初始化它
- 这是我尝试让用户将值输入到数组中.然后将其隐藏为大量的星号
- boost::asio如何生成多个协同程序,然后加入它们
- 如何将图像传输到c++(dll)中的缓冲区,然后在c#的缓冲区中读/写
- 在std::thread中,joinable()然后join()线程安全吗
- 如何将输出数字划分为奇数和偶数
- C++:如何读取分离变量,然后读取向量
- 为什么我的递归函数按降序打印,然后按升序打印?
- 等待整个 omp 块完成,然后再调用第二个函数
- CMake:如何将库 A 链接到库 B,然后将可执行文件链接到库 A
- 如何存储用户输入的所有数据,然后在他们想要查看所有数据时显示它们
- '{'标记之前的预期类名,然后在预声明时无效使用不完整的类型'class class_name'
- 如何使变量从 x 到 y,然后从 y 返回到 x 并始终重复该过程
- C++无符号短裤的划分导致 int
- 我有一个数组,我想输入一个范围,然后找到范围内所有偶数的总和?
- 如何在 C++ 中将数组划分为不同的数组
- 如何正确地推回然后遍历堆中对象的向量?
- 使用gzbuffer快速读取GZ的文件,然后按行划分内容
- 用getline在字符串中从文件中读取,然后将数字从int数组中的字符串划分