Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 11.04.2017, 21:36   #1
UaKot
Пользователь
 
Регистрация: 16.02.2013
Сообщений: 36
По умолчанию Парсинг больших файлов

Под Linux.

У меня есть файлы размером ~ 1-2Гб, задача распарсить файл, сделать изменения, и сохранить изменённую копию. Файл размером около ~1 Гб парсится примерно 6 минут и всё успешно, то есть результат совпадает с желаемым, а с двухгигабайтными начались приколы. Программа обрабатывает где-то 1,4Гб за минут 18, потом с огромной скоростью пишет в файл какие-то данные (не мусор, tail выдаёт осмысленное содержимое), но за минут 5 размер выходного файла доходит до 20 Гб и продолжает расти. Условие на выход из цикла обработки read(...) == 0 или -1.
Как такое может быть? Откуда он вообще берёт эти данные? Будто файл никогда не заканчивается.

Последний раз редактировалось UaKot; 11.04.2017 в 22:20.
UaKot вне форума Ответить с цитированием
Старый 11.04.2017, 22:00   #2
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

Дык код покажите, тут не телепаты.

2 ГБ может переполнение int32 где-то.
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.
Alex11223 вне форума Ответить с цитированием
Старый 11.04.2017, 22:29   #3
UaKot
Пользователь
 
Регистрация: 16.02.2013
Сообщений: 36
По умолчанию

Код основной функции такой.. он не причёсан совсем

Код:
Result* standart(int fd, int fd2){
    unsigned short type;
    unsigned short mask;
    unsigned serial_number;
    unsigned time_stamp;
    unsigned size;
    unsigned all_banks_size;
    unsigned internal_flags;
    unsigned t_size;
    char name[4];
    unsigned short bank_type;
    unsigned short bank_size;
    char bdata[70000];
    int c;
    unsigned short s_bank_size;

    int er = 0;
    int su = 0;
    int ev = 0;
    int res[1040] = {0};
    //Шапка события
    while (true){
        c = read(fd, &type, 2);
        if (c == 0 || c == -1){
            if (code == -1)
                perror("Stopped by an error");
            return new Result(ev, er, su, res);
        }
        read(fd, &mask, 2);
        read(fd, &serial_number, 4);
        read(fd, &time_stamp, 4);
        read(fd, &size, 4);
        write(fd2, &type, 2);
        write(fd2, &mask, 2);
        write(fd2, &serial_number, 4);
        write(fd2, &time_stamp, 4);
        write(fd2, &size, 4);
        if (type != 1){
            char* d = new char[size];
            read(fd, d, size);
            write(fd2, d, size);
            delete[] d;
            continue;
        }
        // Информация о банках
        read(fd, &all_banks_size, 4);
        read(fd, &internal_flags, 4);

        write(fd2, &all_banks_size, 4);
        write(fd2, &internal_flags, 4);
        ev++;
        t_size = 0;
        while (t_size != all_banks_size){
            //Шапка банка
            read(fd, name, 4);
            read(fd, &bank_type, 2);
            read(fd, &bank_size, 2);
            write(fd2, name, 4 );
            write(fd2, &bank_type, 2);
            write(fd2, &bank_size, 2);
            s_bank_size = bank_size;
            if (bank_size % 8 != 0)
                bank_size += 8 - (bank_size % 8);
            t_size += bank_size + 8;
            //Тело банка
            read(fd, bdata, bank_size);

            if ( (((bdata[3] & 0xff) << 8) | (bdata[2] & 0xff)) == 193 /*193 серия*/
                && (((bdata[1] & 0xff) << 8) | (bdata[0] & 0xff)) == 2 /* CRC не сошлась */
                &&  name[0] == 'R'){ /*ROW банк*/
                er++;
                c = try_to_correct(bdata);
                if (c != -1) {
                    su++;
                    res[c]++;
                    bdata[1] = 0;
                    bdata[0] = 0;
                }
            }
            write(fd2, bdata, bank_size);
        }
    }
}
UaKot вне форума Ответить с цитированием
Старый 12.04.2017, 16:21   #4
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

ssize_t write(int fildes, const void *buf, size_t nbytes);
Field Description
int fildes The file descriptor of where to write the output. You can either use a file descriptor obtained from the open system call, or you can use 0, 1, or 2, to refer to standard input, standard output, or standard error, respectively.
const void *buf A null terminated character string of the content to write.
size_t nbytes The number of bytes to write. If smaller than the provided buffer, the output is truncated.
return value Returns the number of bytes that were written. If value is negative, then the system call returned an error.


write не обязательно запишит столько байт, сколько ему дали, может и меньше. Реальное число записаных - в результате (думается мне, с read примерно та же ситуация). У вас это все не учтено совсем.

И это не кешированый ввод-ввывод. Потому и так долго. Используйте fwrite/fread, а еще лучше std::fstream C++
Эти ваши гигабайты ворочаются от силы 30 секунд с верным кешем.
alexzk вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Сортировка больших файлов. stpdqstns Общие вопросы C/C++ 6 05.03.2013 22:52
Загрузка больших файлов Rita26 JavaScript, Ajax 2 09.08.2012 11:23
Загрузка больших файлов Rita26 Общие вопросы .NET 0 23.07.2012 14:47
Отправка больших файлов по почте pu4koff Софт 6 17.07.2012 19:35
Загруprf больших файлов в blob eldalex SQL, базы данных 4 12.10.2010 16:10