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

Скопировать бинарный файл - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 9, средняя оценка - 4.67
Union
 Аватар для Union
17 / 17 / 2
Регистрация: 16.08.2010
Сообщений: 252
18.09.2010, 19:55     Скопировать бинарный файл #1
Нужно скопировать бинарный файл. Копировать нужно блоками по 256 байт.
Запись работает отлично, а вот не могу считать никак

Вот мои наработки:
C++
1
2
3
4
5
6
7
8
9
10
11
12
fp=fopen("test.zip", "r"); // Бинарный файл, который необходимо скопировать
std::ofstream ofs;
ofs.open("kopia_test.zip", std::ios::binary); // Копия
char buf[257] = {0}; // Буфер
int i=0;
while(i<size){ // size - размер файла в байтах
    fgets( buf, 1 , fp ); // Считываем блок из 1 байт и записываем в буфер
    i++;
    ofs.write(buf, 1); // Записываем блок из 1 байт из буфера в файл-копию
}
ofs.close();
fclose(fp);
Пример нерабочий. Судя по всему проблема заключается в функции fgets, которая обрабатывает также перенос строки и соответственно перестаёт считывать как встречается любой перенос. Пробовал другие функции (fread, gets, read) что-то не получилось вообще.
И копирование происходит по одному байту, а нужно по 256 байт.

Помогите переписать чтоб работало
Спасибо
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
fasked
Эксперт C++
 Аватар для fasked
4924 / 2504 / 180
Регистрация: 07.10.2009
Сообщений: 4,306
Записей в блоге: 1
18.09.2010, 20:16     Скопировать бинарный файл #2
на Си:
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
#include <stdio.h>
#include <stdlib.h>
 
#define BLOCK_SIZE 256
 
int main(int argc, char **argv)
{
    size_t i = 0;
 
    unsigned char buffer[BLOCK_SIZE];
 
    char *file_name_in = argv[1];
    char *file_name_out = argv[2];
    
    FILE *fin = NULL;
    FILE *fout = NULL;
    
    size_t file_size = 0;
    
    printf("copy %s to %s\n", file_name_in, file_name_out);
    
    if((fin = fopen(file_name_in, "rb")) == NULL) {
        fprintf(stderr, "can't open file for read\n");
        return EXIT_FAILURE;
    }
    
    if((fout = fopen(file_name_out, "wb")) == NULL) {
        fprintf(stderr, "can't open file for write\n");
        return EXIT_FAILURE;
    }
    
    fseek(fin, 0, SEEK_END);
    file_size = ftell(fin);
    rewind(fin);
    
    for(i = 0; i < file_size / BLOCK_SIZE; ++i) {
        if(fread(buffer, sizeof(unsigned char), BLOCK_SIZE, fin) != BLOCK_SIZE) {
            fprintf(stderr, "reading error\n");
            return EXIT_FAILURE;
        }
        if(fwrite(buffer, sizeof(unsigned char), BLOCK_SIZE, fout) != BLOCK_SIZE) {
            fprintf(stderr, "writing error\n");
            return EXIT_FAILURE;
        }
    }
    
    if((file_size %= BLOCK_SIZE)) {
        if(fread(buffer, sizeof(unsigned char), file_size, fin) != file_size) {
            fprintf(stderr, "reading error\n");
            return EXIT_FAILURE;
        }
        if(fwrite(buffer, sizeof(unsigned char), file_size, fout) != file_size) {
            fprintf(stderr, "writing error\n");
            return EXIT_FAILURE;
        }
    }
    
    fclose(fin);
    fclose(fout);
    
    printf("done\n");
    return EXIT_SUCCESS;
}
Union
 Аватар для Union
17 / 17 / 2
Регистрация: 16.08.2010
Сообщений: 252
18.09.2010, 20:25  [ТС]     Скопировать бинарный файл #3
Спасибо. Если не затруднит, прокомментируйте пожалуйста строки: 32,33,34 и что происходит в блоках, начинающихся в строках 36, 47

Я правильно понял что блок со строки 47 записывает остаток меньше в данном случае 256 байт?
fasked
Эксперт C++
 Аватар для fasked
4924 / 2504 / 180
Регистрация: 07.10.2009
Сообщений: 4,306
Записей в блоге: 1
18.09.2010, 20:42     Скопировать бинарный файл #4
Цитата Сообщение от Union Посмотреть сообщение
Спасибо. Если не затруднит, прокомментируйте пожалуйста строки: 32,33,34 и что происходит в блоках, начинающихся в строках 36, 47
Я правильно понял что блок со строки 47 записывает остаток меньше в данном случае 256 байт?
32, 33, 34 - получение размера файла.
- каретка устанавливается в конец файла
- сохраняется позиция каретки (то есть фактически и есть размер файла в байтах)
- каретка переносится снова в начало файла

