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

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

Войти
Регистрация
Восстановить пароль
 
jkchief
0 / 0 / 0
Регистрация: 19.02.2013
Сообщений: 8
#1

Подсчет строк в гигантском текстовом файле > 4 Гб - C++

19.02.2013, 01:25. Просмотров 838. Ответов 8
Метки нет (Все метки)

Всем привет, я новичок в С++, но очень стараюсь. Прочитал Дейтелов и теперь хочу сделать что-то практическое и полезное.

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

Начало было положено с написания кода, который выполнял подсчет строк в файле с помощью std::getline(), но к сожалению гетлайн не подходит для работы с большими файлами, и считает долго. Гигантский файл в память не загрузишь.

Второй итерацией был написан код, представленный чуть ниже, в нем использовал принцим File memory mapping. И чтение файла ведется порциями по 1 МБ.
Написано в VS2012 С++.
Все работает чудесно, но уперся в ограничение 32 битов unsigned long.... обрабатывает файлы до 4 гб.
А у меня на винте лежит словарик в 24 Гб....хотелось бы его посчитать.
Подскажите ответ на 2 вопроса:
1) можно ли побороть проблемму на 32 битной системе
2) куда копать чтобы реализовать на 64 битах?

Реально первая прога, которую написал не по учебнику, был бы также рад услышать конструктивную критику если заметите признаки говнокода.
Код:
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#include "stdafx.h"
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
using std::cerr;
#include <string>
using std::string;
#include <fstream>
using std::ifstream;
#include <Windows.h>
 
 
string man = "This is programm to count number of lines in text file.\nTo use program type:\ncounter.exe \"filename\"\n\n";
static int numlines=1;
DWORD BUFFERSIZE = 1048576;//buffer size for memory mapping. 1 Mb by default. You can change it to play with performance.
HANDLE hMapFile;      // handle for the file's memory-mapped region
HANDLE hFile;         // the file handle
DWORD dwFileSize;     // temporary storage for file sizes
LPVOID lpMapAddress;  // pointer to the base address of the memory-mapped region
SYSTEM_INFO SysInfo;  // system information; used to get granularity
DWORD dwSysGran;      // system allocation granularity
char * pData;         // pointer to the data
DWORD dwi=0;          // loop counter
BOOL bFlag;           // a result holder
DWORD dwMapViewSize;  // number of bytes to map
DWORD dwCurrentPosition; //position where to start mapping of the file
DWORD dwIterationTimes; //number of iterations to mat the file to the memory
DWORD dwFileMapSize;   // size of the file mapping
 
 
 
