Форум программистов, компьютерный форум CyberForum.ru

Быстрое чтение файла - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 66, средняя оценка - 4.67
programina
 Аватар для programina
1912 / 597 / 37
Регистрация: 23.10.2011
Сообщений: 4,468
Записей в блоге: 2
11.11.2011, 10:59     Быстрое чтение файла #1
Здраствуйте. Я пишу программу, которая читает файлы порядка от нескольких килобайтов до максимум 3 Мб. Посоветуйте пожалуйста, какие функции и/или алгоритмы использовать для максимальнобыстрого чтения данных, представленных вещественными числами. Прошу прощения, если мой вопрос неправильно сформулирован.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Thinker
Эксперт C++
 Аватар для Thinker
4215 / 2189 / 150
Регистрация: 26.08.2011
Сообщений: 3,802
Записей в блоге: 5
11.11.2011, 14:32     Быстрое чтение файла #21
Строчная буферизация это когда строки до '\n' накапливаются, а потом целиком записываются, а блочная это когда не будет заполнен целиком буфер
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Байт
 Аватар для Байт
13947 / 8778 / 1221
Регистрация: 24.12.2010
Сообщений: 15,884
11.11.2011, 14:37     Быстрое чтение файла #22
Цитата Сообщение от programina Посмотреть сообщение
Thinker и Байт, спасибо вам большое. Я узнала про буферизацию потока.
Мой вам совет. Сделайте буфер побольше. И читайте столько, сколько нужно для нормальной логики программы. Хоть по одному числу.
C
1
2
3
4
5
6
7
8
FILE *f; double d; int size = sizeof(double);
f = fopen("nfvt", "rb");
setvbuf(f, NULL, _IOFBF, 10400);
while(1) {
  if (fread(&d, 1, size, f)<size) break;
  .......
}
fclose(f);
Если, конечно, в нашей дискуссии с Thinker прав окажусь я
Charles Kludge
Клюг
 Аватар для Charles Kludge
7621 / 3136 / 361
Регистрация: 03.05.2011
Сообщений: 8,383
11.11.2011, 14:37     Быстрое чтение файла #23
IMHO, для ДОСи можно использовать
C
1
2
#include <stdio.h>
void setbuf( FILE *fp, char *buffer );
The setbuf function can be used to associate a buffer with the file designated by fp. If this function is used, it must be called after the file has been opened and before it has been read or written. If the argument buffer is
NULL, then all input/output for the file fp will be completely unbuffered. If the argument buffer is not NULL, then it must point to an array that is at least BUFSIZ characters in length, and all input/output will be fully buffered.
и
C
1
2
3
4
5
#include <stdio.h>
int setvbuf( FILE *fp,
             char *buf,
             int mode,
             size_t size );
The setvbuf function can be used to associate a buffer with the file designated by fp. If this function is used, it must be called after the file has been opened and before it has been read or written. The argument mode determines how the file fp will be buffered, as follows:


Mode Meaning

_IOFBF

causes input/output to be fully buffered.


_IOLBF

causes output to be line buffered (the buffer will be flushed when a new-line character is written, when the buffer is full, or when input is requested on a line buffered or unbuffered stream).


_IONBF

causes input/output to be completely unbuffered.

If the argument buf is not NULL, the array to which it points will be used instead of an automatically allocated buffer. The argument size specifies the size of the array.
А под виндой
C
1
2
3
4
5
6
7
8
9
HANDLE CreateFileMapping(
 
    HANDLE hFile,   // handle to file to map 
    LPSECURITY_ATTRIBUTES lpFileMappingAttributes,  // optional security attributes 
    DWORD flProtect,    // protection for mapping object 
    DWORD dwMaximumSizeHigh,    // high-order 32 bits of object size  
    DWORD dwMaximumSizeLow, // low-order 32 bits of object size  
    LPCTSTR lpName  // name of file-mapping object 
   );
и иже с ним.
Thinker
Эксперт C++
 Аватар для Thinker
4215 / 2189 / 150
Регистрация: 26.08.2011
Сообщений: 3,802
Записей в блоге: 5
11.11.2011, 14:40     Быстрое чтение файла #24
Цитата Сообщение от Байт Посмотреть сообщение
Сделайте буфер побольше.
Только если он в стек поместится, а то можно динамический массив создать и работать с "rb" или "wb".
Байт
 Аватар для Байт
13947 / 8778 / 1221
Регистрация: 24.12.2010
Сообщений: 15,884
11.11.2011, 14:42     Быстрое чтение файла #25
Цитата Сообщение от Thinker Посмотреть сообщение
Это хорошо, но в двоичных потоках нет буферизации. Столкнулся с этим, когда серьезные и быстрые программы шифрования писал.
Отложим дискуссию. Вот придумаю грамотный эксперимент, посмотрим.
Thinker
Эксперт C++
 Аватар для Thinker
4215 / 2189 / 150
Регистрация: 26.08.2011
Сообщений: 3,802
Записей в блоге: 5
11.11.2011, 14:43     Быстрое чтение файла #26
Цитата Сообщение от Байт Посмотреть сообщение
Отложим дискуссию. Вот придумаю грамотный эксперимент, посмотрим.
Ок, советую с копированием файлов
talis
 Аватар для talis
789 / 541 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
11.11.2011, 14:44     Быстрое чтение файла #27
Цитата Сообщение от Charles Kludge Посмотреть сообщение
CreateFileMapping
Мне казалось, что она просто "выводит" файл в адресное пространство программы. Про буферизацию я ничего на msdn не увидел
Байт
 Аватар для Байт
13947 / 8778 / 1221
Регистрация: 24.12.2010
Сообщений: 15,884
11.11.2011, 14:45     Быстрое чтение файла #28
Цитата Сообщение от Thinker Посмотреть сообщение
Только если он в стек поместится, а то можно динамический массив создать и работать с "rb" или "wb".
setvbuf при втором параметре = NULL сам выделяет память посредством
malloc, т.е. в динамической памяти
Thinker
Эксперт C++
 Аватар для Thinker
4215 / 2189 / 150
Регистрация: 26.08.2011
Сообщений: 3,802
Записей в блоге: 5
11.11.2011, 14:47     Быстрое чтение файла #29
Цитата Сообщение от Байт Посмотреть сообщение
setvbuf при втором параметре = NULL сам выделяет память посредством
malloc, т.е. в динамической памяти
Я про собственный буфер, мы же дискутируем, что setbuf для двоичного формата не подходит, поэтому со своей стороны предлагаю свой динамический буфер создать
-=ЮрА=-
Заблокирован
Автор FAQ
11.11.2011, 15:01     Быстрое чтение файла #30
Цитата Сообщение от programina Посмотреть сообщение
Здраствуйте. Я пишу программу, которая читает файлы порядка от нескольких килобайтов до максимум 3 Мб. Посоветуйте пожалуйста, какие функции и/или алгоритмы использовать для максимальнобыстрого чтения данных, представленных вещественными числами. Прошу прощения, если мой вопрос неправильно сформулирован.
- файл совсем маханький предлагаю всё его содержимое сразу впихнуть в буффер, а затем уже работать с алгоритмами для строки или чего вы там хотите реализовать!Работа с буффером будет куда более быстрой чем парсинг файлового потока!Да и файл можно без опасения переписать, все данные то в буфере
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
long sLen;
char *s;
FILE * f = fopen("fPath","rb");//да rb - не будет граблей с \r\n
if(f)
{
    fseek(f,0,SEEK_END);//Курсор вконец
    sLen = ftell(f);//Узнаём длинну файла
    fseek(f,0,SEEK_SET);//Курсор вначала
    if(!(str = (char *)malloc(sizeof(char) * (sLen + 1))))
           printf("Allocation memory error\n");
    else
    {
          fread(s,sLen,1,f);
          s[sLen] = '\0';//Завершили строку
    }
    fclose(f);//Закрыли файловый поток
    if(s)
   {
           //работаем с инфойфайла
   }
}
Добавлено через 5 минут
Чтобы перебить строку в вещественные числа strtok-ом парсим токены идущие через пробел
char delim[] = " ";
C
1
2
3
4
5
6
char * tok = strtok(str,delim);
while(tok)
{
    arr[i++] = atof(tok);
    tok = strtok(str,delim);
}
Добавлено через 1 минуту
Ну а на плюсах можно всем что выше написал не заморачиваться и сделать вот так
программа с динамической памятью
тут уже готовый проект считывания ifstream-ом
Thinker
11.11.2011, 15:03
  #31

Не по теме:

-=ЮрА=-, но вопрос то такой: происходит ли автоматическая буферизация двоичных потоков

programina
 Аватар для programina
1912 / 597 / 37
Регистрация: 23.10.2011
Сообщений: 4,468
Записей в блоге: 2
11.11.2011, 15:15  [ТС]     Быстрое чтение файла #32
Не по теме:
Спасибо всем большое, но у меня уже переполнение буфера в голове от такого кол-ва информации.
-=ЮрА=-
Заблокирован
Автор FAQ
11.11.2011, 16:37     Быстрое чтение файла #33
Всё же я посьавил себе за цель проверить свои слова о быстроте,
для полноты анализа рассматривал сразу 3 алгоритма чтения вещественных в массив
1 - й вариант fscanf
2 - й буффер а затем подхват всего strtok-ом и atof-ом
3 - й любимый многими начинающими вариант ifstream>>
Пришлось написать заполнитель файла - мой файл содержит 656898 double и весит 3,75 Мб)
(вбивать вручную 3 Мб чисел я бы засел на дня 2)
так что цепляю и код рандомного наполнителя файла тоже
(наполняет файл долго - около 15 сек, ну дык и значений почти 660 тысяч)
fill.cpp
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
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <ctime>
using namespace std;
 
int main()
{
    double val;
    cout<<"Enter num of elements : ";
    long num;cin>>num;
    ofstream ofs("file.txt");
    ofs<<num<<endl;
    srand(time(0));
    for(long i = 0; i < num; i++)
    {
        cout<<(val = rand()%(2*num)/(1.0 + rand()%2));
        ofs<<val;
        if(i != num - 1)
        {
            cout<<" ";
            ofs<<" ";
        }
        else
            cout<<"\n";
    }
    ofs.close();
    system("pause");
    return 0;
}


Сам алгоритм чтения здесь
read.cpp
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <ctime>
using namespace std;
double * parse_fscanf(long &n, double * arr);
double * parse_strtok(long &n, double * arr);
double * parse_ifstrm(long &n, double * arr);
 
int main()
{
    long n,bgn,end;
    double * arr = NULL;
    cout<<"\tVariant C(fscanf)\n";
    time(&bgn);
    cout<<"Algorithm started at : "<<asctime(localtime(&bgn));
    arr = parse_fscanf(n, arr);
    time(&end);
    cout<<"Algorithm stoped at : "<<asctime(localtime(&end));
    cout<<"Time of work : "<<difftime(end,bgn)<<" sec"<<endl;
    cout<<"arr["<<0<<"] = "<<arr[0]<<endl;
    cout<<"arr["<<n - 1<<"] = "<<arr[n - 1]<<endl;
    delete [] arr;
 
    cout<<"\tVariant C(strtok)\n";
    time(&bgn);
    cout<<"Algorithm started at : "<<asctime(localtime(&bgn));
    arr = parse_strtok(n, arr);
    time(&end);
    cout<<"Algorithm stoped at : "<<asctime(localtime(&end));
    cout<<"Time of work : "<<difftime(end,bgn)<<" sec"<<endl;
    cout<<"arr["<<0<<"] = "<<arr[0]<<endl;
    cout<<"arr["<<n - 1<<"] = "<<arr[n - 1]<<endl;
    delete [] arr;
 
    cout<<"\tVariant C++(ifstream)\n";
    time(&bgn);
    cout<<"Algorithm started at : "<<asctime(localtime(&bgn));
    arr = parse_ifstrm(n, arr);
    time(&end);
    cout<<"Algorithm stoped at : "<<asctime(localtime(&end));
    cout<<"Time of work : "<<difftime(end,bgn)<<" sec"<<endl;
    cout<<"arr["<<0<<"] = "<<arr[0]<<endl;
    cout<<"arr["<<n - 1<<"] = "<<arr[n - 1]<<endl;
    delete [] arr;
 
    system("pause");
    return 0;
}
 
double * parse_fscanf(long &n, double * arr)
{
    FILE * file = fopen("file.txt","rb");
    if(!file)
        cout<<"Error open file.txt\n";
    else
    {
        fscanf(file,"%u",&n);
        arr = new double[n];
        for(long i = 0; i < n; i++)
            fscanf(file,"%lf",&arr[i]);
        fclose(file);
    }
    return arr;
}
 
double * parse_strtok(long &n, double * arr)
{
    char * tok;
    char * str;
    char delim[] = " \n";
    long i,sLen;
    FILE * file = fopen("file.txt","rb");
    if(!file)
        cout<<"Error open file.txt\n";
    else
    {
        fseek(file,0,SEEK_END);
        sLen = ftell(file);
        fseek(file,0,SEEK_SET);
        if(!(str = (char *)malloc(sizeof(char)*(sLen + 1))))
            cout<<"Allocation memory error\n";
        else
        {
            fread(str,1,sLen,file);
            str[sLen] = '\0';
        }
        fclose(file);
        if(str)
        {
            
            tok = strtok(str,delim);
            n = atoi(tok);i = 0;
            arr = new double[n];
            tok = strtok(NULL,delim);
            while(tok)
            {
                arr[i++] = atof(tok);
                tok = strtok(NULL,delim);
            }
        }
    }
    return arr;
}
 
double * parse_ifstrm(long &n, double * arr)
{
    ifstream ifs("file.txt");
    if(!ifs)
        cout<<"Error open file.txt\n";
    else
    {
        ifs>>n;
        arr = new double[n];
        for(long i = 0; i < n && !ifs.eof(); i++)
            ifs>>arr[i];
        ifs.close();
    }
    return arr;
}


