Как быстро записать большой буфер в двоичный файл на C ++?


242

Я пытаюсь записать огромное количество данных на мой SSD (твердотельный накопитель). И в огромных количествах я имею в виду 80 ГБ.

Я просматривал в Интернете решения, но лучшее, что я придумал, было это:

#include <fstream>
const unsigned long long size = 64ULL*1024ULL*1024ULL;
unsigned long long a[size];
int main()
{
    std::fstream myfile;
    myfile = std::fstream("file.binary", std::ios::out | std::ios::binary);
    //Here would be some error handling
    for(int i = 0; i < 32; ++i){
        //Some calculations to fill a[]
        myfile.write((char*)&a,size*sizeof(unsigned long long));
    }
    myfile.close();
}

Скомпилированная с Visual Studio 2010 с полной оптимизацией и работающая под Windows7, эта программа работает со скоростью около 20 МБ / с. Что действительно беспокоит меня, так это то, что Windows может копировать файлы с другого SSD на этот SSD со скоростью от 150 МБ / с до 200 МБ / с. Так как минимум в 7 раз быстрее. Вот почему я думаю, что я должен быть в состоянии идти быстрее.

Любые идеи, как я могу ускорить свое письмо?


11
Исключили ли ваши результаты хронометража время, необходимое для выполнения вычислений, чтобы заполнить []?
catchmeifyoutry

7
Я на самом деле сделал эту задачу раньше. Используя простой, fwrite()я мог получить около 80% пиковых скоростей записи. Только с этим FILE_FLAG_NO_BUFFERINGя смог достичь максимальной скорости.
Мистик

10
Я не уверен, что будет справедливо сравнивать запись вашего файла с копированием с SSD на SSD. Вполне возможно, что SSD-to-SSD работает на более низком уровне, избегая библиотек C ++ или используя прямой доступ к памяти (DMA). Копирование чего-либо - это не то же самое, что запись произвольных значений в файл с произвольным доступом.
Игорь Ф.

4
@IgorF .: Это просто неправильное предположение; это совершенно справедливое сравнение (если не сказать больше, в пользу записи файлов). Копирование на диск в Windows - это просто чтение и запись; ничего необычного / сложного / другого не происходит под ним.
user541686

5
@MaximYegorushkin: Ссылка или этого не произошло. : P
user541686

Ответы:


233

Это сделал работу (в 2012 году):

#include <stdio.h>
const unsigned long long size = 8ULL*1024ULL*1024ULL;
unsigned long long a[size];

int main()
{
    FILE* pFile;
    pFile = fopen("file.binary", "wb");
    for (unsigned long long j = 0; j < 1024; ++j){
        //Some calculations to fill a[]
        fwrite(a, 1, size*sizeof(unsigned long long), pFile);
    }
    fclose(pFile);
    return 0;
}

Я только что рассчитал 8 ГБ за 36 секунд, что составляет около 220 МБ / с, и я думаю, что это максимум моего SSD. Также стоит отметить, что код в вопросе использовал одно ядро ​​100%, тогда как этот код использует только 2-5%.

Большое спасибо всем.

Обновление : прошло 5 лет, сейчас 2017. Компиляторы, оборудование, библиотеки и мои требования изменились. Вот почему я внес некоторые изменения в код и сделал несколько новых измерений.

Сначала код:

#include <fstream>
#include <chrono>
#include <vector>
#include <cstdint>
#include <numeric>
#include <random>
#include <algorithm>
#include <iostream>
#include <cassert>

std::vector<uint64_t> GenerateData(std::size_t bytes)
{
    assert(bytes % sizeof(uint64_t) == 0);
    std::vector<uint64_t> data(bytes / sizeof(uint64_t));
    std::iota(data.begin(), data.end(), 0);
    std::shuffle(data.begin(), data.end(), std::mt19937{ std::random_device{}() });
    return data;
}

long long option_1(std::size_t bytes)
{
    std::vector<uint64_t> data = GenerateData(bytes);

    auto startTime = std::chrono::high_resolution_clock::now();
    auto myfile = std::fstream("file.binary", std::ios::out | std::ios::binary);
    myfile.write((char*)&data[0], bytes);
    myfile.close();
    auto endTime = std::chrono::high_resolution_clock::now();

    return std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime).count();
}

