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

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

Войти
Регистрация
Восстановить пароль
 
Kant
32 / 32 / 9
Регистрация: 15.05.2013
Сообщений: 229
#1

Есть очень много маленьких текстовых файлов необходимо слить в один файл - C++

05.01.2014, 03:03. Просмотров 1087. Ответов 13
Метки нет (Все метки)

Очень много маленьких файлов размером от 500 КБ до 90 МБ. Максимальная длина строки в файлах 80 символов.
Всего таких файлов может быть от 2 гигабайт и более. Посоветуйте, как подступиться к программе чтобы она работала максимально быстро.
Вот что я намудрил пока. Чтение и запись с помощью С++ отпадает слишком медленно или я не знаю как по другому. Сижу под Win 7.

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
        list<wstring> allPathFilesPdn = get_path_pdn(pathIn, ext); // получаем пути к файлам
        for (auto it = allPathFilesPdn.cbegin(); it != allPathFilesPdn.cend(); ++it) {
            read_and_write(*it, pathAddWriteFilePDN);
        }
 
 
 
void FindToPdnBase::read_and_write(const wstring &pathRead, const wstring &pathAddWrite) {
    FILE * pFileRead = _wfopen ( pathRead.c_str() , L"rb" );
 
    int seekres = fseek (pFileRead, 0, SEEK_END);
 
    long lSize = ftell (pFileRead);
    char *buffer = (char*) malloc (sizeof(char)*lSize);
 
    rewind (pFileRead);
    size_t result = fread (buffer,1,lSize,pFileRead);
 
    fclose (pFileRead);
 
    FILE * pFileWrite = _wfopen ( pathAddWrite.c_str(), L"ab" );
 
    size_t written = fwrite (buffer, sizeof(char), result, pFileWrite);
 
    fclose (pFileWrite);
 
    free (buffer);
}
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
05.01.2014, 03:03     Есть очень много маленьких текстовых файлов необходимо слить в один файл
Посмотрите здесь:

C++ Объединить несколько файлов в один файл, а потом добавлять туда еще файлы
C++ Проблемка с скачиванием не маленьких файлов в цикле
C++ Как определить, есть ли файл на диске. Проверка двух файлов
Слить один два файла в один C++
C++ Ввод/вывод очень маленьких чисел
Нужен листинг на С++ (даны два вектора, упорядоченные по возрастанию. Слить их в один вектор, так чтобы сохранилась упорядоченность) C++
Сравнить содержание двоих текстовых файлов и вывести на экран номера строк в каких есть отличия C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
alsav22
5415 / 4811 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
05.01.2014, 03:38     Есть очень много маленьких текстовых файлов необходимо слить в один файл #2
Когда-то выяснял какими функциями быстрее всего работать с файлами. Получилось, что самые быстрые - это С-функции пстрочного чтения/записи: fgets(), fputs(). Файл нужно открывать в бинарном режиме, это убыстряет работу этих функций (почему - не знаю, но факт). Насколько знаю, работа с динамической памятью - это медленно, поэтому лучше использовать массив на стеке под размер строки (тем более, размер известен).
Kant
32 / 32 / 9
Регистрация: 15.05.2013
Сообщений: 229
05.01.2014, 03:41  [ТС]     Есть очень много маленьких текстовых файлов необходимо слить в один файл #3
Цитата Сообщение от alsav22 Посмотреть сообщение
Когда-то выяснял какими функциями быстрее всего работать с файлами. Получилось, что самые быстрые - это С-функции пстрочного чтения/записи: fgets(), fputs(). Файл нужно открывать в бинарном режиме, это убыстряет работу этих функций (почему - не знаю, но факт). Насколько знаю, работа с динамической памятью - это медленно, поэтому лучше использовать массив на стеке под размер строки (тем более, размер известен).
Спасибо. Сейчас попробую.
gromo
370 / 269 / 24
Регистрация: 04.09.2009
Сообщений: 1,214
05.01.2014, 04:00     Есть очень много маленьких текстовых файлов необходимо слить в один файл #4
Цитата Сообщение от Kant Посмотреть сообщение
Сижу под Win 7.
Если бы пересели на *nix, то решение вашей проблемы:
Bash
1
cat * > file
Ну или на Си:
C
1
int main() { system("cat * > file"); }
А так мудрите
gazlan
3130 / 1905 / 285
Регистрация: 27.08.2010
Сообщений: 5,132
Записей в блоге: 1
05.01.2014, 04:26     Есть очень много маленьких текстовых файлов необходимо слить в один файл #5
Цитата Сообщение от Kant Посмотреть сообщение
Чтение и запись с помощью С++ отпадает
Потоками, разумеется, лучше не пользоваться. Никаким "построчным" чтением тоже.

Используйте Memory Mapping (WinAPI) - открываете Src файл на чтение и "одним глотком" переписываете в Dst. Если файлы маленькие, то основное время уйдет не на копирование, а на сам поиск/открытие/закрытие. Если необходимо, добавляйте в Dst символ новой строки после каждого записанного файла.
Kant
32 / 32 / 9
Регистрация: 15.05.2013
Сообщений: 229
05.01.2014, 04:43  [ТС]     Есть очень много маленьких текстовых файлов необходимо слить в один файл #6
Цитата Сообщение от alsav22 Посмотреть сообщение
Когда-то выяснял какими функциями быстрее всего работать с файлами. Получилось, что самые быстрые - это С-функции пстрочного чтения/записи: fgets(), fputs(). Файл нужно открывать в бинарном режиме, это убыстряет работу этих функций (почему - не знаю, но факт). Насколько знаю, работа с динамической памятью - это медленно, поэтому лучше использовать массив на стеке под размер строки (тем более, размер известен).
Написал вот такую штуку. Медленней чем мой код. Посмотри пожалуйста может что то не так сделал.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    FILE * pFileRead = _wfopen ( pathRead.c_str() , L"rb" );
    if(!pFileRead) return;
 
    FILE * pFileWrite = _wfopen ( pathAddWrite.c_str(), L"ab" );
    char buffer[80];
 
    while(!feof(pFileRead)) {
        if(fgets(buffer, 80, pFileRead) != 0)
            fputs(buffer, pFileWrite);
    }
 
    fputs("\0", pFileWrite);
 
    fclose (pFileRead);
    fclose (pFileWrite);
}
Добавлено через 1 минуту
Цитата Сообщение от gazlan Посмотреть сообщение
Потоками, разумеется, лучше не пользоваться. Никаким "построчным" чтением тоже.

Используйте Memory Mapping (WinAPI) - открываете Src файл на чтение и "одним глотком" переписываете в Dst. Если файлы маленькие, то основное время уйдет не на копирование, а на сам поиск/открытие/закрытие. Если необходимо, добавляйте в Dst символ новой строки после каждого записанного файла.
Читал об этом. Но на моем уровне задача неподъемная. Если бы показали маленький пример был бы благодарен!
alsav22
5415 / 4811 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
05.01.2014, 05:29     Есть очень много маленьких текстовых файлов необходимо слить в один файл #7
Цитата Сообщение от Kant Посмотреть сообщение
Написал вот такую штуку. Медленней чем мой код.
Насчёт меделнней или быстрей ничего нового не скажу, что знал и пробовал - изложил. Забыл только сказать, что в Release нужно делать.
C++
1
2
while(fgets(buffer, 80, pFileRead)) 
       fputs(buffer, pFileWrite);
gazlan
3130 / 1905 / 285
Регистрация: 27.08.2010
Сообщений: 5,132
Записей в блоге: 1
05.01.2014, 05:39     Есть очень много маленьких текстовых файлов необходимо слить в один файл #8
Цитата Сообщение от Kant Посмотреть сообщение
маленький пример
Эташ.
Вложения
Тип файла: 7z Joiner.7z (8.9 Кб, 56 просмотров)
gazlan
3130 / 1905 / 285
Регистрация: 27.08.2010
Сообщений: 5,132
Записей в блоге: 1
05.01.2014, 05:42     Есть очень много маленьких текстовых файлов необходимо слить в один файл #9
Цитата Сообщение от alsav22 Посмотреть сообщение
убыстряет работу этих функций (почему - не знаю, но факт)
Нет затрат на трансляцию EOL.
Kant
32 / 32 / 9
Регистрация: 15.05.2013
Сообщений: 229
05.01.2014, 06:07  [ТС]     Есть очень много маленьких текстовых файлов необходимо слить в один файл #10
Цитата Сообщение от gazlan Посмотреть сообщение
Эташ.
Ого! Вот что то такого и боялся )
Kant
32 / 32 / 9
Регистрация: 15.05.2013
Сообщений: 229
05.01.2014, 06:16  [ТС]     Есть очень много маленьких текстовых файлов необходимо слить в один файл #11
Цитата Сообщение от alsav22 Посмотреть сообщение
Насчёт меделнней или быстрей ничего нового не скажу, что знал и пробовал - изложил. Забыл только сказать, что в Release нужно делать.
C++
1
2
while(fgets(buffer, 80, pFileRead)) 
       fputs(buffer, pFileWrite);
Угу. В Release запускал. С меня, правда, такой тестер ) Переключил на Релиз и прогнал пару раз. Измеряю время вот так:
C++
1
2
3
4
5
6
7
    DWORD start = GetTickCount();
    FindToPdnBase(L"D:\\Партии\\PDN", L".pdn", L"D:\\MegaBase.pdn");
    DWORD finish = GetTickCount();
    
    cout << "\tПрограмма управилась за "  << finish - start << "\n";
 
