我有一个程序可以从一个非常大的二进制文件 (48 MB) 中读取数据,然后将数据传递给一个名为 pixel 的自定义结构矩阵:
struct pixel {
int r;
int g;
int b;
};
打开文件:
ifstream myFile(inputPath, ios::binary);
pixel **matrixPixel;
文件的读取是这样完成的:
int position = 0;
for (int i = 0; i < HEIGHT; ++i) {
for (int j = 0; j < WIDTH; ++j) {
if (!myFile.eof()) {
myFile.seekg(position, ios::beg);
myFile.read((char *) &matrixPixel[i][j].r, 1); // red byte
myFile.seekg(position + HEIGHT * WIDTH, ios::beg);
myFile.read((char *) &matrixPixel[i][j].g, 1); // green byte
myFile.seekg(position + HEIGHT * WIDTH * 2, ios::beg);
myFile.read((char *) &matrixPixel[i][j].b, 1); // blue byte
++position;
}
}
}
myFile.close();
问题是,对于像开头那个这样的大文件,需要花费很多时间(~7 分钟)并且应该对其进行优化。我怎样才能在更短的时间内读取文件?
最佳答案
因此,您存储在内存中的数据结构如下所示:
rgbrgbrgbrgbrgbrgbrgbrgbrgbrgb..............rgb
但是您正在阅读的文件结构如下所示(假设您的代码逻辑正确):
rrrrrrrrrrrrrrrrrrrrrrrrrrr....
ggggggggggggggggggggggggggg....
bbbbbbbbbbbbbbbbbbbbbbbbbbb....
在您的代码中,您在两者之间进行转换。从根本上说,这会很慢。而且,您已选择通过手动搜索文件中的任意点来读取文件。这会进一步减慢速度。
您可以做的第一件事是简化硬盘读取:
for(int channel = 0; channel < 3; channel++) {
for (int i = 0; i < HEIGHT; ++i) {
for (int j = 0; j < WIDTH; ++j) {
if (!myFile.eof()) {
switch(channel) {
case 0: myFile.read((char *) &matrixPixel[i][j].r, 1); break;
case 1: myFile.read((char *) &matrixPixel[i][j].g, 1); break;
case 2: myFile.read((char *) &matrixPixel[i][j].b, 1); break;
}
}
}
}
}
这需要对您的代码进行最少的更改,并且会加快您的代码速度,但代码可能仍然很慢。
一种增加 CPU 使用率但显着减少硬盘使用率(在绝大多数应用程序中会导致加速)的更好方法是像这样存储数据:
std::vector<unsigned char> reds(WIDTH * HEIGHT);
std::vector<unsigned char> greens(WIDTH * HEIGHT);
std::vector<unsigned char> blues(WIDTH * HEIGHT);
myFile.read(reds.data(), WIDTH * HEIGHT); //Stream can be checked for errors resulting from EOF or other issues.
myFile.read(greens.data(), WIDTH * HEIGHT);
myFile.read(blues.data(), WIDTH * HEIGHT);
std::vector<pixel> pixels(WIDTH * HEIGHT);
for(size_t index = 0; index < WIDTH * HEIGHT; index++) {
pixels[index].r = reds[index];
pixels[index].g = greens[index];
pixels[index].b = blues[index];
}
最终的最佳方法是更改二进制文件的格式化方式,因为它的格式化方式看起来很疯狂(从性能角度来看)。如果文件被重新格式化为 rgbrgbrgbrgbrgb
风格(这在行业中更为标准),您的代码将简单地变成这样:
struct pixel {
unsigned char red, green, blue;
}; //You'll never read values above 255 when doing byte-length color values.
std::vector<pixel> pixels(WIDTH * HEIGHT);
myFile.read(reinterpret_cast<char*>(pixels.data()), WIDTH * HEIGHT * 3);
这是非常短的,并且可能会胜过所有其他方法。但当然,这可能不适合您。
我没有测试过这些方法中的任何一个(可能会有一两个错字),但所有这些方法都应该比您目前正在做的更快。
关于c++ - 性能读取二进制文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40594263/