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

Чтение бинарного файла в поток std::ifstream и вывод в другой бинарный файл std::ofstream (создание копии) - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 17, средняя оценка - 5.00
Pchel
1 / 1 / 0
Регистрация: 04.11.2012
Сообщений: 26
19.11.2014, 12:40     Чтение бинарного файла в поток std::ifstream и вывод в другой бинарный файл std::ofstream (создание копии) #1
Проверил работу программы на маленькой картинке(744 байт). Все работает. С несколько бОльшими файлами(512КБ) нет.
Суть задачи в том, чтобы считать бинарный файл(например *.exe) в поток, сохранить эту информацию в объект-строку типа std::string и оттуда вывести информацию в новый бинарный файл(фактичекски копию).
P.S. Эта строка будет передаваться в составе HTTP ответа на запрос в качестве контента.(но это не важно)
Наблюдения:На тестах стало понятно что при работе с большими файлами программа не заходит в цикл while. Но при этом if (!is) не срабатывает(значит что то там все-таки есть)
Мысли: Возможно не хватает места в объекте is типа ifstream. Хотя переменной offset я присвоил большое значение. Возможно также, можно считывать бинарный файл порциями(насколько это возможно большими) и выводить его также порционно.
Внимание вопрос знатокам: Что делать?(чтобы побороть задачу выделенную красным)
Советы, мысли, код - всему скажу Спасибо!
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
#include <string>
#include <fstream>
#include <iostream>
#include <ostream>
#include <bitset>
#include <conio.h>
 
int main()
{
 
        std::string full_path = "C:\\x.jpg";
        long long int offset = 1024 * 1024 * 1024 + 10;
        std::ifstream is;
        is.open(full_path.c_str(), std::ios::in | std::ios::binary);//ios::binary - бинарное открытие,ios::in - операции ввода
        is.seekg(offset, std::ios::beg);
        if (!is)
        {
            std::cout << "Файл не найден";
            return 0;
        }
        char buf[512];
        std::string content;
        while (is.read(buf, sizeof(buf)).gcount() > 0)//если количество символов, прочтенных при последней операции неформатированного ввода >0
        {
            content.append(buf, is.gcount());// то добавляем в строку это кол-во символов.
 
        }
        std::ofstream fout("copy_x.jpg", std::ofstream::binary);// создаём объект класса ofstream для записи и связываем его с файлом 
 
        fout << content;
        fout.close(); // закрываем файл
    
}
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
19.11.2014, 12:40     Чтение бинарного файла в поток std::ifstream и вывод в другой бинарный файл std::ofstream (создание копии)
Посмотрите здесь:

C++ Не воспринимает ни std::cout, ни std::cin. Вобщем ничего из std. Также не понимает iostream
C++ чтение бинарного файла ifstream
Нужно создать базу данных (создать пустой бинарный файл). Через поток. Поток бинарного файла описать в виде локальной переменной внутри функции. C++
C++ Стандартный поток и STL (std::copy to std::cout)
Error C2678: бинарный "<<": не найден оператор, принимающий левый операнд типа "std::ifstream" C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Ilot
Модератор
Эксперт С++
1765 / 1140 / 221
Регистрация: 16.05.2013
Сообщений: 3,017
Записей в блоге: 5
Завершенные тесты: 1
19.11.2014, 12:45     Чтение бинарного файла в поток std::ifstream и вывод в другой бинарный файл std::ofstream (создание копии) #2
C++
1
       is.seekg(offset, std::ios::beg);
Нафига? И уверены ли вы что файл имеет допустимый для этого размер?
Pchel
1 / 1 / 0
Регистрация: 04.11.2012
Сообщений: 26
19.11.2014, 13:16  [ТС]     Чтение бинарного файла в поток std::ifstream и вывод в другой бинарный файл std::ofstream (создание копии) #3
Хорошо, заменим:
C++
1
2
3
 std::ifstream is;
        is.open(full_path.c_str(), std::ios::in | std::ios::binary);//ios::binary - бинарное открытие,ios::in - операции ввода
        is.seekg(offset, std::ios::beg);
На:
C++
1
std::ifstream is(full_path.c_str(), std::ios::in | std::ios::binary);
По факту ведь ничего не изменится...

Добавлено через 8 минут
Попробую сейчас сделать правки на основе документации:
http://www.cplusplus.com/reference/i...istream/seekg/
Прошу не расходиться из темы!Я быстро!

Добавлено через 18 минут
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
int main()
{
 
    std::string full_path = "C:\\x.jpg";
    std::ifstream is;
    is.open(full_path.c_str(), std::ios::in | std::ios::binary);//ios::binary - бинарное открытие,ios::in - операции ввода
    
    is.seekg(0, is.end);
    long long int length = is.tellg();
    is.seekg(0, is.beg);
    
    std::cout << length;
    
    if (!is)
    {
        std::cout << "Файл не найден";
        return 1;
    }
    std::string content;
    content.resize(length);
    char * buffer = new char[length];
    is.read(buffer, length);
    content = buffer;
    std::cout << "*****" << content << "*****" <<content.size() << "*****";
    std::ofstream fout("copy_x.jpg", std::ofstream::binary);// создаём объект класса ofstream для записи и связываем его с файлом 
 
    fout << content;
    fout.close(); // закрываем файл
    _getch();
    return 0;
}
На консоли:
length=745;//это маленькая картинка весит 745 байт, при большой картинке программа просто завершается мгновенно
buffer="какие то 4 символа байта"
content="те же 4 символа байта"
content.size()=4
Такие дела. Получается что большой файл в поток полностью не зачитывается. Маленький зачитывается, но функция read работает не корректно. Как можно подправить?
Max Dark
В поиске работы
 Аватар для Max Dark
1546 / 1399 / 501
Регистрация: 09.10.2013
Сообщений: 3,185
Записей в блоге: 8
Завершенные тесты: 2
19.11.2014, 13:23     Чтение бинарного файла в поток std::ifstream и вывод в другой бинарный файл std::ofstream (создание копии) #4
Вы забываете, что строки в С/С++ не могут содержать символов с кодом 0, т.к. он является признаком конца строки
Строки сами по себе не предназначены для хранения бинарных данных
Pchel
1 / 1 / 0
Регистрация: 04.11.2012
Сообщений: 26
19.11.2014, 13:35  [ТС]     Чтение бинарного файла в поток std::ifstream и вывод в другой бинарный файл std::ofstream (создание копии) #5
А что тогда предназначено? (кроме потока) И если строки не предназначены, то почему в документации (ссылка выше)именно такой пример?(отчетливо указан флаг binary)
Как много информации можно хранить в объекте типа ifstream?(512 КБ это уже слишком много для него?)

Добавлено через 5 минут
Соглашусь с вашими суждениями касательно строки типа char*, но не std::string. Там другая ситуация, они могут содержать символы с кодом 0
Ilot
Модератор
Эксперт С++
1765 / 1140 / 221
Регистрация: 16.05.2013
Сообщений: 3,017
Записей в блоге: 5
Завершенные тесты: 1
19.11.2014, 13:43     Чтение бинарного файла в поток std::ifstream и вывод в другой бинарный файл std::ofstream (создание копии) #6
Цитата Сообщение от Pchel Посмотреть сообщение
Как много информации можно хранить в объекте типа ifstream?(512 КБ это уже слишком много для него?)
Узнайте сами:
C++
1
2
3
4
5
6
7
#include <limits>
#include <iostream>
#include <fstream>
int main() {
    std::cout << std::numeric_limits<std::filebuf::off_type>::max() << std::endl;
    return 0;
}
Pchel
1 / 1 / 0
Регистрация: 04.11.2012
Сообщений: 26
19.11.2014, 13:55  [ТС]     Чтение бинарного файла в поток std::ifstream и вывод в другой бинарный файл std::ofstream (создание копии) #7
Это и ежу понятно!

Добавлено через 7 минут
Сейчас все работает хорошо!!! Но
C++
1
fout.write(content.c_str(), content.size());
Не пишет файл почему-то. Не создается файл с таким именем в нужной директории(в папке Debug).
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
int main()
{
std::ofstream fout("copy_test.exe", std::ofstream::binary);// создаём объект класса ofstream для записи и связываем его с файлом 
 
    std::string full_path = "C:\\test.exe";
    std::ifstream is;
    is.open(full_path.c_str(), std::ios::in | std::ios::binary);//ios::binary - бинарное открытие,ios::in - операции ввода
 
    is.seekg(0, is.end);
    long long int length = is.tellg();
    is.seekg(0, is.beg);
 
    std::cout << length;
 
    if (!is)
    {
        std::cout << "Файл не найден";
        return 1;
    }
    char buf[512];
    std::string content;
    while (is.read(buf, sizeof(buf)).gcount() > 0)//если количество символов, прочтенных при последней операции неформатированного ввода >0
    {
        content.append(buf, is.gcount());// то добавляем в строку это кол-во символов.
        std::cout << '*';
 
    }
    std::cout<<content.size();
    fout.write(content.c_str(), content.size());
    fout.close();
    std::cout << '*';
// закрываем файл
    _getch();
    return 0;
}
Max Dark
В поиске работы
 Аватар для Max Dark
1546 / 1399 / 501
Регистрация: 09.10.2013
Сообщений: 3,185
Записей в блоге: 8
Завершенные тесты: 2
19.11.2014, 14:07     Чтение бинарного файла в поток std::ifstream и вывод в другой бинарный файл std::ofstream (создание копии) #8
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
#include <iostream>
#include <fstream>
#include <string>
#include <cstdint>
 
using ibyte_stream = std::basic_ifstream < uint8_t >;
using obyte_stream = std::basic_ofstream < uint8_t >;
using  byte_stream = std::basic_fstream  < uint8_t >;
 
void copy_me(const std::string& in, const std::string& out, std::streamsize bsize = 4 * 1024) {
    std::streamsize count;
    uint8_t* buffer;
    ibyte_stream fin;
    obyte_stream fout;
    fin.open(in, std::ios::binary | std::ios::in);
    if (!fin) return;
    fout.open(out, std::ios::binary | std::ios::out);
    if (!fout) return;
 
    buffer = new uint8_t[bsize];
    do {
        count = fin.readsome(buffer, bsize);
        fout.write(buffer, count);
    } while (bsize == count);
    delete[] buffer;
}
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
19.11.2014, 14:18     Чтение бинарного файла в поток std::ifstream и вывод в другой бинарный файл std::ofstream (создание копии)
Еще ссылки по теме:

Std:string в бинарный файл и обратно C++
Error: ambiguous overload for 'operator<<' (operand types are 'std::ofstream {aka std::basic_ofstream<char>}' C++
Std::ofstream запись и чтение переменных в бинарный файл C++

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

Или воспользуйтесь поиском по форуму:
Pchel
1 / 1 / 0
Регистрация: 04.11.2012
Сообщений: 26
19.11.2014, 14:18  [ТС]     Чтение бинарного файла в поток std::ifstream и вывод в другой бинарный файл std::ofstream (создание копии) #9
Cra3y , спасибо за поддержку и помощь!!!
Правильное решение, которое возможно, пригодится форумчанам:

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
#include <string>
#include <fstream>
#include <iostream>
#include <ostream>
#include <bitset>
#include <conio.h>
 
int main()
{
 
        std::string full_path = "C:\\test.exe";
        
        std::ifstream is;
        is.open(full_path.c_str(), std::ios::in | std::ios::binary);//ios::binary - бинарное открытие,ios::in - операции ввода
        if (!is)
        {
            std::cout << "Файл не найден";
            return 0;
        }
        char buf[512];
        std::string content;
        while (is.read(buf, sizeof(buf)).gcount() > 0)//если количество символов, прочтенных при последней операции неформатированного ввода >0
        {
            content.append(buf, is.gcount());// то добавляем в строку это кол-во символов.
            std::cout << '*';
        }
        std::ofstream fout("copy_test.exe", std::ofstream::binary);// создаём объект класса ofstream для записи и связываем его с файлом 
 
        fout << content;
        fout.close(); // закрываем файл
    
}
Yandex
Объявления
19.11.2014, 14:18     Чтение бинарного файла в поток std::ifstream и вывод в другой бинарный файл std::ofstream (создание копии)
Ответ Создать тему
Опции темы

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