Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 17, средняя оценка - 5.00
Gepar
1177 / 533 / 20
Регистрация: 01.07.2009
Сообщений: 3,517
#1

Максимально эфективное бинарное чтение из файла под Windows - C++

14.12.2012, 02:50. Просмотров 2520. Ответов 40
Метки нет (Все метки)

Задача: максимально эфективно (быстро) читать данные из файла. Каким это будет происходить образом - в виде си функции, с++ или винапи функции не имеет значения, имеет значение лишь результат.
Как мне известно размер странички в Windows = 4Кб так что быстрее всего по идее чтение должно происходить если читать по 4 кб, но как лучше всего это сделать?

Вообще в итоге я буду использоать 64битные значения после того как считаю кусок файла. Вот мой маленький набросок, который првда закончился фиаско потому что стандартная fread, как оказалось, имеет буфер под чтение меньше 4 кб так что нужно что-то другое быстрое
C++
1
2
3
4
5
6
7
    FILE* readFrom = fopen("input.bin","rb"); _ASSERT(readFrom);
    uint64_t bufferRead[64];//мой буффер на 4 кб
    size_t countBlocks;//считано блоков
 
        // вернёт 0 потому что fread не может считать 4096 байтиков
    countBlocks = fread(bufferRead,1,4096,readFrom);
    fclose(readFrom);
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
14.12.2012, 02:50
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Максимально эфективное бинарное чтение из файла под Windows (C++):

Бинарное чтение файла - C++
FILE *ftm; ftm = _wfopen(fff, L"r+"); //fff - это переменная wchar_t содержащая имя файла! unsigned short buf = { 0 }; ...

Бинарное чтение файла - C++
Что за каракули в конце файла,? Спасибо.

Бинарное чтение из файла с пoмощью функции fread() - C++
Подскажите, пожалуйста, почему feof() может возвращать конец файла далеко до его реального конца? Конец проверяется из обозревателя файлов...

Чтение файла под WATCOM - C++
Всем добрый день! Стоит задача чтения информации из файла. Есть простой код: #include <iostream> #include <fstream> #include...

Бинарное чтение файла - C++ Qt
Всем доброго времени суток. Стоит задача реализовать зашифровать файл RSA ключом в 1024 бит. Но споткнулся с проблемой чтения файла в виде...

Бинарное чтение из файла - C++ Builder БД
Всем доброго времени суток. Столкнулся с проблемой чтения из файла в бинарном режиме. У меня есть исполнительный файл программы для...

40
-=ЮрА=-
14.12.2012, 03:11     Максимально эфективное бинарное чтение из файла под Windows
  #16

Не по теме:

PS:Gepar, лично мне кажется целесообразней не ограничиваться производительностью головок HDD а производить обработку файла в оператвке в буффере аккурат под размер файла (благо современные планки памяти позволят чуть ли не поверхность HDD в памяти держать) и производить все операции над файлом именно в ОЗУ - будет в тысячи раз быстрей. Конечно сам я максимум держал в оперативе 300 Мб данных не более, не было необходимости держать больше

0
Gepar
1177 / 533 / 20
Регистрация: 01.07.2009
Сообщений: 3,517
14.12.2012, 03:12  [ТС] #17
MrGluck, ну блин, предлагаешь сразу хапонуть 2 гб в оперативе, пошифровать их там (использовав ещё + 100 мб) и потом записать?
0
MrGluck
Модератор
Эксперт CЭксперт С++
7491 / 4606 / 692
Регистрация: 29.11.2010
Сообщений: 12,592
14.12.2012, 03:13 #18
Gepar, 4 Гб оперативки нынче стоит 700р.
0
-=ЮрА=-
Заблокирован
Автор FAQ
14.12.2012, 03:16 #19
Цитата Сообщение от Vourhey Посмотреть сообщение
Это неправда.
Vourhey я продаю за что купил(тобишь данные интернет ресурса, не провернные)Кстати где то лежит статья что большие файлы около 2 или 4 Кб лучше буффер. А по хорошему проверяь надо но мне лично жаль времени на такое дело.

редлагаешь сразу хапонуть 2 гб в оперативе, пошифровать их там (использовав ещё + 100 мб) и потом записать?
- тоже самое постом выше предлагал. Именно так
0
Миниатюры
Максимально эфективное бинарное чтение из файла под Windows  
Вложения
Тип файла: pdf zdrt76.htm.pdf (106.2 Кб, 5 просмотров)
Gepar
1177 / 533 / 20
Регистрация: 01.07.2009
Сообщений: 3,517
14.12.2012, 03:18  [ТС] #20
Цитата Сообщение от MrGluck Посмотреть сообщение
Gepar, 4 Гб оперативки нынче стоит 700р.
так не себе же пишу.
0
Vourhey
Почетный модератор
6486 / 2260 / 123
Регистрация: 29.07.2006
Сообщений: 12,635
14.12.2012, 03:24 #21
Gepar, потому что вызывать много раз операцию чтения с диска не даст никакого прироста к производительности.
Еще хорошо бы установить флаг FILE_FLAG_SEQUENTIAL_SCAN, чтобы упреждающее чтение работало лучше. Это тоже даст прирост.

Добавлено через 3 минуты
Gepar, и, конечно, это зависит от самого диска и и оси. Поэтому говорить, что 4к - это самый быстрый вариант - ошибка. Бери больше, и проверяй, а не верь плохим программистам.
1
Gepar
1177 / 533 / 20
Регистрация: 01.07.2009
Сообщений: 3,517
14.12.2012, 03:24  [ТС] #22
Ну ... если хапать по n мб то как тогда узнать сколько там оп свободно (чтобы при чтении не перестараться и не привести к перекачке данных в своп) ?
0
Vourhey
Почетный модератор
6486 / 2260 / 123
Регистрация: 29.07.2006
Сообщений: 12,635
14.12.2012, 03:29 #23
Цитата Сообщение от Gepar Посмотреть сообщение
то как тогда узнать сколько там оп свободно
Зачем узнавать? Компы с объемом меньше 1 гига уже редкость. А буфер в метр еще в своп никого не загонял.
1
MrGluck
Модератор
Эксперт CЭксперт С++
7491 / 4606 / 692
Регистрация: 29.11.2010
Сообщений: 12,592
14.12.2012, 03:38 #24
Gepar, я к тому сказал, что память сейчас оперативная взлетает в объемах по експоненте и беспокоится о её нехватке бесмысленно.
Вот, что я предлагаю:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
#include <stdlib.h>
 
int main(void)
{
    FILE* pFile;
    pFile = fopen ("test.txt" , "rb");
    if (pFile == NULL) exit(1);
    fseek (pFile , 0 , SEEK_END);
    unsigned long long size = ftell (pFile); // не знаю, существует ли он в С
    rewind (pFile);
    char *buf = (char *) malloc(sizeof(char) * size);
    if (buf == NULL) exit(2);
    size_t result = fread (buf, 1, size, pFile);
    if (result != size) exit (3);
    //printf("%s", buf);
    free(buf);
    fclose(pFile);
    return 0;
}
Добавлено через 3 минуты
Мегабайтный файл считывает за 0.004 секунды (на моем компе естественно)
0
activnaya
255 / 45 / 2
Регистрация: 24.11.2012
Сообщений: 466
14.12.2012, 03:48 #25
Цитата Сообщение от Gepar Посмотреть сообщение
Vourhey, ну проаргументируй, тема то интересная.
можно я? какая скорость чтения с HDD и какая из RAM? Что мешает загружать в RAM по гигу или 2 и обрабатывать данные из оперативной памяти? Странный конечно подход... по 4Кб.
Цитата Сообщение от Gepar Посмотреть сообщение
MrGluck, ну блин, предлагаешь сразу хапонуть 2 гб в оперативе, пошифровать их там (использовав ещё + 100 мб) и потом записать?
очевидно же.
0
MrGluck
Модератор
Эксперт CЭксперт С++
7491 / 4606 / 692
Регистрация: 29.11.2010
Сообщений: 12,592
14.12.2012, 04:04 #26
И я уж молчу про http://help.3l.com/3L/index.html?threads_thread_h.htm из С11
0
WhiteP
606 / 204 / 23
Регистрация: 20.11.2012
Сообщений: 426
14.12.2012, 09:50 #27
Самое эффективное - читать функцией ReadFile (winapi) большими блоками (>= 64 кб) с флагом FILE_FLAG_NO_BUFFERING. Это чтобы не было 100500 промежуточных буферов, как в случае с функами с и с++. Если время обработки довольно большое, то имеет смысл читать асинхронно и обрабатывать покусочно по мере поступения.
1
Gepar
1177 / 533 / 20
Регистрация: 01.07.2009
Сообщений: 3,517
14.12.2012, 15:50  [ТС] #28
WhiteP, а можно небольшой пример чтения ею бинарных данных (с правильным получением хендлера файла для этой функции), допустим для файла input.bin и буффера на 64 кб uint64_t[8192] ну и соответственно с получением информации сколько реально байт было считано (ато она я смотрю просто BOOL возвращает).
0
WhiteP
606 / 204 / 23
Регистрация: 20.11.2012
Сообщений: 426
14.12.2012, 17:32 #29
Вот как-то так. Естественно, чтобы был прирост скорости - нужно избавиться от частых вызовов тормозных потоков C++ (std::cout). Тут они только для наглядности.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <iostream>
#include <windows.h>
 
#define BUFSIZE 65536 //должен быть кратен размеру сектора (обычно 512, точнее - GetDiskFreeSpace)
 
int main()
{
    //буфер должен быть выровнен по границе сектора. VirtualAlloc выравнивает начало буфера
    //автоматически по адресу кратному 64.
    BYTE * pBuf = (PBYTE)VirtualAlloc(NULL, BUFSIZE, MEM_COMMIT, PAGE_READWRITE);
 
    if(!pBuf)
    {
        std::cout<<"VirtualAlloc error. Code: "<<GetLastError()<<std::endl;
        return -1;
    }
 
    std::cout<<"Memory successfully allocated. Address: "<<(int)pBuf<<std::endl;
        
    HANDLE hFile = CreateFileW(L"c:\\input.bin", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_NO_BUFFERING, 0);
    
    if(hFile == INVALID_HANDLE_VALUE)
    {
        std::cout<<"CreateFile error. Code: "<<GetLastError()<<std::endl;
        VirtualFree(pBuf, BUFSIZE, MEM_RELEASE);
        return -1;
    }
 
    std::cout<<"File successfully opened. Start reading."<<std::endl;
 
    DWORD readed = 0, fSize = 0, step = 1;
    BOOL isOk = 0;
 
    //двигать файловый указатель можно только по границам секторов!
    while(isOk = ReadFile(hFile, pBuf, BUFSIZE, &readed, 0))
    {
        std::cout<<"Step "<<step++<<". Readed bytes: "<<readed<<std::endl;
        fSize+=readed;
        if(readed < BUFSIZE)
            break;
    }
    if(isOk == FALSE)
        std::cout<<GetLastError()<<std::endl;
 
    std::cout<<" Total readed bytes: "<<fSize<<". FileSize is "<<GetFileSize(hFile, 0)<<std::endl;  
 
    CloseHandle(hFile);
    VirtualFree(pBuf, BUFSIZE, MEM_RELEASE);
 
    return 0;
}
1
Gepar
1177 / 533 / 20
Регистрация: 01.07.2009
Сообщений: 3,517
17.12.2012, 01:13  [ТС] #30
WhiteP, не получается у меня использовать этот твой винапи вариант - почему-то WriteFile нифига не пишет и чесно признаётся что записывает каждый раз 0 байт. Какого хрена оно так ?
Вот код где я его использую, вот почему он каждый раз нифигашеньки не запсывает WriteFile этот
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#define BUFSIZE 65536 //должен быть кратен размеру сектора (обычно 512, точнее - GetDiskFreeSpace)
 
void CryptoSaveFastHelper(Cryptographer* crypto,CryptoMode mode, uint64_t* keys, char* from, char* to)
{
    //буфер должен быть выровнен по границе сектора. VirtualAlloc выравнивает начало буфера
    //автоматически по адресу кратному 64.
    uint64_t * pBuf = (uint64_t*)VirtualAlloc(NULL, BUFSIZE, MEM_COMMIT, PAGE_READWRITE);
 
    if(!pBuf)
    {
        std::cout<<"VirtualAlloc error. Code: "<<GetLastError()<<std::endl;
        throw -1;
    }
 
    int* key; //ключ (и)
 
    //uint64_t bufferRead[512];//мой буффер на 4 кб
    uint64_t lastBlock = 0ULL;//последний блок который нужно будет дописать в конец файла
 
    HANDLE inputData = CreateFile(from, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_NO_BUFFERING|FILE_FLAG_SEQUENTIAL_SCAN, 0);
    HANDLE outputData = CreateFile(to, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS , FILE_ATTRIBUTE_NORMAL|FILE_FLAG_NO_BUFFERING, 0);
 
    DWORD readed = 0;//сколько байт считано
    DWORD writed = 0;//сколько байт записано
    BOOL isOk = 0;
 
    switch(mode)
    {
    case _DESEBC:
        {
            while(isOk = ReadFile(inputData, pBuf, BUFSIZE, &readed, 0))
            {
                //шифруем считанные блоки
                crypto->EnCrypt(pBuf,readed/8);
 
                _ASSERT(WriteFile(outputData,pBuf,readed-(readed%8),&writed,0)==0);//отрабатывает без ошибок, но нифига не пишеет!
                if(readed < BUFSIZE)
                    break;
            }
 
            //если число байтиков в файле делилось на 4 без остатка
            if(!(readed % 8))
            {
                lastBlock = crypto->EnCrypt(lastBlock);
                WriteFile(outputData,&lastBlock,(DWORD)8,&writed,0);
            }
            else//иначе добиваем нолями предпоследний а в последний пишем размер
            {
                lastBlock = readed%8;
                lastBlock = crypto->EnCrypt(lastBlock);
                char* ptr = (char*)(pBuf+(readed/8));
                ptr += (readed%8);
                for(int i=0;i<8-(readed%8); i++)
                    *ptr++=0;
 
                pBuf[(readed/8)] = crypto->EnCrypt(pBuf[(readed/8)]);
 
                WriteFile(outputData,&pBuf[readed/8],(DWORD)8,&writed,0);
                WriteFile(outputData,&lastBlock,(DWORD)8,&writed,0);
            }
        }
        break;
    }
    CloseHandle(inputData);
    CloseHandle(outputData);
}
0
17.12.2012, 01:13
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
17.12.2012, 01:13
Привет! Вот еще темы с ответами:

Бинарное чтение файла - PHP
&lt;?php @error_reporting ( E_ALL ); @ini_set ( 'display_errors', true ); @ini_set ( 'html_errors', false ); @ini_set (...

Максимально быстрое чтение очень большого файла - C#
Добрый день, задача прочитать очень большой файл (1GB-10GB+). Нужно провести операцию с каждой строкой этого файла. Используя...

Бинарное дерево поиска. Как осуществить запись в файл и чтение из файла - C (СИ)
Добрый день! Если кому не жаль своего времени окажите помощь! Необходимо осуществить запись в файл,просмотр содержимого файла, и создание...

Чтение загрузочного сектора под Windows - Assembler
Требуется считать загрузочный сектор с диска (fdd,hdd,flash,cd) при чтении с флопа всё проходит нормально, но при попытке чтения с любого...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
30
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru