读取大型 txt 文件时在结构内动态分配向量
Dynamic allocation of a vector inside a struct while reading a large txt file
我目前正在学习C++语言,需要阅读一个包含5000多个double类型数字的文件。由于 push_back
将在分配新数据时制作副本,因此我试图找出一种减少计算工作的方法。请注意,该文件可能包含随机数的双精度类型,因此通过指定足够大的向量来分配内存并不是寻找的解决方案。
我的想法是快速读取整个文件并获取数组的近似大小。在?发现一个有趣的想法,可以在下面的代码中找到。
基本上,包含文件数据的向量被插入到名为 PathStruct
的结构类型中。请记住 PathStruct
包含的内容比此向量更多,但为了简单起见,我删除了所有其余内容。该函数接收 PathStruct
指针的引用并读取文件。
struct PathStruct
{
std::vector<double> trivial_vector;
};
bool getFileContent(PathStruct *&path)
{
std::ifstream filename("simplePath.txt", std::ios::in | std::ifstream::binary);
if (!filename.good())
return false;
std::vector<char> buffer{};
std::istreambuf_iterator<char> iter(filename);
std::istreambuf_iterator<char> end{};
std::copy(iter, end, std::back_inserter(buffer));
path->trivial_vector.reserve(buffer.size() / sizeof(double));
memcpy(&path->trivial_vector[0], &buffer[0], buffer.size());
return true;
};
int main(int argc, char **argv)
{
PathStruct *path = new PathStruct;
const int result = getFileContent(path);
return 0;
}
当我运行代码时,编译器给出以下错误:
corrupted size vs. prev_size, Aborted (core dumped).
我认为我的问题在于指针的使用不正确。绝对不是我的强项,但我找不到问题所在。我希望有人能帮助这个可怜的灵魂。
如果您的文件只包含连续的double 值,您可以检查文件大小并将其除以double 大小。要确定文件大小,您可以使用 std::filesystem::file_size but this function is available from C++ 17. If you cannot use C++ 17, you can find other methods for determining file size here
auto fileName = "file.bin";
auto fileSize = std::filesystem::file_size(fileName);
std::ifstream inputFile("file.bin", std::ios::binary);
std::vector<double> values;
values.reserve(fileSize / sizeof(double));
double val;
while(inputFile.read(reinterpret_cast<char*>(&val), sizeof(double)))
{
values.push_back(val);
}
或使用指针:
auto numberOfValues = fileSize / sizeof(double);
std::vector<double> values(numberOfValues);
// Notice that I pass numberOfValues * sizeof(double) as a number of bytes to read instead of fileSize
// because the fileSize may be not divisable by sizeof(double)
inputFile.read(reinterpret_cast<char*>(values.data()), numberOfValues * sizeof(double));
备选
如果可以修改文件结构,可以在文件开头添加若干个double值,在读入double值前读取这个数。这样,您将始终知道要读取的值的数量,而无需检查文件大小。
备选方案 2
您还可以将容器从 std::vector 更改为 std::deque。此容器类似于 std::vector,但它不是为数据保留单个缓冲区,而是有可能更小的数组。如果您正在插入数据并且数组已满,则将分配和链接额外的数组而不复制以前的数据。
然而,这有一个很小的代价,数据访问需要两个指针解引用而不是一个。
我目前正在学习C++语言,需要阅读一个包含5000多个double类型数字的文件。由于 push_back
将在分配新数据时制作副本,因此我试图找出一种减少计算工作的方法。请注意,该文件可能包含随机数的双精度类型,因此通过指定足够大的向量来分配内存并不是寻找的解决方案。
我的想法是快速读取整个文件并获取数组的近似大小。在
基本上,包含文件数据的向量被插入到名为 PathStruct
的结构类型中。请记住 PathStruct
包含的内容比此向量更多,但为了简单起见,我删除了所有其余内容。该函数接收 PathStruct
指针的引用并读取文件。
struct PathStruct
{
std::vector<double> trivial_vector;
};
bool getFileContent(PathStruct *&path)
{
std::ifstream filename("simplePath.txt", std::ios::in | std::ifstream::binary);
if (!filename.good())
return false;
std::vector<char> buffer{};
std::istreambuf_iterator<char> iter(filename);
std::istreambuf_iterator<char> end{};
std::copy(iter, end, std::back_inserter(buffer));
path->trivial_vector.reserve(buffer.size() / sizeof(double));
memcpy(&path->trivial_vector[0], &buffer[0], buffer.size());
return true;
};
int main(int argc, char **argv)
{
PathStruct *path = new PathStruct;
const int result = getFileContent(path);
return 0;
}
当我运行代码时,编译器给出以下错误:
corrupted size vs. prev_size, Aborted (core dumped).
我认为我的问题在于指针的使用不正确。绝对不是我的强项,但我找不到问题所在。我希望有人能帮助这个可怜的灵魂。
如果您的文件只包含连续的double 值,您可以检查文件大小并将其除以double 大小。要确定文件大小,您可以使用 std::filesystem::file_size but this function is available from C++ 17. If you cannot use C++ 17, you can find other methods for determining file size here
auto fileName = "file.bin";
auto fileSize = std::filesystem::file_size(fileName);
std::ifstream inputFile("file.bin", std::ios::binary);
std::vector<double> values;
values.reserve(fileSize / sizeof(double));
double val;
while(inputFile.read(reinterpret_cast<char*>(&val), sizeof(double)))
{
values.push_back(val);
}
或使用指针:
auto numberOfValues = fileSize / sizeof(double);
std::vector<double> values(numberOfValues);
// Notice that I pass numberOfValues * sizeof(double) as a number of bytes to read instead of fileSize
// because the fileSize may be not divisable by sizeof(double)
inputFile.read(reinterpret_cast<char*>(values.data()), numberOfValues * sizeof(double));
备选
如果可以修改文件结构,可以在文件开头添加若干个double值,在读入double值前读取这个数。这样,您将始终知道要读取的值的数量,而无需检查文件大小。
备选方案 2
您还可以将容器从 std::vector 更改为 std::deque。此容器类似于 std::vector,但它不是为数据保留单个缓冲区,而是有可能更小的数组。如果您正在插入数据并且数组已满,则将分配和链接额外的数组而不复制以前的数据。 然而,这有一个很小的代价,数据访问需要两个指针解引用而不是一个。