读取大型 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,但它不是为数据保留单个缓冲区,而是有可能更小的数组。如果您正在插入数据并且数组已满,则将分配和链接额外的数组而不复制以前的数据。 然而,这有一个很小的代价,数据访问需要两个指针解引用而不是一个。