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

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

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

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

05.01.2014, 03:03. Просмотров 1263. Ответов 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);
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
05.01.2014, 03:03
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Есть очень много маленьких текстовых файлов необходимо слить в один файл (C++):

Слить много контейнеров в один - C++
здравствуйте, подскажите, что не так в коде, ибо не совсем правильно работает (мозг сносит уже от подобного) : void...

Слить несколько txt-файлов в один - C++
Есть задание:есть несколько файлов(txt) их нужно записать в один,то есть txt1(21)+txt(433)+txt(25)=txt(2143325).Как можно сделать?пока...

Разделить файл txt на несколько равных маленьких файлов - C++
Пожалуйста помогите. Есть большой txt там 1335478 символов Как сделать чтоб он создал папку а в ней 667 файлов по 2000 символов в каждом...

Слить один два файла в один - C++
Подскажите как слить 1 и 2 файл в 3 файл

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

Необходимо определить, есть ли в указанной строке хотя бы один элемент, равный заданному числу - C++
Дан двумерный массив n×m элементов, заполненный целыми числами. Также заданы число a и номер строки i. Необходимо определить, есть ли в...

13
alsav22
5426 / 4821 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
05.01.2014, 03:38 #2
Когда-то выяснял какими функциями быстрее всего работать с файлами. Получилось, что самые быстрые - это С-функции пстрочного чтения/записи: fgets(), fputs(). Файл нужно открывать в бинарном режиме, это убыстряет работу этих функций (почему - не знаю, но факт). Насколько знаю, работа с динамической памятью - это медленно, поэтому лучше использовать массив на стеке под размер строки (тем более, размер известен).
1
Kant
33 / 33 / 9
Регистрация: 15.05.2013
Сообщений: 236
05.01.2014, 03:41  [ТС] #3
Цитата Сообщение от alsav22 Посмотреть сообщение
Когда-то выяснял какими функциями быстрее всего работать с файлами. Получилось, что самые быстрые - это С-функции пстрочного чтения/записи: fgets(), fputs(). Файл нужно открывать в бинарном режиме, это убыстряет работу этих функций (почему - не знаю, но факт). Насколько знаю, работа с динамической памятью - это медленно, поэтому лучше использовать массив на стеке под размер строки (тем более, размер известен).
Спасибо. Сейчас попробую.
0
gromo
371 / 270 / 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"); }
А так мудрите
1
gazlan
3133 / 1909 / 285
Регистрация: 27.08.2010
Сообщений: 5,132
Записей в блоге: 1
05.01.2014, 04:26 #5
Цитата Сообщение от Kant Посмотреть сообщение
Чтение и запись с помощью С++ отпадает
Потоками, разумеется, лучше не пользоваться. Никаким "построчным" чтением тоже.

Используйте Memory Mapping (WinAPI) - открываете Src файл на чтение и "одним глотком" переписываете в Dst. Если файлы маленькие, то основное время уйдет не на копирование, а на сам поиск/открытие/закрытие. Если необходимо, добавляйте в Dst символ новой строки после каждого записанного файла.
1
Kant
33 / 33 / 9
Регистрация: 15.05.2013
Сообщений: 236
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 символ новой строки после каждого записанного файла.
Читал об этом. Но на моем уровне задача неподъемная. Если бы показали маленький пример был бы благодарен!
0
alsav22
5426 / 4821 / 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);
1
gazlan
3133 / 1909 / 285
Регистрация: 27.08.2010
Сообщений: 5,132
Записей в блоге: 1
05.01.2014, 05:39 #8
Цитата Сообщение от Kant Посмотреть сообщение
маленький пример
Эташ.
1
Вложения
Тип файла: 7z Joiner.7z (8.9 Кб, 58 просмотров)
gazlan
3133 / 1909 / 285
Регистрация: 27.08.2010
Сообщений: 5,132
Записей в блоге: 1
05.01.2014, 05:42 #9
Цитата Сообщение от alsav22 Посмотреть сообщение
убыстряет работу этих функций (почему - не знаю, но факт)
Нет затрат на трансляцию EOL.
1
Kant
33 / 33 / 9
Регистрация: 15.05.2013
Сообщений: 236
05.01.2014, 06:07  [ТС] #10
Цитата Сообщение от gazlan Посмотреть сообщение
Эташ.
Ого! Вот что то такого и боялся )
0
Kant
33 / 33 / 9
Регистрация: 15.05.2013
Сообщений: 236
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);
}
0
alsav22
5426 / 4821 / 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;
}
0
gazlan
3133 / 1909 / 285
Регистрация: 27.08.2010
Сообщений: 5,132
Записей в блоге: 1
05.01.2014, 06:46 #13
Цитата Сообщение от Kant Посмотреть сообщение
такого и боялся
Там уже скомпилированная аппликация. Просто запустите ее на вашем наборе.
1
Kant
33 / 33 / 9
Регистрация: 15.05.2013
Сообщений: 236
05.01.2014, 13:12  [ТС] #14
Цитата Сообщение от gazlan Посмотреть сообщение
Там уже скомпилированная аппликация. Просто запустите ее на вашем наборе.
Спасибо! Но хотел получить что нибудь для понимания, а потом уже с наработанными деталями. Но все равно спасибо, код там не сложный некоторые функции погуглить.
0
05.01.2014, 13:12
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
05.01.2014, 13:12
Привет! Вот еще темы с ответами:

Ввод/вывод очень маленьких чисел - C++
Народ, срочно нужно! Подскажите, как сделать чтобы при арифметических операциях в С++ можно было посчитать числа порядка 10^(-200)? А еще...

Объединение данных из N файлов в один файл - C++
Добрый день! Помогите решить следующую задачу. Существует N файлов в папке(точное количество программа должна определять сама), в...

Слить вектора в один вектор {z},i=1,...20 так, чтобы сохранилась упорядоченность - C++
даны два вектора {x}, {y}, i=1,...10, упорядоченные по возрастанию. слить их в один вектор {z},i=1,...20 так, чтобы сохранилась...

Слить много текстовых файлов в несколько, по названию - MS Word
Задача: есть несколько папок с текстовыми файлами .doc ( внутри одной папки названия файлов вида :&quot; число, буквы&quot; , &quot;число +1 , буквы&quot;) ...


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

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

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