Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/131.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 写入文件中间(不覆盖数据)_C++_Windows_Winapi - Fatal编程技术网

C++ 写入文件中间(不覆盖数据)

C++ 写入文件中间(不覆盖数据),c++,windows,winapi,C++,Windows,Winapi,在windows中,是否可以通过API写入文件的中间部分而不覆盖任何数据,也不必重写之后的所有内容 如果有可能的话,我相信它显然会将文件分割成碎片;在它成为严重问题之前,我可以做多少次 如果不可能,通常采取什么方法/解决方法?在插入点之后重新写入所有内容对于大文件(即千兆字节)来说很快就会变得禁止 注意:我不得不写到中间。把应用程序想象成一个文本编辑器,用户在其中键入内容然后保存。我也不能将文件拆分为几个较小的文件。如果您需要的中间结果是一个平面文件,而该文件可以由编辑器以外的其他应用程序使用

在windows中,是否可以通过API写入文件的中间部分而不覆盖任何数据,也不必重写之后的所有内容

如果有可能的话,我相信它显然会将文件分割成碎片;在它成为严重问题之前,我可以做多少次

如果不可能,通常采取什么方法/解决方法?在插入点之后重新写入所有内容对于大文件(即千兆字节)来说很快就会变得禁止



注意:我不得不写到中间。把应用程序想象成一个文本编辑器,用户在其中键入内容然后保存。我也不能将文件拆分为几个较小的文件。

如果您需要的中间结果是一个平面文件,而该文件可以由编辑器以外的其他应用程序使用,我不知道有什么方法可以做到这一点。如果您希望生成一个平面文件,那么必须从更改点到文件末尾对其进行更新,因为它实际上只是一个顺序文件

但斜体字的出现是有充分理由的。如果可以控制文件格式,则可以使用一些选项。某些版本的MS Word具有快速保存功能,它们不重写整个文档,而是在文件末尾追加增量记录。然后,当重新读取文件时,它会按顺序应用所有增量,以便最终得到正确的文件。如果保存的文件必须立即可用于另一个不了解文件格式的应用程序,那么这显然不起作用

我建议不要将文件存储为文本。使用一个可以有效编辑和保存的中间表单,然后使用一个步骤将其转换为不经常使用的文本文件(例如,在编辑器退出时)。这样,用户可以节省他们想要的,但时间昂贵的操作不会有太大的影响

除此之外,还有其他一些可能性

内存映射(而不是加载)文件可以提供效率,从而加快速度。您可能仍然需要重写到文件的末尾,但这将在操作系统的较低级别上发生


如果希望快速保存的主要原因是开始让用户继续工作(而不是让文件可用于其他应用程序),则可以将保存操作分包到单独的线程,并立即将控制权返回给用户。然后,您需要在两个线程之间进行同步,以防止用户修改尚未保存到磁盘的数据。

我不确定您的文件的格式,但您可以将其设置为基于“记录”

  • 将数据分块写入,并为每个块指定一个id
  • Id可以是文件中的数据偏移量
  • 在文件的开头,您可以 有一个带有ID列表的标题,所以 您可以在中读取记录 秩序
  • 在“id列表”的末尾,您可以指向文件中存储另一个id列表的另一个位置(以及id/偏移量)
类似于文件系统的东西

要添加新数据,请将它们附加到末尾并更新索引(将id添加到列表)

您必须弄清楚如何处理删除记录和更新


如果记录大小相同,则要删除,您可以将其标记为空,然后下次使用适当的索引表更新重新使用它。

如果使用.NET 4,请尝试内存映射文件,如果您有一个类似于编辑器的应用程序-可能是jsut。类似这样的内容(我没有将其键入VS,因此不确定语法是否正确):

MemoryMappedFile bigFile=MemoryMappedFile.CreateFromFile(
新文件流(@“C:\bigfile.dat”,FileMode.Create),
“BigFileMemMapped”,
1024 * 1024,
MemoryMappedFileAccess.ReadWrite);
MemoryMappedViewAccessor视图=MemoryMapped.CreateViewAccessor();
整数偏移=100000000;
view.Write(偏移量,参考MyObject);

现实的答案是否定的。您唯一真正的选择是从修改的角度重新编写,或者构建一种更复杂的格式,使用索引之类的东西告诉您如何按预定顺序排列记录

从纯理论的角度来看,你可以在适当的情况下做这件事。使用FAT(例如,但大多数其他文件系统至少有某种程度的相似性),您可以直接操作FAT。FAT基本上是组成文件的集群的链接列表。您可以修改该链接列表以在文件中间添加一个新的集群,然后将新的数据写入您添加的那个群集。
请注意,我说的纯粹是理论上的。在MS-DOS这样一个完全不受保护的系统下进行这种操作是很困难的,但接近合理。对于大多数较新的系统,进行修改通常是相当困难的。大多数现代文件系统也(相当)比FAT复杂,这将给实现增加更多的困难。从理论上讲,这仍然是可能的——事实上,现在想一想,这曾经几乎是合理的,这简直是疯了。

也许最有效的方法是调用
ReadFileScatter()
在插入点前后读取块,将新数据插入到<代码>的中间文件FielyStEngEngEng[[ 3 ] < /Cord>列表中,并调用<代码> WrreFieleGrace>>(<)/代码>。是的,这涉及到移动磁盘上的字节。但是你可以把最难的部分留给操作系统。

我注意到paxdiablo关于处理其他应用程序的回答,以及Matteo Italia关于可安装文件系统的评论。这让我意识到还有另一个非平凡的解决方案

使用重分析点,可以从基础文件和增量创建“虚拟”文件。任何不知道此方法的应用程序都会看到连续的字节范围,因为增量是由文件系统过滤器动态应用的。对于小增量(对于内存映射,总计+1
MemoryMappedFile bigFile = MemoryMappedFile.CreateFromFile(
   new FileStream(@"C:\bigfile.dat", FileMode.Create),
       "BigFileMemMapped",
       1024 * 1024,
       MemoryMappedFileAccess.ReadWrite);
MemoryMappedViewAccessor view = MemoryMapped.CreateViewAccessor();
int offset = 1000000000;
view.Write<ObjectType>(offset, ref MyObject);