C++中文件数据的动态分配
Dynamic allocation of file data in C++
坦率地说,我的作业非常含糊地说,
"If the file exists, the one-argument constructor allocates memory for the number of records contained in the file and copies them into memory."
现在,在考虑这条指令时,我似乎要分配动态内存/之前/复制数据,这在原则上似乎是不可能的。
据我所知,要动态分配内存,您需要运行时定义要保留的块的大小。
鉴于文件大小或 'entries' 的数量未知,怎么可能分配那么多内存?这个概念不会违背动态分配的目的吗?
明智的解决方案,似乎唯一的选择是解析整个文件,确定大小,然后分配适当数量的内存,然后再次读取文件,将数据复制到分配的内存中。
鉴于这一定是任何读取文件数据的程序中的常见操作,我想知道:将文件加载到 RAM 中的正确或最有效的方法是什么?
读取一次确定大小,然后再次复制的想法似乎效率很低。我假设有一种方法可以跳到文件末尾以确定最大长度,这将使过程更快。或者也许使用静态缓冲区并将其以块的形式加载到 RAM?
是否可以读取所有数据,然后使用移动运算符将其移动到动态内存中?或者使用某种链表可能更有效?
最有效的方法是让操作系统将文件映射到内存。在 OS API 中搜索 "mmap" 或 "memory mapping"。
另一种方法是查找文件末尾并获取位置(tellg()
)。这是文件的大小。在动态内存中分配一个数组或创建一个 std::vector
至少保留此数量的 space.
有些操作系统 API 您可以调用它来获取文件的大小(无需搜索到末尾)。您可以使用此方法,然后动态分配内存或使用 std::vector<char>
.
如果文件不适合内存,您将需要制定计划。
如果您需要将整个文件读入内存,您可以使用 istream::read
使用文件长度。
这完全取决于文件格式。一种存储记录的方法是首先写入文件中存储了多少条记录。如果您有两个 phone 号码,您的文件可能如下所示:
2
Jon
555-123
Mary
555-456
在这种情况下,解决方案很简单:
// ...
is >> count;
record_type *record = new record_type[count];
for ( int i = 0; i < count; ++i )
is >> record[i].name >> record[i].number; // stream checks omitted
// ...
如果文件没有存储记录数(我不会这样做),你就得先数一下,再用上面的解决方法:
// ...
int count = 0;
std::string dummy;
while ( is >> dummy >> dummy )
++count;
is.clear();
is.seekg( 0 );
// ...
第二种情况的第二种解决方案是编写一个动态容器(我假设您不允许使用标准容器)并在读取记录时推送它们:
// ...
list_type list;
record_type r;
while ( is >> r.name >> r.number )
list.push_back( r );
// ...
解决方案按复杂程度排序。我没有编译上面的例子。
坦率地说,我的作业非常含糊地说,
"If the file exists, the one-argument constructor allocates memory for the number of records contained in the file and copies them into memory."
现在,在考虑这条指令时,我似乎要分配动态内存/之前/复制数据,这在原则上似乎是不可能的。
据我所知,要动态分配内存,您需要运行时定义要保留的块的大小。
鉴于文件大小或 'entries' 的数量未知,怎么可能分配那么多内存?这个概念不会违背动态分配的目的吗?
明智的解决方案,似乎唯一的选择是解析整个文件,确定大小,然后分配适当数量的内存,然后再次读取文件,将数据复制到分配的内存中。
鉴于这一定是任何读取文件数据的程序中的常见操作,我想知道:将文件加载到 RAM 中的正确或最有效的方法是什么?
读取一次确定大小,然后再次复制的想法似乎效率很低。我假设有一种方法可以跳到文件末尾以确定最大长度,这将使过程更快。或者也许使用静态缓冲区并将其以块的形式加载到 RAM?
是否可以读取所有数据,然后使用移动运算符将其移动到动态内存中?或者使用某种链表可能更有效?
最有效的方法是让操作系统将文件映射到内存。在 OS API 中搜索 "mmap" 或 "memory mapping"。
另一种方法是查找文件末尾并获取位置(tellg()
)。这是文件的大小。在动态内存中分配一个数组或创建一个 std::vector
至少保留此数量的 space.
有些操作系统 API 您可以调用它来获取文件的大小(无需搜索到末尾)。您可以使用此方法,然后动态分配内存或使用 std::vector<char>
.
如果文件不适合内存,您将需要制定计划。
如果您需要将整个文件读入内存,您可以使用 istream::read
使用文件长度。
这完全取决于文件格式。一种存储记录的方法是首先写入文件中存储了多少条记录。如果您有两个 phone 号码,您的文件可能如下所示:
2
Jon
555-123
Mary
555-456
在这种情况下,解决方案很简单:
// ...
is >> count;
record_type *record = new record_type[count];
for ( int i = 0; i < count; ++i )
is >> record[i].name >> record[i].number; // stream checks omitted
// ...
如果文件没有存储记录数(我不会这样做),你就得先数一下,再用上面的解决方法:
// ...
int count = 0;
std::string dummy;
while ( is >> dummy >> dummy )
++count;
is.clear();
is.seekg( 0 );
// ...
第二种情况的第二种解决方案是编写一个动态容器(我假设您不允许使用标准容器)并在读取记录时推送它们:
// ...
list_type list;
record_type r;
while ( is >> r.name >> r.number )
list.push_back( r );
// ...
解决方案按复杂程度排序。我没有编译上面的例子。