在C++中创建大文件的最快方法是什么?

5

使用C++创建一个大小约为50-100MB的纯文本文件,其中内容应插入4百万次“Added first line”。


我想这一切都取决于您想在文件中包含什么“文本”,以及您所说的“最佳”是什么意思。是最快的吗?我猜重复写入一个包含一些示例文本的缓冲区将最快地让您达到目标。选择缓冲区大小以获得最佳速度需要进行实验。 - Mike G.
1
“Lakh”是印度语中表示一万的词汇。 - ijw
原始问题(已经被彻底修改)要求在文件中重复一个文本块,并想知道写入速度有多快。修改后的问题要求在顶部只有一个字符串。根据下面的答案判断,它可能有其他变化。 - ijw
6个回答

17

使用老式文件IO

fopen 打开用于写入的文件。

fseek 定位到所需文件大小减1的位置。

fwrite 写入单个字节。

fclose 关闭文件。


  1. 忘记了“添加第一行”
  2. 并非所有操作系统/文件系统都会在物理上分配。有些会留下中间块未分配。Raj 应该告诉我们磁盘空间是否真的需要在物理上分配,还是仅逻辑上分配即可。
- blabla999
40 lakhs time 是什么意思? - EvilTeach
哈哈。这回答了原来的问题。自那以后它已经被编辑过了一些。需要一个新的答案。 - EvilTeach
如果你想要这样做,可以使用'man truncate'(适用于路径)或ftruncate(与open()一起使用),它们可以将文件扩展并截断到给定的长度。 - ijw

12

创建特定大小的文件最快的方法是使用creat()open()创建一个零长度的文件,然后使用chsize()更改大小。这将简单地为文件分配磁盘上的块,内容将是那些块中存在的任何内容。由于不需要进行缓冲区写入,因此速度非常快。


1
一个好的操作系统,应该将所有分配的块清零作为安全措施。我注意到Novell Netware在1989年左右就已经这样做了,所以现在所有的操作系统都应该这样做。 - James Curran
1
这取决于操作系统。在大多数Unix系统上,如果您寻求偏移量,然后写入数据,您最终将得到一个“稀疏文件”,其中介于块不占用磁盘空间。 - Alnitak
1
实际上没有分配并填充零块的事实无关紧要。稀疏文件(至少在Unix上)将读取为零,这就是您要寻找的安全性。 - ijw

2

我不确定我是否理解了这个问题。您是否想确保文件中的每个字符都是可打印的ASCII字符?如果是这样,那么这个方法可以实现:用“abcdefghabc....”填充文件。

#include <stdio.h>
int main ()
{
   const int FILE_SiZE = 50000; //size in KB
   const int BUFFER_SIZE = 1024;
   char buffer [BUFFER_SIZE + 1];
   int i;
   for(i = 0; i < BUFFER_SIZE; i++)
      buffer[i] = (char)(i%8 + 'a');
   buffer[BUFFER_SIZE] = '\0';

   FILE *pFile = fopen ("somefile.txt", "w");
   for (i = 0; i < FILE_SIZE; i++)
     fprintf(pFile, buffer);

   fclose(pFile);

   return 0;
}

1

你没有提到操作系统,但我假设creat/open/close/write是可用的。

为了真正高效地写入数据,假设有一个4k页面和磁盘块大小以及重复字符串:

  1. 打开文件。
  2. 分配4k * 重复字符串中字符数的内存,最好对齐到页面边界。
  3. 将重复字符串打印到内存中4k次,精确地填充块。
  4. 使用write()将块写出到磁盘上多次。您可能希望为最后一个块编写部分内容,以使大小正确。
  5. 关闭文件。

这样可以绕过fopen()和其他函数的缓冲区,这既有好处也有坏处:它们的缓冲意味着它们很快,但它们仍然不会像这样高效,因为它没有使用缓冲区的开销。

这可以很容易地用C++或C编写,但假设您将出于效率考虑使用POSIX调用,而不是iostream或stdio,因此它不在核心库规范之内。


我真的很喜欢这个答案,但我是一个愚蠢的C语言新手,这似乎是一个愚蠢的问题,但我们如何对齐到页面边界呢? - Jack G
4k页均匀地从0开始间隔,因此您需要一个可以被4k整除的指针。因此,类似char *a = malloc(8192); char *aligned = (char *)(((size_t)a + 4096) & ~(size_t)4095)这样的东西-如果您喜欢,也可以使用4096-a%4096。您的目标是找到一个比a高但比a + 4096低的舍入数字,该数字可以被4096整除。 - ijw

1

我遇到了同样的问题,在Windows上非常快地创建了一个大约500MB的文件。 你传递给fwrite()的缓冲区越大,速度就越快。

int i;
FILE *fp;

fp = fopen(fname,"wb");

if (fp != NULL) {

    // create big block's data
    uint8_t b[278528]; // some big chunk size

    for( i = 0; i < sizeof(b); i++ ) // custom initialization if != 0x00
    {
        b[i] = 0xFF;
    }

    // write all blocks to file
    for( i = 0; i < TOT_BLOCKS; i++ )
        fwrite(&b, sizeof(b), 1, fp);

    fclose (fp);
}

现在至少在我的Win7,MinGW几乎立即创建文件。 与每次写入1字节的fwrite()相比,它将在10秒内完成。 传递4k缓冲区将在2秒钟内完成。


0

在C++中创建大文件的最快方法是什么? 好的。我假设最快的方式意味着运行时间最短。

使用C ++创建一个大小约为50-100 MB的平面文本文件,其中内容“添加第一行”应插入到文件中4百万次。

使用旧式文件IO预分配文件。

fopen the file for write.
fseek to the desired file size - 1.
fwrite a single byte
fclose the file

create a string containing the "Added first line\n" a thousand times.
find it's length.

使用旧式文件IO预分配文件空间

fopen the file for write.
fseek to the the string length * 4000
fwrite a single byte
fclose the file

open the file for read/write
loop 4000 times, 
    writing the string to the file.
close the file.

那是我最好的猜测。我相信有很多方法可以做到。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接