long long option_2(std::size_t bytes)
{
    std::vector<uint64_t> data = GenerateData(bytes);

    auto startTime = std::chrono::high_resolution_clock::now();
    FILE* file = fopen("file.binary", "wb");
    fwrite(&data[0], 1, bytes, file);
    fclose(file);
    auto endTime = std::chrono::high_resolution_clock::now();

    return std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime).count();
}

long long option_3(std::size_t bytes)
{
    std::vector<uint64_t> data = GenerateData(bytes);

    std::ios_base::sync_with_stdio(false);
    auto startTime = std::chrono::high_resolution_clock::now();
    auto myfile = std::fstream("file.binary", std::ios::out | std::ios::binary);
    myfile.write((char*)&data[0], bytes);
    myfile.close();
    auto endTime = std::chrono::high_resolution_clock::now();

    return std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime).count();
}

int main()
{
    const std::size_t kB = 1024;
    const std::size_t MB = 1024 * kB;
    const std::size_t GB = 1024 * MB;

    for (std::size_t size = 1 * MB; size <= 4 * GB; size *= 2) std::cout << "option1, " << size / MB << "MB: " << option_1(size) << "ms" << std::endl;
    for (std::size_t size = 1 * MB; size <= 4 * GB; size *= 2) std::cout << "option2, " << size / MB << "MB: " << option_2(size) << "ms" << std::endl;
    for (std::size_t size = 1 * MB; size <= 4 * GB; size *= 2) std::cout << "option3, " << size / MB << "MB: " << option_3(size) << "ms" << std::endl;

    return 0;
}

Этот код компилируется с Visual Studio 2017 и g ++ 7.2.0 (новые требования). Я запустил код с двумя настройками:

  • Ноутбук, Core i7, SSD, Ubuntu 16.04, g ++ Версия 7.2.0 с -std = c ++ 11 -march = native -O3
  • Рабочий стол, Core i7, SSD, Windows 10, Visual Studio 2017 версии 15.3.1 с / Ox / Ob2 / Oi / Ot / GT / GL / Gy

Что дало следующие измерения (после сброса значений для 1 МБ, потому что они были очевидными выбросами): введите описание изображения здесь введите описание изображения здесь оба варианта option1 и option3 максимально превышают мой SSD. Я не ожидал, что это увидит, потому что option2 раньше был самым быстрым кодом на моей старой машине.

TL; DR : мои измерения указывают на использование std::fstreamболее FILE.


8
+1 Да, это было первое, что я попробовал. FILE*быстрее, чем потоки. Я бы не ожидал такой разницы, так как она все равно должна была быть связана с вводом / выводом.
Мистик

12
Можно ли сделать вывод, что ввод-вывод в стиле C (как ни странно) намного быстрее, чем потоки C ++?
Щепурин

22
@SChepurin: Если вы педантичны, вероятно нет. Если вы практичны, вероятно, да. :)
user541686

10
Не могли бы вы объяснить (для дурака C ++, как я) разницу между двумя подходами, и почему этот работает намного быстрее, чем оригинал?
Майк Чемберлен

11
Имеет ли предопределение ios::sync_with_stdio(false);какое-либо значение для кода с потоком? Мне просто любопытно, насколько велика разница между использованием этой строки и нет, но у меня нет достаточно быстрого диска для проверки углового случая. И если есть какая-то реальная разница.
Артур Цайка

24

Попробуйте следующее по порядку:

  • Меньший размер буфера. Написание ~ 2 MiB за раз может быть хорошим началом. На моем последнем ноутбуке ~ 512 КиБ было приятным местом, но я еще не тестировал свой SSD.

    Примечание: я заметил, что очень большие буферы имеют тенденцию снижать производительность. Я заметил потерю скорости при использовании буферов по 16 МБ вместо буферов по 512 КБ.

  • Используйте _open(или _topenесли вы хотите, чтобы Windows-корректно), чтобы открыть файл, затем используйте _write. Это, вероятно, позволит избежать большой буферизации, но это не обязательно.

  • Использование специфичных для Windows функций, таких как CreateFileи WriteFile. Это позволит избежать буферизации в стандартной библиотеке.


Проверьте любые результаты тестов, опубликованные в Интернете. Для получения любой приемлемой пропускной способности вам потребуется либо запись 4 КБ с глубиной очереди 32 или более, либо запись 512 КБ или выше.
Бен Фойгт

@BenVoigt: Да, это соотносится со мной, говоря, что 512 КиБ были приятным местом для меня. :)
user541686

Да. По моему опыту, меньшие размеры буфера обычно оптимальны. Исключение составляют случаи, когда вы используете FILE_FLAG_NO_BUFFERINGбуферы большего размера. Так как я думаю FILE_FLAG_NO_BUFFERINGэто в значительной степени DMA.
Мистик

22

Я не вижу разницы между std :: stream / FILE / device. Между буферизацией и без буферизации.

Также обратите внимание:

  • SSD-накопители «склонны» тормозить (снижать скорость передачи) по мере заполнения.
  • SSD-накопители «имеют тенденцию» замедляться (снижать скорость передачи данных) по мере старения (из-за неработающих битов).

Я вижу код запускается в 63 секунды.
Таким образом скорость передачи: 260M / s (мой SSD выглядит немного быстрее, чем ваш).

64 * 1024 * 1024 * 8 /*sizeof(unsigned long long) */ * 32 /*Chunks*/

= 16G
= 16G/63 = 260M/s

Я не получаю увеличения при переходе на FILE * из std :: fstream.

#include <stdio.h>

using namespace std;

int main()
{
    
    FILE* stream = fopen("binary", "w");

    for(int loop=0;loop < 32;++loop)
    {
         fwrite(a, sizeof(unsigned long long), size, stream);
    }
    fclose(stream);

}

Таким образом, поток C ++ работает настолько быстро, насколько позволяет соответствующая библиотека.

Но я думаю, что несправедливо сравнивать ОС с приложением, созданным поверх ОС. Приложение не может делать никаких предположений (оно не знает, что диски являются SSD) и, таким образом, использует файловые механизмы ОС для передачи.

Пока ОС не нужно делать никаких предположений. Он может определять типы используемых дисков и использовать оптимальную технику для передачи данных. В этом случае прямая передача из памяти в память. Попробуйте написать программу, которая копирует 80G из одного места в памяти в другое и посмотрите, насколько это быстро.

редактировать

Я изменил свой код, чтобы использовать вызовы более низкого уровня:
т.е. без буферизации.

#include <fcntl.h>
#include <unistd.h>


const unsigned long long size = 64ULL*1024ULL*1024ULL;
unsigned long long a[size];
int main()
{
    int data = open("test", O_WRONLY | O_CREAT, 0777);
    for(int loop = 0; loop < 32; ++loop)
    {   
        write(data, a, size * sizeof(unsigned long long));
    }   
    close(data);
}

Это не имеет никакого значения.

ПРИМЕЧАНИЕ . Мой диск является диском SSD. Если у вас обычный диск, вы можете увидеть разницу между двумя методами, описанными выше. Но, как я и ожидал, не буферизация и буферизация (при записи больших кусков, превышающих размер буфера) не имеют значения.

Изменить 2:

Вы пробовали самый быстрый способ копирования файлов в C ++

int main()
{
    std::ifstream  input("input");
    std::ofstream  output("ouptut");

    output << input.rdbuf();
}

5
Я не понизил голос, но ваш размер буфера слишком мал. Я сделал это с тем же 512 МБ буфером, который использует OP, и я получаю 20 МБ / с с потоками против 90 МБ / с с FILE*.
Мистика

Также ваш путь с fwrite (a, sizeof (unsigned long long), размер, поток); вместо fwrite (a, 1, size * sizeof (unsigned long long), pFile); дает мне 220 МБ / с с кусками 64 МБ на запись.
Доминик Хофер

2
@Mysticial: Меня удивляет, что размер буфера имеет значение (хотя я вам верю). Буфер полезен, когда у вас много небольших записей, так что основное устройство не беспокоит много запросов. Но когда вы пишете огромные куски, нет необходимости в буфере при записи / чтении (на блокирующем устройстве). Как таковые, данные должны передаваться непосредственно на базовое устройство (таким образом, обходя буфер). Хотя, если вы видите разницу, это противоречит этому и заставляет задуматься, почему запись вообще использует буфер.
Мартин Йорк,

2
Лучшее решение - НЕ увеличивать размер буфера, а удалять буфер и заставлять запись передавать данные непосредственно на базовое устройство.
Мартин Йорк,

1
@Mysticial: 1) Нет маленьких кусочков => Он всегда достаточно большой (в этом примере). В этом случае куски 512M 2) Это SSD-накопитель (как мой, так и OP), поэтому ничего из этого не имеет значения. Я обновил свой ответ.
Мартин Йорк,

13

Лучшее решение - реализовать асинхронную запись с двойной буферизацией.

