Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Ошибка в делении файла 
:(
    Опции темы
segmentation_fault
Дата 26.10.2005, 22:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 82
Регистрация: 14.2.2005
Где: в интернете

Репутация: 1
Всего: 1



Недавно написал небольшой код который должен разделить бинарный файл на два файла и потом 'склеить' его обратно. Попробовал на экзешнике - программа работает, файл делит и склеивает, но экзешник потом не работает. Не подскажете, где я тут ошибся?
Вот код который делит:
Код


#include <cstdlib>
#include <stdio.h>
#include <string>
#include <iostream>

main() {
    using namespace std;

    cout<<"print the name of the file"<<"\n";
    string filename;
    cin>>filename;
    int bytes;
    cout<<"print the byte number"<<"\n";
    cin>>bytes;

    FILE* input;
    input = fopen(filename.c_str(), "rb");
    FILE* output1;
    FILE* output2;
    output1 = fopen("out1", "wb");
    output2 = fopen("out2", "wb");
    int ch;
    long int mid_file = fseek(input, 0, SEEK_SET) + bytes;
    do {  
        ch = getc(input);
        putc(ch, output1);

    }
    while(ftell(input) < mid_file);
            fclose(output1);
            fseek(input, ftell(input), SEEK_SET);
    do {  
        ch = getc(input);
        putc(ch, output2);

    }
    while(ch != EOF);

    cout<<"file split successfully!!"<<"\n";
    fclose(input);
    fclose(output2);

}


А вот который обратно соединяет:
Код

#include <cstdlib>
#include <stdio.h>
#include <string>
#include <iostream>

main() {
    using namespace std;

    cout<<"print the name of the output file"<<"\n";
    string filename;
    cin>>filename;

    FILE* output;
    output = fopen(filename.c_str(), "wb");
    FILE* input1;
    FILE* input2;
    input1 = fopen("out1", "rb");
    input2 = fopen("out2", "rb");
    int ch;
    do {  
        ch = getc(input1);
        putc(ch, output);

    }
    while(ch != EOF);
    fclose(input1);

    do {  
        ch = getc(input2);
        putc(ch, output);

    }
    while(ch != EOF);

    cout<<"file merged successfully!!"<<"\n";
    fclose(input2);
    fclose(output);

}


PM MAIL   Вверх
BreakPointMAN
Дата 26.10.2005, 23:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 725
Регистрация: 15.9.2004
Где: Saratov

Репутация: 14
Всего: 24



И в первой, и во второй программе одна и та же ошибка: ты, сразу после считывания байта из входного файла, начинаешь им манипулировать, записывая его в выходной... в то время как это может быть уже не очередной считанный байт, а значение EOF, с которым делать ничего не надо... исправить это "в лоб" можно, например, так:
Код

    do {  
        ch = getc(input);
        if(ch!=EOF)
           putc(ch, output2);

    }
    while(ch != EOF);


а, вообще, реализация довольно кривенькая... smile


--------------------
"Разруха не в клозетах, а в головах." © Ф.Ф. Преображенский (М.Булгаков, "Собачье сердце")
PM WWW ICQ   Вверх
cardinal
Дата 26.10.2005, 23:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Инженер
****


Профиль
Группа: Экс. модератор
Сообщений: 6003
Регистрация: 26.3.2002
Где: Германия

Репутация: 2
Всего: 99



А ты посмотри на два файла, которые у тебя после деления получились в Norton Commander'e и если они в сумме их размеров не дают размер исходного файла, то ты уже поделил неправильно.
Если сумма правильная, то смотри на размер того, что получилось в итоге. Опять же если в итоге размер файла не тот, то ошибка в склеивании.
Если размеры правильные, то значит ты разделил/слепил с определенными значениями, но при этом записал всякую ерунду в файлы.
А вообще для того, чтобы побайтно сравнить два файла есть (в том же Norton'e Commander'e) комманда fc.
Пишешь
fc /b 1файл 2файл > 3файл
В 3файл получаешь результат побайтового сравнения. Если в файле будет написано, что различия не найдены, то все разделилось/слепилось правильно.

Действуй! smile
Добавлено @ 23:50
Немного опоздал с советом, но ничего...


--------------------
Немецкая оппозиция потребовала упростить натурализацию иммигрантов
В моем блоге: Разные истории из жизни в Германии

"Познание бесконечности требует бесконечного времени, а потому работай не работай - все едино".  А. и Б. Стругацкие
PM   Вверх
segmentation_fault
Дата 27.10.2005, 00:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 82
Регистрация: 14.2.2005
Где: в интернете

Репутация: 1
Всего: 1



BreakPointMAN, тут ты конечно прав, но программа всё равно не работает, проблема в чем-то еще.
Цитата(BreakPointMAN @ 26.10.2005, 23:25)
а, вообще, реализация довольно кривенькая... 

Буду рад услышать любую конструктивную критику.
cardinal
Спасибо, но Нортон Коммандером не пользуюсь. Просто просматривая свойства файлов получается что склеенный файл на два байта больше чем он должен быть. Откуда они берутся, непонятно smile
PM MAIL   Вверх
LPBOY
Дата 27.10.2005, 00:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 228
Регистрация: 12.7.2005

Репутация: 20
Всего: 20



BreakPointMAN прав!
Попробуй так.
Код

#include <cstdlib>
#include <stdio.h>
#include <string>
#include <iostream>
main() {
    using namespace std;
    cout<<"print the name of the file"<<"\n";
    string filename;
    cin>>filename;
    int bytes;
    cout<<"print the byte number"<<"\n";
    cin>>bytes;
    FILE* input;
    input = fopen(filename.c_str(), "rb");
    FILE* output1;
    FILE* output2;
    output1 = fopen("out1", "wb");
    output2 = fopen("out2", "wb");
    int ch;
    long int mid_file = fseek(input, 0, SEEK_SET) + bytes;
    do {  
        ch = getc(input);
        putc(ch, output1);
    }
    while(ftell(input) < mid_file);
            fclose(output1);
            fseek(input, ftell(input), SEEK_SET);
    ch = !EOF;
    while((ch = getc(input)) != EOF)
    {  
        putc(ch, output2);
    }
    cout<<"file split successfully!!"<<"\n";
    fclose(input);
    fclose(output2);
}


Код

#include <cstdlib>
#include <stdio.h>
#include <string>
#include <iostream>
main() {
    using namespace std;
    cout<<"print the name of the output file"<<"\n";
    string filename;
    cin>>filename;
    FILE* output;
    output = fopen(filename.c_str(), "wb");
    FILE* input1;
    FILE* input2;
    input1 = fopen("out1", "rb");
    input2 = fopen("out2", "rb");
    int ch = 0;
    while((ch = getc(input1)) != EOF)
    {  
        putc(ch, output);
    }
    
    fclose(input1);
    while((ch = getc(input2)) != EOF)
    {  
        putc(ch, output);
    }
    cout<<"file merged successfully!!"<<"\n";
    fclose(input2);
    fclose(output);
}

--------------------
Каждый человек по-своему прав, а по-моему нет...
PM MAIL   Вверх
BreakPointMAN
Дата 27.10.2005, 00:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 725
Регистрация: 15.9.2004
Где: Saratov

Репутация: 14
Всего: 24



Цитата(segmentation_fault @ 27.10.2005, 00:06)
Откуда они берутся, непонятно

оттуда и берутся!.. ты же в них еще два раза значение EOF пишешь!..
Добавлено @ 00:23
Цитата(segmentation_fault @ 27.10.2005, 00:06)
BreakPointMAN, тут ты конечно прав, но программа всё равно не работает, проблема в чем-то еще.

ты все ошибки исправил? у тебя 1 ошибка в 3-х экземплярах, в обоих файлах!..
ну, а если всё равно не работает - потести под отладчиком... уверен, сразу наткнешься на ошибку, если есть такая...


--------------------
"Разруха не в клозетах, а в головах." © Ф.Ф. Преображенский (М.Булгаков, "Собачье сердце")
PM WWW ICQ   Вверх
cardinal
Дата 27.10.2005, 00:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Инженер
****


Профиль
Группа: Экс. модератор
Сообщений: 6003
Регистрация: 26.3.2002
Где: Германия

Репутация: 2
Всего: 99



Цитата(segmentation_fault @ 26.10.2005, 22:06)
Спасибо, но Нортон Коммандером не пользуюсь.

Я тоже им обычно не пользуюсь, но иногда его очень полезно иметь. Попробуй описанным выше методом найти ошибки, а потом их исправить. Заодно поймешь в какой момент лишние байты появляются...


--------------------
Немецкая оппозиция потребовала упростить натурализацию иммигрантов
В моем блоге: Разные истории из жизни в Германии

"Познание бесконечности требует бесконечного времени, а потому работай не работай - все едино".  А. и Б. Стругацкие
PM   Вверх
BreakPointMAN
Дата 27.10.2005, 01:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 725
Регистрация: 15.9.2004
Где: Saratov

Репутация: 14
Всего: 24



а, собственно, причем здесь Norton Commander?
fc - это вроде как стандартная программа в Windows... smile Хоть из-под FAR'а ее запускай, хоть из чистой консоли command.com/cmd.exe...


--------------------
"Разруха не в клозетах, а в головах." © Ф.Ф. Преображенский (М.Булгаков, "Собачье сердце")
PM WWW ICQ   Вверх
segmentation_fault
Дата 27.10.2005, 01:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 82
Регистрация: 14.2.2005
Где: в интернете

Репутация: 1
Всего: 1



Могу подтвердить, что FC работает и в обычном ДОС-окошке. Что касается программы, то вроде уже во все циклы вставил проверку на ЕOF, то же результат. Да бог с ним, завтра прогоню программу под отладчиком, будет ясно. Спасибо всем кто ответил.
PM MAIL   Вверх
Chaos A.D.
Дата 27.10.2005, 12:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 172
Регистрация: 16.1.2005
Где: 09 RUS

Репутация: 6
Всего: 7



Вот очень лаконичный и наглядный способ решения твоей задачи (привел только кусок кода, надеюсь все и так станет ясно) :

Код

if ( action == Merge )  // Если параметры проги заданы так, что мы сливаем два куска файла...
{
    std::ostream_iterator<char> i(*file1);  // Создаем итератор вывода, и ассоциируем его с выходным файлом file1.

    // Копируем содержимое первого куска. Используем алгоритм copy, и два итератора ввода с буферизацией.
    // Для справки - первый аргумент вызова создает итератор, который считывает и буферизирует данные из файла. 
    // Второй - это итератор, созданный конструктором без аргументов. Означает конец входной последовательности.
    std::copy( std::istreambuf_iterator<char>(*file2), std::istreambuf_iterator<char>(), i ); 

    // То же самое - итератор читает файл file3, и пишет его в файл file1.
    std::copy( std::istreambuf_iterator<char>(*file3), std::istreambuf_iterator<char>(), i );

}
else  // action == Split - разбиваем на куски :
{
    // Читаем весь файл в вектор (плохо, если файлы огромные, но я не видел exe-шника больше 10 метров(MS Office).)
    std::vector<char> input_file;

    // Резервируем место, чтобы память не Realloc-алась много раз. 
    // Можно узнавать размер exe-шника, и realloc-ать сразу под весь файл. Но код бы зависел от платформы.
    input_file.reserve(1024*1024);  

    // Читаем весь входной файл в массив. Обходимся без цикла с помощью интервальной функции assign и итераторов.
    input_file.assign( std::istreambuf_iterator<char>(*file1), std::istreambuf_iterator<char>() );

    // Копируем с помощью итераторов половину файла в первый кусок, вторую половину во второй.
    std::copy( input_file.begin(), input_file.begin() + input_file.size() / 2, std::ostream_iterator<char>(*file2, "") );
    std::copy( input_file.begin() + input_file.size() / 2, input_file.end(), std::ostream_iterator<char>(*file3) );
}


Правда наглядный он только для тех, кто хорошо знает STL. Но зато очень коротко. И никаких циклов.

Это сообщение отредактировал(а) Chaos A.D. - 27.10.2005, 13:12
--------------------
Надо смеяться над тем, что тебя мучит, иначе не сохранишь равновесия, иначе мир сведет тебя с ума...Ken Kesey - One Flew Over The Cocoo's Nest
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0591 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.