int _tmain(int argc, _TCHAR* argv[])
{
    //we accept only one file name
    if (argc != 2 ){cout << man; 
    exit(1);}
     _tprintf(TEXT("Open file \"%s\" for line counting.\n"), argv[1]);
 
// Open the file 
  hFile = CreateFile(argv[1],
                     GENERIC_READ,
                     0,
                     NULL,
                     OPEN_EXISTING,
                     FILE_ATTRIBUTE_NORMAL,
                     NULL);
 
  if (hFile == INVALID_HANDLE_VALUE)
  {_tprintf(TEXT("Target file \"%s\" does not exist. Try to check spelling.\n"), argv[1]);
    exit(1);};
 
 
    //Now we will count some variables ************************************
    //Gety file size.
    dwFileSize = GetFileSize(hFile,  NULL);
    _tprintf(TEXT("File size is: %3d bites\n"), dwFileSize); 
 
    // Get the system allocation granularity.
    GetSystemInfo(&SysInfo);
    dwSysGran = SysInfo.dwAllocationGranularity;
    //_tprintf(TEXT("system allocation granularity is: %d\n"), dwSysGran);
 
    //Calculate number iterations to read all file maps
    
    if (dwFileSize <= BUFFERSIZE) {dwIterationTimes = 1;};
            if (dwFileSize > BUFFERSIZE) {
                DWORD dba = dwFileSize % BUFFERSIZE ;
                if ( dba == 0)  {dwIterationTimes = dwFileSize / BUFFERSIZE;};
                if (dba > 0)  {dwIterationTimes = (dwFileSize / BUFFERSIZE)+1;};
            };
        //_tprintf(TEXT("Iterations: %3d\n"), dwIterationTimes);
 
 
        // now we count some changing variables for cycle
        for  (DWORD c=0 ; c < dwIterationTimes; c=c+1 ) {
                //Count file mapping size and wiev size size for NOT last itteration
                if (c < dwIterationTimes-1){
                    dwMapViewSize=BUFFERSIZE;
                    dwFileMapSize = (c * BUFFERSIZE)  + BUFFERSIZE; //file mapping size
                    //_tprintf (TEXT("The middle file mapping object is %ld bytes large for %ld itteration\n"),dwFileMapSize, c+1);
                    };
 
                ///Count file mapping size and wiev size for last itteration itteration
                if (c == dwIterationTimes-1){
                    DWORD d = (dwFileSize - (c * BUFFERSIZE));//length of last part (less than buffersize)
                    //_tprintf (TEXT("Current offset is %ld, Length of last part of file is %ld \n"),(c * BUFFERSIZE), d);
                    dwMapViewSize = d;
                    dwFileMapSize = dwFileSize;
                    //_tprintf (TEXT("The LAST file mapping object is %ld bytes large for %ld itteration\n"),dwFileMapSize, c+1);
                };//if it is last operation we do not need to allocate all buffer size
        
        
                // Create a file mapping object for the file
                hMapFile = CreateFileMapping( hFile,          // current file handle
                    NULL,           // default security
                    PAGE_READONLY,  // read permission
                    0,              // size of mapping object, high
                    dwFileMapSize,  // size of mapping object, low
                    NULL);          // name of mapping object
                //That it is a good idea to ensure the file size is not zero
                if (hMapFile == NULL)
                    {
                    _tprintf(TEXT("hMapFile is NULL\n"));
                    exit(2);
                    };
 
                // Map the view and test the results.       
                lpMapAddress = MapViewOfFile(hMapFile,            // handle to mapping object
                               FILE_MAP_READ,       // read/write
                               0,                   // high-order 32 bits of file offset
                               (c * BUFFERSIZE),    // low-order 32 bits of file offset
                               dwMapViewSize);      
                if (lpMapAddress == NULL)
                {
                _tprintf(TEXT("lpMapAddress is NULL: last error: %d\n"), GetLastError());
                exit(1);
                }
                else {
                //  _tprintf(TEXT("lpMapAddress is: %d\n"), lpMapAddress);
                };
 
 
                //pointer to the data.
                pData = (char *) lpMapAddress ;
 
                // At last!!! Data processing.************************************************* 
  
                for (dwi=0; dwi < dwMapViewSize ; dwi=dwi+1) {
                if (pData[dwi] == '\n'){numlines++;};
                };
                
 
                // Close the file mapping object and the open file
                 bFlag = UnmapViewOfFile(lpMapAddress);
                 bFlag = CloseHandle(hMapFile); // close the file mapping object
                 if(!bFlag) { _tprintf(TEXT("\nError %ld occurred closing the mapping object!"), GetLastError());}
 
        };//end of for
 
        bFlag = CloseHandle(hFile);   // close the file itself
        if(!bFlag) { _tprintf(TEXT("\nError %ld occurred closing the file!"), GetLastError());}
        
        
        cout << "Number of lines in our file is: " << numlines << endl;
    return 0;
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
19.02.2013, 01:25
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Подсчет строк в гигантском текстовом файле > 4 Гб (C++):

Подсчет количества цифр в текстовом файле - C++
написать программу,которая в текстовом файле,состоящем из строк не более 60 символов,находит количество цифр

Подсчет количества предложений в текстовом файле - C++
Сама задача:Подсчитать число предложений в заданном текстовом файле (текст на английском языке). Предложением считается последовательность...

Подсчет количества символов русского алфавита в текстовом файле - C++
Здравствуйте, нужна ваша помощь) Допустим у нас имеется текстовой файл Test.txt( в нем находятся русские буквы и другие... символы и...

Программа для поиска соответствие строк, учитывая регистр, в текстовом файле с 10000+ строк - C++
Уважаемые форумчане, прошу у вас помощи я неделю в поисках. Мне нужна программа или код для поиска слов, очень похожую на расширение Pearls...

Сделать подсчет частоты встречаемости последовательности символов АБВ в текстовом файле - C++
Народ помогите пожалуйста решить задачу: подсчет частоты встречаемости последовательности символов АБВ в текстовом файле?

Центрирование строк в текстовом файле - C++
Длина строк текстового файла не может превышать 80 символов. Нужно разместить все эти строки по центру. Вроде как идея такая... Сначала...

8
Toshkarik
1141 / 858 / 51
Регистрация: 03.08.2011
Сообщений: 2,386
Завершенные тесты: 1
19.02.2013, 04:33 #2
Есть ведь 64 битный тип long long int в новом стандарте. Так же есть тип std::size_t, который в 64 битной программе так же 64 битный.
0
WhiteP
606 / 204 / 23
Регистрация: 20.11.2012
Сообщений: 426
19.02.2013, 09:07 #3
Цитата Сообщение от jkchief Посмотреть сообщение
1) можно ли побороть проблемму на 32 битной системе
// high-order 32 bits of file offset
в MapViewOfFile и соответствующие максимумы в CreateFileMapping для чего по твоему?
Нужно двигать отображение. Смапил кусок, обработал, анмап. Смапил следующий кусок, обработал, анмап.
И не нужно закрывать хэндл FileMappingObject'a каждую итерацию и создавать снова для одного и того же файла.
1
jkchief
0 / 0 / 0
Регистрация: 19.02.2013
Сообщений: 8
19.02.2013, 14:10  [ТС] #4
Цитата Сообщение от WhiteP Посмотреть сообщение
в MapViewOfFile и соответствующие максимумы в CreateFileMapping для чего по твоему?
Нужно двигать отображение. Смапил кусок, обработал, анмап. Смапил следующий кусок, обработал, анмап.
И не нужно закрывать хэндл FileMappingObject'a каждую итерацию и создавать снова для одного и того же файла.
Про хендл понял, вынесу за цикл, спасибо.
А вот с остальным как-то не очень.В мануалах и примерах не нашел пример использования... уж не забросайте помидорами.
Я не совсем понимаю как игратся с єтими
// size of mapping object, high
// size of mapping object, low