Надо бы саму функцию, но решил весь класс.
Зато с вашим советом память вообще не тратится )) И в среднем на 2-3 секунды медленней, что по сути ерунда. И
код короче намного ) Буду теперь только так юзать
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void FindToPdnBase::read_and_write(const wstring &pathRead, const wstring &pathAddWrite) {
    FILE * pFileRead = _wfopen ( pathRead.c_str() , L"rb" );
    if(!pFileRead) return;
 
    FILE * pFileWrite = _wfopen ( pathAddWrite.c_str(), L"ab" );
    static char buffer[80];
 
    while(fgets(buffer, 80, pFileRead))
            fputs(buffer, pFileWrite);
 
    fputs("\0", pFileWrite);
 
    fclose (pFileRead);
    fclose (pFileWrite);
}
alsav22
5415 / 4811 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
05.01.2014, 06:27     Есть очень много маленьких текстовых файлов необходимо слить в один файл #12
Я вот на таком коде пробую (в студии 10). В файле 1000000 строк, размер каждой - около 45 символов. Размер файла 46.7мгб.
Если построчно: Debug - 0.83, Release - 0.5.
Если блоком, размером в файл: Debug - 0.84, Release - 0.813.
Получается, что самое быстрое - построчно, и именно в Release (оптимизация там для построчного лучше сделана или что, не знаю. Оптимизация выставлена - максимальная скорость).
Кликните здесь для просмотра всего текста
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
include <iostream>
#include <string>
#include <ctime>
#include <fstream>
 
using namespace std;
 
const int N = 1000000; // количество строк в файле
const int L = 500;     // длина строки
 
void createfile() //создание файла для теста
{
    string str = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
    ofstream fout("file1.txt");
    for (int i = 0; i < N; ++i)
    {
        fout << i + 1;
        fout << str << endl;
    }
    fout.close();
}
 
int main()
{
    //createfile(); //создание файла для теста
    
    clock_t t1 = clock();
    FILE *fin = fopen("file1.txt", "rb"); // в бинарном быстрее
    
    if (!fin) printf("Error!\n");
    else
    {
        FILE *fout = fopen("file2.txt", "wb");
        
        // построчно
      //begin...............................
        
        char str1[L] = {'\0'};       
        while (fgets(str1, L, fin)) 
                fputs(str1, fout);
      //end ...................................     
        
        // блоком, размером с размер файла
     //begin...............................
        
        /*fseek(fin, 0, SEEK_END); 
        int size = ftell(fin);
        char * buffer = (char*) malloc(size);
        
        rewind(fin);
        fread(buffer, 1, size, fin);
        fwrite(buffer, 1, size, fout);
        free(buffer);*/
     
     //end ...................................  
        
        fclose(fout);
        fclose(fin);
        
        clock_t t2 = clock();
        printf("%f\n", (t2 - t1 + .0) / CLOCKS_PER_SEC); // время отработки
    }
  
    system("pause");
    return 0;
}
gazlan
3130 / 1905 / 285
Регистрация: 27.08.2010
Сообщений: 5,132
Записей в блоге: 1
05.01.2014, 06:46     Есть очень много маленьких текстовых файлов необходимо слить в один файл #13
Цитата Сообщение от Kant Посмотреть сообщение
такого и боялся
Там уже скомпилированная аппликация. Просто запустите ее на вашем наборе.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
05.01.2014, 13:12     Есть очень много маленьких текстовых файлов необходимо слить в один файл
Еще ссылки по теме:

C++ Очень много ошибок в программе
Слить несколько txt-файлов в один C++
Разделить файл txt на несколько равных маленьких файлов C++
Слить вектора в один вектор {z},i=1,...20 так, чтобы сохранилась упорядоченность C++
C++ Объединение данных из N файлов в один файл

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

Или воспользуйтесь поиском по форуму:
Kant
32 / 32 / 9
Регистрация: 15.05.2013
Сообщений: 229
05.01.2014, 13:12  [ТС]     Есть очень много маленьких текстовых файлов необходимо слить в один файл #14
Цитата Сообщение от gazlan Посмотреть сообщение
Там уже скомпилированная аппликация. Просто запустите ее на вашем наборе.
Спасибо! Но хотел получить что нибудь для понимания, а потом уже с наработанными деталями. Но все равно спасибо, код там не сложный некоторые функции погуглить.
Yandex
Объявления
05.01.2014, 13:12     Есть очень много маленьких текстовых файлов необходимо слить в один файл
Ответ Создать тему
Опции темы

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