да. начиная с 47 строки копируются оставшиеся байты.
easybudda
Модератор
Эксперт С++
 Аватар для easybudda
9373 / 5423 / 914
Регистрация: 25.07.2009
Сообщений: 10,423
19.09.2010, 04:47     Скопировать бинарный файл #5
fasked, "... Или, если хочешь, скажу проще." (с)
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
#include <stdio.h>
#include <stdlib.h>
 
#define BLOCK_SIZE 256
 
int main(int argc, char ** argv){
    FILE * fin, * fout;
    char buf[BLOCK_SIZE];
    ssize_t ret;
    
    if ( argc < 3 ){
        fprintf(stderr, "Usage: %s <in_file> <out_file>\n", argv[0]);
        exit(1);
    }
    
    if ( ( fin = fopen(argv[1], "rb") ) == NULL ){
        fprintf(stderr, "%s: can't open file %s for input!\n", argv[0], argv[1]);
        exit(1);
    }
    
    if ( ( fout = fopen(argv[2], "wb") ) == NULL ){
        fprintf(stderr, "%s: can't open file %s for output!\n", argv[0], argv[2]);
        fclose(fin);
        exit(1);
    }
    
    while ( ( ret = fread(buf, 1, BLOCK_SIZE, fin) ) > 0 ){
        if ( fwrite(buf, 1, ret, fout) < 0 ){
            fprintf(stderr, "%s: can't write to file %s\n", argv[0], argv[2]);
            fclose(fin);
            fclose(fout);
            exit(1);
        }
    }
    if ferror(fin){
        fprintf(stderr, "%s: can't read from file %s\n", argv[0], argv[1]);
        fclose(fin);
        fclose(fout);
        exit(1);
    }
    
    fclose(fout);
    fclose(fin);
    
    exit(0);
}
fasked
Эксперт C++
 Аватар для fasked
4924 / 2504 / 180
Регистрация: 07.10.2009
Сообщений: 4,306
Записей в блоге: 1
19.09.2010, 15:05     Скопировать бинарный файл #6
easybudda, я как-то не очень люблю вот разбрасывать ни о чем не говорящие argv по коду
А вот то, что fread возвращает количество байт не подумал, спасибо.
И что это за тип такой ssize_t, вроде раньше не встречал?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
19.09.2010, 16:13     Скопировать бинарный файл
Еще ссылки по теме:

C++ Скопировать текстовый файл в новый файл, заменив в каждой строке слова «ok» на «*»
Бинарный файл C++
C++ Бинарный файл

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

Или воспользуйтесь поиском по форуму:
easybudda
Модератор
Эксперт С++
 Аватар для easybudda
9373 / 5423 / 914
Регистрация: 25.07.2009
Сообщений: 10,423
19.09.2010, 16:13     Скопировать бинарный файл #7
Цитата Сообщение от fasked Посмотреть сообщение
И что это за тип такой ssize_t
signed size_t. В cygwin-овском gcc объявлен вот так:
/usr/include/sys/_types.h
C
1
2
3
4
5
6
7
#ifndef __ssize_t_defined
#if defined(__INT_MAX__) && __INT_MAX__ == 2147483647
typedef int _ssize_t;
#else
typedef long _ssize_t;
#endif
#endif
/usr/include/sys/types.h
C
1
typedef _ssize_t ssize_t;
На самом деле fread()/fwrite() значение типа size_t возвращают, это я по привычке от read()/write() написал, но есть и такой тип, и ошибок с ним никаких не возникнет - у нас же буфер 256 байт.

Добавлено через 11 минут
Цитата Сообщение от fasked Посмотреть сообщение
я как-то не очень люблю вот разбрасывать ни о чем не говорящие argv по коду
Так их всего три... Но если сильно смущает, можно вот так например сделать
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
 
#define PROGRAM_NAME argv[0]
#define INPUT_FILE argv[1]
#define OUTPUT_FILE argv[2]
 
int main(int argc, char ** argv){
    if ( argc < 3 ){
        printf("Usage: %s <input_file> <output_file>\n", PROGRAM_NAME);
        return 1;
    }
    
    printf("For input file used %s\n", INPUT_FILE);
    printf("For output file used %s\n", OUTPUT_FILE);
    
    return 0;
}
Yandex
Объявления
19.09.2010, 16:13     Скопировать бинарный файл
Ответ Создать тему
Опции темы

Текущее время: 20:25. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru