Запис бінарного файлу на C ++ дуже швидко


241

Я намагаюся записати величезну кількість даних на свій 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 десь між 150MB / s та 200MB / s. Так хоча б у 7 разів швидше. Ось чому я думаю, що я мав би змогу йти швидше.

Будь-які ідеї, як я можу пришвидшити написання?


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

7
Я справді раніше робив це завдання. Використовуючи прості, fwrite()я міг отримати близько 80% пікової швидкості запису. Тільки за допомогою FILE_FLAG_NO_BUFFERINGя колись міг досягти максимальної швидкості.
Містичний

10
Я не впевнений, що справедливо порівнювати запис файлів із копіюванням на SSD-SSD. Можливо, SSD-SSD працює на нижчому рівні, уникаючи бібліотек C ++ або використовуючи прямий доступ до пам'яті (DMA). Копіювання чогось не те саме, що запис довільних значень у файл випадкового доступу.
Ігор Ф.

4
@IgorF. Це просто неправильні міркування; це абсолютно чесне порівняння (якщо нічого іншого, на користь написання файлів). Копіювання через диск у Windows - це просто читання та запис; нічого фантазійного / складного / різного не відбувається під ним.
користувач541686

5
@MaximYegorushkin: Посилання або цього не сталося. : P
користувач541686

Відповіді:


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 ++?
Шчепурін

21
@SChepurin: Якщо ти ведеш педантичність, напевно, ні. Якщо ти практичний, напевно, так. :)
користувач541686

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

11
Чи ios::sync_with_stdio(false);має попереднє передбачення якесь значення для коду з потоком? Мені просто цікаво, наскільки велика різниця між використанням цієї лінії та ні, але у мене немає достатньо швидкого диска, щоб перевірити кутовий випадок. І якщо є якась реальна різниця.
Артур Чайка

24

Спробуйте наступне для того, щоб:

  • Менший розмір буфера. Написання ~ 2 МіБ одночасно може стати гарним початком. На моєму останньому ноутбуці ~ 512 KiB було найприємнішим місцем, але я ще не перевірив свій SSD.

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

  • Використовуйте _open(або, _topenякщо ви хочете, щоб це було правильно), щоб відкрити файл, а потім скористайтеся _write. Це, ймовірно, дозволить уникнути багато буферизації, але це не певно.

  • Використання специфічних для Windows функцій, таких як CreateFileі WriteFile. Це дозволить уникнути буферизації у стандартній бібліотеці.


Перевірте будь-які результати еталону, розміщені в Інтернеті. Для отримання будь-якої гідної пропускної спроможності вам потрібно записувати 4 КБ з глибиною черги 32 або більше, або 512 К або вище.
Бен Войгт

@BenVoigt: Так, це співвідноситься зі мною, кажучи, що 512 KiB було для мене найприємнішим місцем. :)
користувач541686

Так. З мого досвіду, менші розміри буфера зазвичай є оптимальними. Виняток - коли ви використовуєте FILE_FLAG_NO_BUFFERING- у яких більші буфери, як правило, краще. Оскільки я думаю, що FILE_FLAG_NO_BUFFERINGце дуже багато DMA.
Містичний

22

Я не бачу різниці між std :: stream / FILE / пристроєм. Між буферизацією та не буферизацією.

Також зверніть увагу:

  • SSD-накопичувачі "мають тенденцію" сповільнюватись (знижуючи швидкість передачі) по мірі їх заповнення.
  • SSD-накопичувачі «прагнуть» сповільнюватись (знижуючи швидкість передачі) у міру дорослішання (через неробочі біти).

Я бачу, як код працює в 63 секунди.
Таким чином, швидкість передачі даних: 260 М / с (мій 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 з 1 місця в пам'яті в інше і подивіться, наскільки це швидко.

Редагувати

Я змінив свій код, щоб використовувати дзвінки нижнього рівня:
тобто відсутність буферизації.

#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 Мб, який використовує ОП, і я отримую 20 МБ / с потоками проти 90 Мб / с FILE*.
Містичний

Також ваш шлях з fwrite (a, sizeof (неподписаний довгий довгий), розмір, потік); замість fwrite (a, 1, size * sizeof (неподписаний довгий довгий), 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-го буфера до файлу
_ - зачекайте, поки операція завершена

Такий підхід із заміною буфера дуже корисний, коли заповнення буфера вимагає більш складних обчислень (отже, більше часу). Я завжди реалізую клас CSequencesStreamWriter, який приховує всередині асинхронну запис, тому для кінцевого користувача інтерфейс має просто функції запису.

А розмір буфера повинен бути кратним розміру кластера диска. В іншому випадку ви отримаєте низьку продуктивність, записавши один буфер на 2 сусідні кластери диска.

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

Помилка обробки.
Хоча код починає заповнювати другий буфер, а 1-й записується в окремий потік, але запис чомусь не вдається, головний потік повинен знати про цей збій.

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

Припустимо, що в інтерфейсі CSequentialStreamWriter функція Write має функцію Write, яка повертає bool або викидає виняток, таким чином, маючи помилку в окремому потоці, ви повинні пам'ятати про цей стан, тому наступного разу, коли ви зателефонуєте Write або Finilize на основний потік, метод повернеться Неправдивий або викине виняток. І зовсім неважливо, в який момент ви перестали заповнювати буфер, навіть якщо ви записали деякі дані попереду після відмови - швидше за все, файл буде пошкоджений і марний.


3
Виконання вводу-виводу паралельно з обчисленнями є дуже хорошою ідеєю, але в Windows не слід використовувати теми для його виконання. Натомість використовуйте "Перекритий ввід / вивід", який не блокує жодного з ваших потоків під час дзвінка вводу / виводу. Це означає, що вам ледь не потрібно хвилюватися про синхронізацію потоків (просто не звертайтеся до буфера, який використовує активну операцію вводу / виводу, використовуючи її).
Бен Войгт

11

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


1
@nalply Це все-таки робоче, ефективне та цікаве рішення, яке потрібно пам’ятати.
Ям Маркович

stackoverflow.com/a/2895799/220060 про плюси та мінуси mmap. Особливо зауважте "Що стосується чистого послідовного доступу до файлу, це також не завжди краще рішення [...]" Також stackoverflow.com/questions/726471 , це ефективно говорить про те, що для 32-бітної системи ви обмежені 2 або 3 Гб. - до речі, не я спротив цю відповідь.
nalply

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

fstreams самі по собі не повільніші за потоки C, але вони використовують більше процесора (особливо якщо буферизація не налаштована належним чином). Коли процесор насичується, він обмежує швидкість вводу / виводу.

Щонайменше, реалізація MSVC 2015 копіює одночасно 1 char у вихідний буфер, коли буфер потоку не встановлений (див. 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

Спробуйте використовувати файли, зіставлені з пам'яттю.


@Mehrdad але чому? Тому що це рішення, яке залежить від платформи?
qehgt

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

Але файли, зіставлені з пам'яттю, використовуються ОС, наприклад, для пейджингу. Я думаю, що це дуже оптимізований (з точки зору швидкості) спосіб читання / запису даних.
qehgt

7
@Mysticial: Люди "знають" багато речей, які просто невірно.
Ben Voigt

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

3

Якщо ви скопіюєте щось з диска А на диск B в провідник, Windows використовує DMA. Це означає, що для більшості процесів копіювання процесор в основному не зробить нічого, крім того, щоб сказати дисковому контролеру, куди його поставити, і отримати дані, виключаючи цілий крок в ланцюжку, і той, який зовсім не оптимізований для переміщення великих обсягів даних - і я маю на увазі апаратне забезпечення.

Те, що ви робите, багато в чому включає процесор. Хочу вказати на "Деякі обчислення для заповнення []" частини. Що я вважаю важливим. Ви генеруєте [], потім копіюєте з [] у вихідний буфер (ось що робить fstream :: write), потім знову генеруєте і т.д.

Що робити? Багатопотоковість! (Сподіваюся, у вас багатоядерний процесор)

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

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.