Сравнительная таблица на миниатюре. Как видим быстро отработали 1-й и 2-й варианты, но
спешу заметить посмотрите сколько операций именно во 2-м варианте - в два раза больше чем в
1-м, а время работы идентично, так что выводы делайте сами...
PS:Плюсовый вариант прямого чтения ifstream>> явообще отбросил для себя
(даже и не думал что это такой ужас в плане времени)
Миниатюры
Быстрое чтение файла   Быстрое чтение файла  
programina
 Аватар для programina
1912 / 597 / 37
Регистрация: 23.10.2011
Сообщений: 4,468
Записей в блоге: 2
11.11.2011, 18:44  [ТС]     Быстрое чтение файла #34
Если не использовать cout, то на заполнение файла у меня ушло ~5 сек
Чтение фсканфом у меня в 4 раза быстрее чем ifstream
А strtok у меня not declared in this scope
greeezz
272 / 165 / 4
Регистрация: 10.07.2011
Сообщений: 441
11.11.2011, 18:47     Быстрое чтение файла #35
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
спешу заметить посмотрите сколько операций именно во 2-м варианте - в два раза больше чем в 1-м, а время работы идентично, так что выводы делайте сами...
осмелюсь предположить что fscanf за сценой делает аналогичные операции что и strtok и atof вместе взятые. отсюда и одинаковое время.
з.ы. было бы информативно проверить результаты действия разных вариантов с точносттю не до секунды, а до миллисекунды. возможно разница всетаки есть.
Байт
 Аватар для Байт
13947 / 8778 / 1221
Регистрация: 24.12.2010
Сообщений: 15,884
11.11.2011, 18:50     Быстрое чтение файла #36
Вот
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
#include <stdio.h>
#include <time.h>
 
#define afc(j,n) for(j=0; j<n; j++)  // Пара макросов, украшающих жизнь
#define SD sizeof(double)
 
main()
{  time_t Beg, End; int k;
 
  // full();
  afc(k,2) {
    Beg = time(NULL);
    readx(k);
    End = time(NULL);
    printf("k=%d Time=%f sec\n", k, difftime(End, Beg));
  }
}
/************/
full()
{ double d=3.14; FILE *f; long j;
 
   f = fopen("test.tst", "wb");
   printf("full:bsize=%d buffer=%d\n", f->bsize, f->buffer!=NULL);
   afc(j,4000000L) fwrite(&d, 1, SD, f);
   fclose(f);
}
/*************/
readx(int k)
{ double d; FILE *f;
 
   f = fopen("test.tst", "rb");
   if (k) setvbuf(f, NULL, _IONBF, 0);
   printf("%d:bsize=%d buffer=%d\n", k, f->bsize, f->buffer!=NULL);
   while(fread(&d, SD, 1, f)==1);
   fclose(f);
}
/*************/
/* Результат:
0:bsize=512 buffer=1
k=0 Time=1.000000 sec
1:bsize=0 buffer=1
k=1 Time=61.000000 sec
*/
Thinker, сдавайтесь!
programina
 Аватар для programina
1912 / 597 / 37
Регистрация: 23.10.2011
Сообщений: 4,468
Записей в блоге: 2
11.11.2011, 19:04  [ТС]     Быстрое чтение файла #37
У меня не работает

error: 'readx' was not declared in this scope
talis
 Аватар для talis
789 / 541 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
11.11.2011, 19:09     Быстрое чтение файла #38
допишите вверх под макросы:

C
1
2
int readx( int );
int full();
greeezz
272 / 165 / 4
Регистрация: 10.07.2011
Сообщений: 441
11.11.2011, 19:09     Быстрое чтение файла #39
Цитата Сообщение от programina Посмотреть сообщение
error: 'readx' was not declared in this scope
это потому что функция main объявлена раньше функции readx.
поменяйте местами или объявите прототипы.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
11.11.2011, 19:10     Быстрое чтение файла
Еще ссылки по теме:

C++ Быстрое преобразование фурье wave файла
Преобразование текстового файла в двоичный и чтение исходных данных из двоичного файла. C++
C++ Быстрое создание бинарного файла заданного размера

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

Или воспользуйтесь поиском по форуму:
talis
11.11.2011, 19:10     Быстрое чтение файла
  #40

Не по теме:

Байт, а это что у вас за компилятор, который нашёл функции без объявления перед использованием?

Yandex
Объявления
11.11.2011, 19:10     Быстрое чтение файла
Ответ Создать тему
Опции темы

Текущее время: 21:07. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru