Версия для печати
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум на Исходниках.RU > Visual C++ / MFC / WTL > Самый быстрый способ работы с файлами


Автор: Brunnen-g 17.04.06, 19:31
Долгое время я работал с файлами используя потоки наприме: ifstream inf ("data.txt",ios::binary);
Но недавно мне посоветовали что если работать с файлами посредством функции _open (например: inf = _open ("data.txt",_O_WRONLY | _O_BINARY | _O_CREAT);) то скорость работы программы увеличится в несколько раз. Так ли это? И есть ли еще более быстрый способ?
И последний вопрос: если не использовать потоки, то какой тогда будет аналог функции seekg()/seekp()?

Автор: bullet 17.04.06, 20:47
Можно еще использорвать CFile класс для работы с файлами или fopen ... Что насчет скорости - слоный вопрос, вернее я на него ответа не знаю! ;)

Автор: Aver 17.04.06, 21:01
Исполmзуй File Mapping. Скорость обращению к файлу и обработка - моментальная(файл не загружается в оперативку).
Пример создания файла 4 Га.

<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
        DWORD size = 1024;
        DWORD tm1 = ::GetTickCount();
     
     
        HANDLE hFile = ::CreateFile("D:\\444.txt", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
     
        HANDLE hMap = ::CreateFileMapping(hFile, NULL, PAGE_READWRITE, 1, size, NULL);
     
        BYTE* buf = (BYTE*)::MapViewOfFile(hMap, FILE_MAP_WRITE|FILE_MAP_READ, 0, 1, size);
     
        DWORD tm2 = ::GetTickCount();
     
        DWORD res = tm2 - tm1;
     
        ::UnmapViewOfFile(buf);
        ::CloseHandle(hMap);
        ::CloseHandle(hFile);


Но лучше всего(если файлы >> 4 Га) обрабатывать блоками и блоки брать длиной кластера.
З.Ы. Кстати кто знает как определить длину кластера API функцией?

Автор: Hsilgos 17.04.06, 21:58
Цитата
З.Ы. Кстати кто знает как определить длину кластера API функцией?

Хм... Может, вычислить? Ну там, размер диска разделить на 2^32... ( Для FAT32 по-моему =) ) Или типа того =) :whistle:

Автор: HOMO_PROGRAMMATIS 17.04.06, 23:23
Длину кластера можно получить, вызвав ::GetDiskFreeSpace() и умножив lpSectorsPerCluster на lpBytesPerSector

Добавлено
Кстати, насчет File Mapping - ничего моментального там не будет, волшебства не бывает. И ясное дело файл загружается в оперативку, просто не весь а те участки что используются в анный момент. Что до скорости, то почти у всех способов она будет примерно одинаковой, если писать код правильно

Автор: Red Devil 18.04.06, 04:59
Цитата

Исполmзуй File Mapping. Скорость обращению к файлу и обработка - моментальная(файл не загружается в оперативку).

Хм... а я всегда думал, что доступ к оперативной памяти быстрее, чем к ЖД.

Я предпочитаю использовать fstream, т.к. это класс и с ним удобнее работать, чем через fopen, и потому что системно независимый. Хоть под unix, хоть под win.
Хотя мне кажется, подчеркиваю слово кажется, если применять WINAPI то работа с файлом будет немного быстрее.

Автор: SVK 18.04.06, 06:37
Цитата Red Devil @
fopen
Он тоже, 'системо независимый'.

Автор: TarasCo 18.04.06, 09:58
Цитата Aver @
Исполmзуй File Mapping. Скорость обращению к файлу и обработка - моментальная(файл не загружается в оперативку).
Пример создания файла 4 Га.

Не согласен, спрорить лень, обсуждалось не раз. Например:
Скорость FlushViewOfFile

Автор: Алиса 18.04.06, 10:53
Цитата Aver @
файл не загружается в оперативку

загружается, но при обращении к опред. байту.

TarasCo, а Рихтер писал, что ф-ции WriteFile/ReadFile реализованы именно через File Mapping! :huh:
и он же писал о ф-ции FlushViewOfFile, как о "тормозной" и жрущей много ресурсов.

Автор: TarasCo 18.04.06, 14:11
Цитата Алиса @
TarasCo, а Рихтер писал, что ф-ции WriteFile/ReadFile реализованы именно через File Mapping!

а где противоречее?

Цитата Алиса @
и он же писал о ф-ции FlushViewOfFile, как о "тормозной" и жрущей много ресурсов.

просто обычно содержимое файла кешируется и не скидывается на диск сразу же, по закрытию файла. Файловые буфера будут дозаписаны в режиме т.н lazy writer а. С другой стороны FlushViewOfFile будет дожидаться синхронно окончания асинхронной операции записи на диск, что приведет к перепланировке задач.

Автор: Denny 19.04.06, 07:37
Цитата Алиса @
Рихтер писал, что ф-ции WriteFile/ReadFile реализованы именно через File Mapping!

покажи, где он это писал?

Автор: Brunnen-g 21.04.06, 21:57
А может лучше не будем отходить от темы? :)

Какой все таки метод работы с файлами наиболее прост и наиболее быстр?
Стоит ли мне свои потоки переписывать на что либо другое?

Автор: Hryak 22.04.06, 07:07
Цитата Brunnen-g @
А может лучше не будем отходить от темы? :)

Поиски серебрянной пули - это не тема, а флейм.
"Просто и быстро" - обычно противоречат друг другу. Например, чтобы прочитать в массив числа из текстового файла, разделенные пробелами, сложно придумать что-то проще, чем:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    vector<double> v(istream_iterator<double>(fstream("data.txt")), istream_iterator<double>());
Но это будет далеко не самый быстрый способ.
Есть редкие исключения, конечно. Для специфичных задач. Например, некий массив сохранен бинарно в файле (размером несколько сотен мегабайт) и нужно в нем некоторые значения прочитать, некоторые записать, но не все. Вразнобой, к каждому элементу могут как не обращаться, так и десятки раз использовать... В таком случае при использовании MMF противоречия между скоростью и удобством нет.

Даже если рассматривать только скорость - тоже многое зависит от задачи. Например, если читать сотни мегабайт бинарных данные большими блоками последовательно, то ReadFile будет наиболее быстрой, особенно, если поиграться флагами в CreateFile.
Однако, при чтении небольшими кусками она сольёт абсолютно всем прочим способам, даже форматированному вводу потоков C++. И величина слива будет исчисляться порядками (в случае однобайтных блоков порядков будет много).

Автор: Dimach 22.04.06, 07:44
1) Обычно лучше пользоваться fopen/fread/frite для C или fstream-ми для С++, т.к. они буферизируют данные (очень полезно если читаешь/пишешь небольшими порциями).
2) Если читаешь/пишешь большими кусками, кратными размеру блока на файл-системе (16/32/64/... КБ) то можно использовать WinAPI ReadFile/WriteFile. Пожалуй будет чуть побыстрее, т.к. эти ф-ции находятся ближе к моменту системного вызова и меньше кода выполниться на уровне апликации.
3) Мапируюшие ф-ции (MapViewOfFile...) обычно работают медленей обычного чтения, пользоваться ими стоит только если действительно необходимо замапировать файл в память (для простоты доступа например).

ЗЫ: Обший принцип вообще-то прост и не зависит от выбранного API: читать/писать последовательно и большими кусками.

Powered by Invision Power Board (https://www.invisionboard.com)
© Invision Power Services (https://www.invisionpower.com)