gpt4 book ai didi

c++ - 访问文件中的单个字符效率低下? (C++)

转载 作者:可可西里 更新时间:2023-11-01 17:37:12 25 4
gpt4 key购买 nike

我一直认为在处理文本文件时,首先将内容(或其中的一部分)读入 std::string 或 char 数组会更有效,因为——根据我有限的理解——文件被读取从比单个字符大得多的 block 中的内存中提取。但是,我听说现代操作系统实际上通常并不直接从文件中读取数据,这使得我手动缓冲输入几乎没有什么好处。

假设我想确定文本文件中某个字符的数量。以下会不会效率低下?

while (fin.get(ch)) {
if (ch == 'n')
++char_count;
}

当然,我想这取决于文件大小,但有没有人对什么是最佳方法有任何一般规则?

最佳答案

这里很大程度上取决于性能对您/您的应用程序的真正关键程度。这反过来往往取决于您要处理的文件有多大——如果您要处理几十或几百千字节的文件,您通常应该只编写最简单的代码,而不用太担心它 -- 您可以做的任何事情基本上都是瞬时的,因此优化代码不会真正完成很多事情。

另一方面,如果您要处理大量数据——大约数十兆字节或更多,则效率差异可能会变得相当大。除非您采取相当具体的步骤来绕过它(例如使用 read),否则您的所有读取都将被缓冲——但这并不意味着它们都将是相同的速度(或者甚至必须非常接近相同的速度)。

例如,让我们尝试快速测试几种不同的方法,以从根本上完成您所询问的内容:

#include <stdio.h>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <fstream>
#include <time.h>
#include <string>
#include <algorithm>

unsigned count1(FILE *infile, char c) {
int ch;
unsigned count = 0;

while (EOF != (ch=getc(infile)))
if (ch == c)
++count;
return count;
}

unsigned int count2(FILE *infile, char c) {
static char buffer[4096];
int size;
unsigned int count = 0;

while (0 < (size = fread(buffer, 1, sizeof(buffer), infile)))
for (int i=0; i<size; i++)
if (buffer[i] == c)
++count;
return count;
}

unsigned count3(std::istream &infile, char c) {
return std::count(std::istreambuf_iterator<char>(infile),
std::istreambuf_iterator<char>(), c);
}

unsigned count4(std::istream &infile, char c) {
return std::count(std::istream_iterator<char>(infile),
std::istream_iterator<char>(), c);
}

template <class F, class T>
void timer(F f, T &t, std::string const &title) {
unsigned count;
clock_t start = clock();
count = f(t, 'N');
clock_t stop = clock();
std::cout << std::left << std::setw(30) << title << "\tCount: " << count;
std::cout << "\tTime: " << double(stop-start)/CLOCKS_PER_SEC << "\n";
}

int main() {
char const *name = "test input.txt";

FILE *infile=fopen(name, "r");

timer(count1, infile, "ignore");

rewind(infile);
timer(count1, infile, "using getc");

rewind(infile);
timer(count2, infile, "using fread");

fclose(infile);

std::ifstream in2(name);
in2.sync_with_stdio(false);
timer(count3, in2, "ignore");

in2.clear();
in2.seekg(0);
timer(count3, in2, "using streambuf iterators");

in2.clear();
in2.seekg(0);
timer(count4, in2, "using stream iterators");

return 0;
}

我用一个大约 44 兆字节的文件作为输入来运行它。用VC++2012编译时,得到如下结果:

ignore                          Count: 400000   Time: 2.08
using getc Count: 400000 Time: 2.034
using fread Count: 400000 Time: 0.257
ignore Count: 400000 Time: 0.607
using streambuf iterators Count: 400000 Time: 0.608
using stream iterators Count: 400000 Time: 5.136

使用相同的输入,但使用 g++ 4.7.1 编译:

ignore                          Count: 400000   Time: 0.359
using getc Count: 400000 Time: 0.339
using fread Count: 400000 Time: 0.243
ignore Count: 400000 Time: 0.697
using streambuf iterators Count: 400000 Time: 0.694
using stream iterators Count: 400000 Time: 1.612

因此,即使所有读取都被缓冲,我们看到 g++ 的变化约为 8:1,而 VC++ 的变化约为 20:1。当然,我还没有测试(甚至接近)读取输入的所有可能方式。如果我们测试更多的阅读技巧,我怀疑我们会看到更广泛的时间范围,但我对此可能是错的。无论我们是否这样做,我们都看到了足够多的变化,至少如果您正在处理大量数据,您很可能有理由选择一种技术而不是另一种技术来提高处理速度。

关于c++ - 访问文件中的单个字符效率低下? (C++),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13808714/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com