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

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

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 17, средняя оценка - 5.00
Pchel
1 / 1 / 0
Регистрация: 04.11.2012
Сообщений: 26
#1

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

19.11.2014, 12:40. Просмотров 3076. Ответов 8
Метки нет (Все метки)

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

Std::ofstream запись и чтение переменных в бинарный файл - C++
int a = 1; std::ofstream file(&quot;test.settings&quot;, std::ios::in | std::ios::out | std::ios::binary); ...

Error: ambiguous overload for 'operator<<' (operand types are 'std::ofstream {aka std::basic_ofstream<char>}' - C++
на #define LOG(Variable) Log&lt;&lt;&quot;&lt;&quot;;...

Стандартный поток и STL (std::copy to std::cout) - C++
#include &lt;iostream&gt; #include &lt;sstream&gt; #include &lt;algorithm&gt; #include &lt;functional&gt; #include &lt;string&gt; using namespace std; ...

Нужно создать базу данных (создать пустой бинарный файл). Через поток. Поток бинарного файла описать в виде локальной переменной внутри функции. - C++
Совсем не понял эту тему. Нужно создать базу данных (создать пустой бинарный файл). Через поток. Поток бинарного файла описать в виде...

Чтение бинарного файла ifstream - C++
есть бинарный файл 10101010101111010101011011001101001010100010 нужно прочить его в массив как числа, как? спасибо

Не воспринимает ни std::cout, ни std::cin. Вобщем ничего из std. Также не понимает iostream - C++
Здравствуйте! Я хотел начать изучать язык C++. Набрал литературы. Установил Microsoft Visual C++ 2005 Express Edition. Образ диска...

8
Ilot
Модератор
Эксперт С++
1823 / 1181 / 232
Регистрация: 16.05.2013
Сообщений: 3,118
Записей в блоге: 5
Завершенные тесты: 1
19.11.2014, 12:45 #2
C++
1
       is.seekg(offset, std::ios::beg);
Нафига? И уверены ли вы что файл имеет допустимый для этого размер?
0
Pchel
1 / 1 / 0
Регистрация: 04.11.2012
Сообщений: 26
19.11.2014, 13:16  [ТС] #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/istream/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 работает не корректно. Как можно подправить?
0
Max Dark
шКодер самоучка
1849 / 1649 / 603
Регистрация: 09.10.2013
Сообщений: 3,678
Записей в блоге: 6
Завершенные тесты: 2
19.11.2014, 13:23 #4
Вы забываете, что строки в С/С++ не могут содержать символов с кодом 0, т.к. он является признаком конца строки
Строки сами по себе не предназначены для хранения бинарных данных
0
Pchel
1 / 1 / 0
Регистрация: 04.11.2012
Сообщений: 26
19.11.2014, 13:35  [ТС] #5
А что тогда предназначено? (кроме потока) И если строки не предназначены, то почему в документации (ссылка выше)именно такой пример?(отчетливо указан флаг binary)
Как много информации можно хранить в объекте типа ifstream?(512 КБ это уже слишком много для него?)

Добавлено через 5 минут
Соглашусь с вашими суждениями касательно строки типа char*, но не std::string. Там другая ситуация, они могут содержать символы с кодом 0
0
Ilot
Модератор
Эксперт С++
1823 / 1181 / 232
Регистрация: 16.05.2013
Сообщений: 3,118
Записей в блоге: 5
Завершенные тесты: 1
19.11.2014, 13:43 #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;
}
0
Pchel
1 / 1 / 0
Регистрация: 04.11.2012
Сообщений: 26
19.11.2014, 13:55  [ТС] #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;
}
0
Max Dark
шКодер самоучка
1849 / 1649 / 603
Регистрация: 09.10.2013
Сообщений: 3,678
Записей в блоге: 6
Завершенные тесты: 2
19.11.2014, 14:07 #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;
}
0
Pchel
1 / 1 / 0
Регистрация: 04.11.2012
Сообщений: 26
19.11.2014, 14:18  [ТС] #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(); // закрываем файл
    
}
0
19.11.2014, 14:18
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
19.11.2014, 14:18
Привет! Вот еще темы с ответами:

Error C2678: бинарный "<<": не найден оператор, принимающий левый операнд типа "std::ifstream" - C++
Собственно, текст ошибки приведен в названии темы. Сам код: #include &quot;stdafx.h&quot; #include &lt;conio.h&gt; #include &lt;iomanip&gt; #include...

Std:string в бинарный файл и обратно - C++
Извините! Тупонул. Уже сам всё сделал. Не знаю как только тему удалить теперь.

ошибка error: cannot convert 'std::string {aka std::basic_string<char>}' to 'std::string* {aka std::basic_stri - C++
на вод поступают 2 строки типа string. определить количество вхождений строки 2 в строку 1 ошибка error: cannot convert 'std::string {aka...

STL std::set, std::pair, std::make_pair - C++
Я не знаю как описать тему в двух словах, поэтому не обращайте внимание на название темы. Собственно перейдем к нашим баранам: есть...


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

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

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