Посмотрите на временную шкалу:

------------------------------------------------>
FF|WWWWWWWW|FF|WWWWWWWW|FF|WWWWWWWW|FF|WWWWWWWW|

«F» представляет время для заполнения буфера, а «W» представляет время для записи буфера на диск. Так что проблема в том, чтобы тратить время между записью буферов в файл. Однако, реализовав запись в отдельном потоке, вы можете сразу же начать заполнение следующего буфера следующим образом:

------------------------------------------------> (main thread, fills buffers)
FF|ff______|FF______|ff______|________|
------------------------------------------------> (writer thread)
  |WWWWWWWW|wwwwwwww|WWWWWWWW|wwwwwwww|

F - заполнение 1-го буфера
f - заполнение 2-го буфера
W - запись 1-го буфера в файл
w - запись 2-го буфера в файл
_ - ожидание завершения операции

Этот подход с заменой буфера очень полезен, когда заполнение буфера требует более сложных вычислений (следовательно, больше времени). Я всегда реализую класс CSequentialStreamWriter, который скрывает асинхронную запись внутри, поэтому для конечного пользователя интерфейс имеет только функцию Write.

И размер буфера должен быть кратным размеру дискового кластера. В противном случае вы получите низкую производительность, записав один буфер в 2 смежных дисковых кластера.

Запись последнего буфера.
Когда вы в последний раз вызываете функцию Write, вы должны убедиться, что текущий буфер заполняется, и на диск также записывается. Таким образом, CSequentialStreamWriter должен иметь отдельный метод, скажем, Finalize (финальная очистка буфера), который должен записывать на диск последнюю часть данных.

Обработка ошибок.
Хотя код начинает заполнять 2-й буфер, а 1-й пишется в отдельном потоке, но по какой-то причине запись не удалась, основной поток должен знать об этом сбое.

------------------------------------------------> (main thread, fills buffers)
FF|fX|
------------------------------------------------> (writer thread)
__|X|

Давайте предположим, что интерфейс CSequentialStreamWriter имеет функцию Write, возвращает bool или выдает исключение, поэтому при наличии ошибки в отдельном потоке вы должны запомнить это состояние, поэтому в следующий раз, когда вы вызовете Write или Finilize в основном потоке, метод вернет Ложь или бросит исключение. И на самом деле не имеет значения, в какой момент вы перестали заполнять буфер, даже если вы записали некоторые данные после сбоя - скорее всего, файл будет поврежден и бесполезен.


3
Выполнение ввода-вывода параллельно с вычислениями - очень хорошая идея, но в Windows вам не следует использовать потоки для этого. Вместо этого используйте «Overlapped I / O», который не блокирует один из ваших потоков во время вызова I / O. Это означает, что вам не нужно беспокоиться о синхронизации потоков (просто не обращайтесь к буферу, в котором используется активная операция ввода-вывода).
Бен Фойгт

11

Я бы предложил попробовать сопоставление файлов . Я использовал mmapв прошлом в среде UNIX, и я был впечатлен высокой производительностью, которую я смог достичь


1
@nalply Это все еще работающее, эффективное и интересное решение для запоминания.
Ям Маркович

stackoverflow.com/a/2895799/220060 о плюсах и минусах mmap. Особенно примечание «Для чисто последовательного доступа к файлу, это также не всегда лучшее решение [...]». Также stackoverflow.com/questions/726471 , он фактически говорит, что в 32-битной системе вы ограничены 2 или 3 Гб. - кстати, это не я, кто отверг этот ответ.
Вскоре

8

Можете ли вы использовать FILE*вместо этого, и меру производительности, которую вы получили? Несколько вариантов использовать fwrite/writeвместо fstream:

#include <stdio.h>

int main ()
{
  FILE * pFile;
  char buffer[] = { 'x' , 'y' , 'z' };
  pFile = fopen ( "myfile.bin" , "w+b" );
  fwrite (buffer , 1 , sizeof(buffer) , pFile );
  fclose (pFile);
  return 0;
}

Если вы решили использовать write, попробуйте нечто подобное:

#include <unistd.h>
#include <fcntl.h>

int main(void)
{
    int filedesc = open("testfile.txt", O_WRONLY | O_APPEND);

    if (filedesc < 0) {
        return -1;
    }

    if (write(filedesc, "This will be output to testfile.txt\n", 36) != 36) {
        write(2, "There was an error writing to testfile.txt\n", 43);
        return -1;
    }

    return 0;
}

Я бы также посоветовал вам разобраться memory map. Это может быть ваш ответ. Однажды мне пришлось обработать файл размером 20 ГБ в другом, чтобы сохранить его в базе данных, и файл даже не открывался. Так что решение как использовать карту памяти. Я сделал это в Pythonто же время.


Фактически, прямой FILE*эквивалент исходного кода, использующего тот же самый буфер 512 МБ, получает полную скорость. Ваш текущий буфер слишком мал.
Мистик

1
@Mysticial Но это всего лишь пример.
Кибертекстрон

В большинстве систем 2соответствует стандартной ошибке, но все равно рекомендуется использовать STDERR_FILENOвместо 2. Другая важная проблема заключается в том, что одним из возможных ошибок, который вы можете получить, является EINTR, когда вы получаете сигнал прерывания, это не настоящая ошибка, и вам следует просто повторить попытку.
Пейман

6

Попробуйте использовать вызовы API open () / write () / close () и поэкспериментируйте с размером выходного буфера. Я имею в виду, не передавайте весь буфер "много-много байтов" сразу, сделайте пару записей (т.е. TotalNumBytes / OutBufferSize). OutBufferSize может быть от 4096 байтов до мегабайта.

Еще одна попытка - используйте WinAPI OpenFile / CreateFile и используйте эту статью MSDN для отключения буферизации (FILE_FLAG_NO_BUFFERING). И эта статья MSDN о WriteFile () показано, как получить размер блока, чтобы накопитель знал оптимальный размер буфера.

В любом случае, std :: ofstream является оболочкой и может быть блокировка операций ввода-вывода. Имейте в виду, что обход всего массива N-гигабайт также занимает некоторое время. Пока вы пишете небольшой буфер, он попадает в кеш и работает быстрее.


6

fstreamПо сути, они не медленнее, чем C-потоки, но они используют больше ЦП. (особенно если буферизация настроена неправильно). Когда процессор насыщается, он ограничивает скорость ввода-вывода.

По крайней мере, реализация MSVC 2015 копирует 1 символ за раз в буфер вывода, когда буфер потока не установлен (см. streambuf::xsputn). Поэтому не забудьте установить буфер потока (> 0) .

Я могу получить скорость записи 1500 МБ / с (полная скорость моего M.2 SSD) с fstreamпомощью этого кода:

#include <iostream>
#include <fstream>
#include <chrono>
#include <memory>
#include <stdio.h>
#ifdef __linux__
#include <unistd.h>
#endif
using namespace std;
using namespace std::chrono;
const size_t sz = 512 * 1024 * 1024;
const int numiter = 20;
const size_t bufsize = 1024 * 1024;
int main(int argc, char**argv)
{
  unique_ptr<char[]> data(new char[sz]);
  unique_ptr<char[]> buf(new char[bufsize]);
  for (size_t p = 0; p < sz; p += 16) {
    memcpy(&data[p], "BINARY.DATA.....", 16);
  }
  unlink("file.binary");
  int64_t total = 0;
  if (argc < 2 || strcmp(argv[1], "fopen") != 0) {
    cout << "fstream mode\n";
    ofstream myfile("file.binary", ios::out | ios::binary);
    if (!myfile) {
      cerr << "open failed\n"; return 1;
    }
    myfile.rdbuf()->pubsetbuf(buf.get(), bufsize); // IMPORTANT
    for (int i = 0; i < numiter; ++i) {
      auto tm1 = high_resolution_clock::now();
      myfile.write(data.get(), sz);
      if (!myfile)
        cerr << "write failed\n";
      auto tm = (duration_cast<milliseconds>(high_resolution_clock::now() - tm1).count());
      cout << tm << " ms\n";
      total += tm;
    }
    myfile.close();
  }
  else {
    cout << "fopen mode\n";
    FILE* pFile = fopen("file.binary", "wb");
    if (!pFile) {
      cerr << "open failed\n"; return 1;
    }
    setvbuf(pFile, buf.get(), _IOFBF, bufsize); // NOT important
    auto tm1 = high_resolution_clock::now();
    for (int i = 0; i < numiter; ++i) {
      auto tm1 = high_resolution_clock::now();
      if (fwrite(data.get(), sz, 1, pFile) != 1)
        cerr << "write failed\n";
      auto tm = (duration_cast<milliseconds>(high_resolution_clock::now() - tm1).count());
      cout << tm << " ms\n";
      total += tm;
    }
    fclose(pFile);
    auto tm2 = high_resolution_clock::now();
  }
  cout << "Total: " << total << " ms, " << (sz*numiter * 1000 / (1024.0 * 1024 * total)) << " MB/s\n";
}