// high-order 32 bits of file offset
// low-order 32 bits of file offset

Какие мне DWORD значения в 32 битном приложении нужно подставить чтобы прочитать из файла размером > 40GB
Скажем, начиная с офсета в 42 949 672 960 B байта (40Gb) до 42 950 721 536 байта (40Gb + 1 Mb).


C++
1
2
3
4
5
6
7
8
9
10
11
12
hMapFile = CreateFileMapping( hFile,          // current file handle
                    NULL,           // default security
                    PAGE_READONLY,  // read permission
                    ??????,              // size of mapping object, high
                    ??????, // size of mapping object, low
                    NULL);          // name of mapping object
 
lpMapAddress = MapViewOfFile(hMapFile,            // handle to mapping object
                               FILE_MAP_READ,       // read/write
                               ??????,                   // high-order 32 bits of file offset
                               ??????// low-order 32 bits of file offset
                               dwMapViewSize);
0
WhiteP
606 / 204 / 23
Регистрация: 20.11.2012
Сообщений: 426
19.02.2013, 14:53 #5
Ну вот. А вообще используй long long или int64
1
Миниатюры
Подсчет строк в гигантском текстовом файле > 4 Гб  
jkchief
0 / 0 / 0
Регистрация: 19.02.2013
Сообщений: 8
19.02.2013, 16:30  [ТС] #6
Ответ не до конца понятен.
CreateFileMapping и MapViewOfFile принимают значения DWORD. (typedef unsigded long DWORD)....32 бита на сколько я понимаю. Разве я могу скармливать им long long? Или мне нужно дополнительно какой-то функцией распарсить побитно long long на два DWORDа и скармливать отдельно старшую и младшую часть?

Тоесть применимо к моему вопросу будет ли работатьзначения подставленные ниже?

Есть ли вобще смысл заморачиватся и высчитывать CreateFileMapping размеры, я так понимаю можно подставить нули и смапится тогда весь файл.
Ведь эта функция не жрет память?
CreateFileMapping //
0 // size of mapping object, high
0 // size of mapping object, low


MapViewOfFile
10 // high-order 32 bits of file offset 0000 0000 0000 0000 0000 0000 0000 1010
0 // low-order 32 bits of file offset 0000 0000 0000 0000 0000 0000 0000 0000
1048576// number of bytes to map (1 MB)

Добавлено через 8 минут
А как получить размер большого файла для 32 бит приложения, или мне неменуемо нужно переезджать на 64?
0
WhiteP
606 / 204 / 23
Регистрация: 20.11.2012
Сообщений: 426
19.02.2013, 16:34 #7
Цитата Сообщение от jkchief Посмотреть сообщение
дополнительно какой-то функцией распарсить побитно long long на два DWORDа и скармливать отдельно старшую и младшую часть?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <windows.h>
 
int main()
{
    __int64 x = 42949672960;
    DWORD low = (DWORD)x;
    DWORD high = (DWORD)(x>>32);
 
    std::cout<<x<<std::endl;
    std::cout<<low<<std::endl;
    std::cout<<high<<std::endl;
 
 
    return 0;
}
Добавлено через 3 минуты
Цитата Сообщение от jkchief Посмотреть сообщение
А как получить размер большого файла для 32 бит приложения, или мне неменуемо нужно переезджать на 64?
GetFileSize(обрати внимание на второй параметр)
http://msdn.microsoft.com/en-us/libr...(v=vs.85).aspx
1
jkchief
0 / 0 / 0
Регистрация: 19.02.2013
Сообщений: 8
20.02.2013, 13:09  [ТС] #8
Переделал все с учетом работы с большими файлами, намучался с этими типами данных...но теперь как-то криво работать начало. Вроде считает строки, но для разных размеров буфера памяти выдает разные результаты.
Для примера скормил словарь обьемом в 835Мб своей проге и сторонней, выдаются разные варианты.
Скорей всего логическая ошибка, помогите выявить.
Подсчет строк в гигантском текстовом файле > 4 Гб

Сам код вот какой теперь:

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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#include "stdafx.h"
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
using std::cerr;
#include <string>
using std::string;
#include <Windows.h>
#include <time.h>
 
 
string man = "This is programm to count number of lines in text file.\nTo use program type:\ncounter.exe \"filename\"\n\n";
static int numlines=1;
LARGE_INTEGER liBufferSize; //buffer size for memory mapping. 1 Mb by default. You can change it to play with performance.
HANDLE hMapFile;      // handle for the file's memory-mapped region
HANDLE hFile;         // the file handle
LARGE_INTEGER liFileSize; // temporary storage for file sizes for big files
LPVOID lpMapAddress;  // pointer to the base address of the memory-mapped region
SYSTEM_INFO SysInfo;  // system information; used to get granularity
DWORD dwSysGran;      // system allocation granularity
char * pData;         // pointer to the data
int inti=0;          // loop counter for data manipulation
BOOL bFlag;           // a result holder
int intIterationTimes; //number of iterations to mat the file to the memory
LARGE_INTEGER liMapViewSize;  // number of bytes to map
LARGE_INTEGER liOffset; //current position holder
 
 
 
int _tmain(int argc, _TCHAR* argv[])
{
    clock_t tStart = clock();
    liBufferSize.LowPart = 1048576;// 1 Mb by default. You can change it to play with performance.
    
    //we accept only one file name
    if (argc != 2 ){cout << man; 
    exit(1);}
     _tprintf(TEXT("Open file \"%s\" for line counting.\n"), argv[1]);
 
// Open the file 
  hFile = CreateFile(argv[1],
                     GENERIC_READ,
                     0,
                     NULL,
                     OPEN_EXISTING,
                     FILE_ATTRIBUTE_NORMAL,
                     NULL);
 
    if (hFile == INVALID_HANDLE_VALUE)
    {_tprintf(TEXT("Target file \"%s\" does not exist. Try to check spelling.\n"), argv[1]);
    exit(1);
    };
 
 
    //Now we will count some variables ************************************
    //Gety file size.
    GetFileSizeEx(hFile, &liFileSize);
    _tprintf(TEXT("File size is: %I64d bites\n"), liFileSize.QuadPart); 
    
    // Get the system allocation granularity.
    GetSystemInfo(&SysInfo);
    dwSysGran = SysInfo.dwAllocationGranularity;
    _tprintf(TEXT("system allocation granularity is: %d\n"), dwSysGran);
 
    //Calculate number iterations to read all file maps
    if (liFileSize.QuadPart <= liBufferSize.QuadPart) {intIterationTimes = 1;};
    if (liFileSize.QuadPart > liBufferSize.QuadPart) {
                LONGLONG dba = liFileSize.QuadPart % liBufferSize.QuadPart ;
                if ( dba == 0)  {intIterationTimes = (int)(liFileSize.QuadPart / liBufferSize.QuadPart);};
                if (dba > 0)  {intIterationTimes = (int)((liFileSize.QuadPart / liBufferSize.QuadPart)+1);};
    };
    _tprintf(TEXT("Iterations: %u \n"), intIterationTimes);
 
    // Create a file mapping object for the file
    hMapFile = CreateFileMapping( hFile,          // current file handle
            NULL,           // default security
            PAGE_READONLY,  // read permission
            (DWORD)liFileSize.HighPart,  // size of mapping object, high
            liFileSize.LowPart, // size of mapping object, low
            NULL);          // name of mapping object
    //That it is a good idea to ensure the file size is not zero
    if (hMapFile == NULL){
        _tprintf(TEXT("hMapFile is NULL\n"));
        exit(2);
    };
 
 
    // now we count some changing variables for cycle
    for  (int intc=0 ; intc < intIterationTimes; intc++ ) {
        //Count  map wiev size  for NOT last itteration
        if (intc < intIterationTimes-1){
            liMapViewSize.LowPart=liBufferSize.LowPart;
        //  _tprintf (TEXT("The middle file mapping view is %I64d bytes large for %i itteration\n"),liMapViewSize.QuadPart, (intc+1));
            };
 
        ///Count file wiev size and current offset for last itteration 
        if (intc == intIterationTimes-1){
            liMapViewSize.QuadPart = (liFileSize.QuadPart - (   (LONGLONG)intc * liBufferSize.QuadPart)  );//length of last part (less than liBufferSize)
            liOffset.QuadPart= (LONGLONG)intc * liBufferSize.QuadPart;
            _tprintf (TEXT("Current offset is %I64d, Length of last part of view is %I64d \n"),liOffset.QuadPart, liMapViewSize.QuadPart);
            };//if it is last operation we do not need to allocate all buffer size
        
 
        // Map the view and test the results.       
        lpMapAddress = MapViewOfFile(
                hMapFile,               // handle to mapping object
                FILE_MAP_READ,          // read/write
                liOffset.HighPart,      // high-order 32 bits of file offset
                liOffset.LowPart ,      // low-order 32 bits of file offset
                liMapViewSize.LowPart);  //length of the view    
        
        if (lpMapAddress == NULL){
            _tprintf(TEXT("lpMapAddress is NULL: last error: %d\n"), GetLastError());
            exit(1);}
        else {
            //_tprintf(TEXT("lpMapAddress is: %d\n"), lpMapAddress);
        };
 
 
        //pointer to the data.
        pData = (char *) lpMapAddress ;
 
        // At last!!! Data processing.************************************************* 
        for (inti=0; (DWORD)inti < liMapViewSize.LowPart ; inti++) {
                if (pData[inti] == '\n'){numlines++;};
                };
                
 
        // Close the file mapping object and the open file
         bFlag = UnmapViewOfFile(lpMapAddress);
                
    };//end of for
 
    bFlag = CloseHandle(hMapFile); // close the file mapping object
    if(!bFlag)  { _tprintf(TEXT("\nError %ld occurred closing the mapping object!"), GetLastError());}
    bFlag = CloseHandle(hFile);   // close the file itself
    if(!bFlag) { _tprintf(TEXT("\nError %ld occurred closing the file!"), GetLastError());}
        
    //now we cout the reults
    cout << "Number of lines in our file is: " << numlines << endl;
    printf("Time taken: %.2fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC);
 
    return 0;
}
0
jkchief
0 / 0 / 0
Регистрация: 19.02.2013
Сообщений: 8
20.02.2013, 14:45  [ТС] #9
Все, сам нашел, забыл вставить вычисление офсета для всех непоследних итерраций... строки считались постоянно для нулевого офсета
0
20.02.2013, 14:45
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
20.02.2013, 14:45
Привет! Вот еще темы с ответами:

Подсчитать количество строк в текстовом файле - C++
Нужно написать программу : Подсчитать количество строк в текстовом файле. Под строкой понимать совокупность символов, заканчивающихся...

Алгоритм поиска строк в текстовом файле - C++
Доброго времени суток! Есть текстовый файл размером ~65 Мб, ~605000 строк. Из этих строк необходимо выделить строки, котрые содержат...

Поиск определенных строк в текстовом файле - C++
Здравствуйте. Есть файл &quot;file.txt&quot; в котором есть строки: Bread: 3 Milk: 1 Chicken: 4 Juice: 3 Potatoes: 2 Tomatoes: 1 ...

Найти количество строк в текстовом файле - C++
я не можу написати програму для підрахування кількості стрічок в текстовому файлі. чомусь в результаті видає 3 помилки, я пишу на Turbo...


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

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

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