Я попробовал этот код на других платформах (Ubuntu, FreeBSD) и не заметил различий в скорости ввода-вывода, но разница в использовании процессора составляет около 8: 1 ( fstreamиспользуется в 8 раз больше процессора ). Так что можно себе представить, если бы у меня был более быстрый диск, fstreamзапись замедлялась бы быстрее, чем stdioверсия.


3

Если вы копируете что-то с диска A на диск B в проводнике, Windows использует DMA. Это означает, что для большей части процесса копирования ЦП в основном не будет делать ничего, кроме указания дисковому контроллеру, куда помещать и получать данные, исключая целый шаг в цепочке и тот, который вообще не оптимизирован для перемещения больших объемов данных - и я имею в виду оборудование.

То, что вы делаете, требует много ресурсов процессора. Я хочу указать вам на «Некоторые вычисления, чтобы заполнить []» часть. Что я считаю необходимым. Вы генерируете [], затем копируете из [] в выходной буфер (это делает fstream :: write), затем генерируете снова и т. Д.

Что делать? Многопоточность! (Надеюсь у вас многоядерный процессор)

  • раскошелиться.
  • Используйте один поток для создания [] данных
  • Используйте другой для записи данных с [] на диск
  • Вам понадобятся два массива a1 [] и a2 [] и переключаться между ними
  • Вам понадобится какая-то синхронизация между вашими потоками (семафоры, очередь сообщений и т. Д.)
  • Используйте низкоуровневые небуферизованные функции, такие как функция WriteFile, упомянутая Mehrdad

2

Попробуйте использовать отображенные в памяти файлы.


@ Mehrdad но почему? Потому что это решение зависит от платформы?
14

3
Нет ... это потому, что для быстрой последовательной записи файлов вам нужно записывать большие объемы данных одновременно. (Скажем, 2-мегабайтные чанки, вероятно, являются хорошей отправной точкой.) Файлы с отображением в памяти не позволяют вам контролировать гранулярность, так что вы находитесь в зависимости от того, что менеджер памяти решит предварительно выбрать для буфера / буфера. В общем, я никогда не видел, чтобы они были такими же эффективными, как обычные устройства для чтения / записи ReadFileи для последовательного доступа, хотя для произвольного доступа они вполне могут быть лучше.
user541686

Но отображенные в памяти файлы используются ОС, например, для подкачки. Я думаю, что это высоко оптимизированный (с точки зрения скорости) способ чтения / записи данных.
14

7
@Mysticial: люди «знают» много вещей, которые просто неправильно.
Бен Фойгт

1
@qehgt: во всяком случае, пейджинг гораздо более оптимизирован для произвольного доступа, чем для последовательного доступа. Чтение 1 страницы данных намного медленнее, чем чтение 1 мегабайта данных за одну операцию.
user541686

1

Если вы хотите быстро записывать в файловые потоки, вы можете увеличить поток для буфера чтения:

wfstream f;
const size_t nBufferSize = 16184;
wchar_t buffer[nBufferSize];
f.rdbuf()->pubsetbuf(buffer, nBufferSize);

Кроме того, при записи большого количества данных в файлы иногда быстрее логически расширить размер файла, чем физически, это происходит потому, что при логическом расширении файла файловая система не обнуляет новое пространство перед записью в него. Также разумно расширять файл больше, чем нужно, чтобы предотвратить множество расширений файлов. Расширение логического файла поддерживается в Windows путем вызова SetFileValidDataили xfsctlс помощью XFS_IOC_RESVSP64систем XFS.


0

я компилирую мою программу в gcc в GNU / Linux и mingw в win 7 и win xp и работала хорошо

Вы можете использовать мою программу и создать файл размером 80 ГБ, просто измените строку 33 на

makeFile("Text.txt",1024,8192000);

при выходе из программы файл будет уничтожен, затем проверьте файл, когда он работает

иметь программу, которую вы хотите просто изменить программу

Первая - программа для Windows, вторая - для GNU / Linux.

http://mustafajf.persiangig.com/Projects/File/WinFile.cpp

http://mustafajf.persiangig.com/Projects/File/File.cpp

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.