119

I'm trying to write code to read a binary file into a buffer, then write the buffer to another file. I have the following code, but the buffer only stores a couple of ASCII characters from the first line in the file and nothing else.

int length;
char * buffer;

ifstream is;
is.open ("C:\\Final.gif", ios::binary );
// get length of file:
is.seekg (0, ios::end);
length = is.tellg();
is.seekg (0, ios::beg);
// allocate memory:
buffer = new char [length];
// read data as a block:
is.read (buffer,length);
is.close();

FILE *pFile;
pFile = fopen ("C:\\myfile.gif", "w");
fwrite (buffer , 1 , sizeof(buffer) , pFile );
gsamaras
  • 66,800
  • 33
  • 152
  • 256
nf313743
  • 3,409
  • 8
  • 41
  • 61

8 Answers8

190

If you want to do this the C++ way, do it like this:

#include <fstream>
#include <iterator>
#include <algorithm>

int main()
{
    std::ifstream input( "C:\\Final.gif", std::ios::binary );
    std::ofstream output( "C:\\myfile.gif", std::ios::binary );

    std::copy( 
        std::istreambuf_iterator<char>(input), 
        std::istreambuf_iterator<char>( ),
        std::ostreambuf_iterator<char>(output));
}

If you need that data in a buffer to modify it or something, do this:

#include <fstream>
#include <iterator>
#include <vector>

int main()
{
    std::ifstream input( "C:\\Final.gif", std::ios::binary );

    // copies all data into buffer
    std::vector<unsigned char> buffer(std::istreambuf_iterator<char>(input), {});

}
Björn Pollex
  • 70,106
  • 28
  • 177
  • 265
  • 4
    What if I want copy only some segment of data to buffer. How I can do it? Let say 1024 bytes. – likern Jul 10 '14 at 15:45
  • 8
    @Mikhail [Here](http://insanecoding.blogspot.it/2011/11/how-to-read-in-file-in-c.html) you can find some benchmarking. – Paolo M Feb 01 '16 at 16:06
  • 3
    AFAIK, binary files sometimes contain unreadable char, in the fact, they are not char at all. Is this code safe for reading non-text base file? My knowledge is short in this range :) – Andiana Nov 08 '16 at 15:09
  • That's a really good question, I can't tell you that. I think it depends on the default locale used by your system, but I really have no experience with that either. For me, this has always worked reliably as a byte-by-byte copy operation. – Björn Pollex Nov 08 '16 at 16:21
  • 5
    so-called `char` is used in C/C++ to store bytes (and have been for the last 40 years). it's safe to do so, as long as you don't try to actually **USE** that data as characters (don't use strlen() on it, don't print it to console, etc). c++17 introduces `std::byte` for this purpose (which is still char actually `char` in disguise) – d.Candela Apr 10 '18 at 15:25
  • This doesn't work for me, it's not reading anything. Why is that? – dav May 07 '19 at 12:58
  • 2
    @DavidTran Can't say without knowing more - this seems like you should create a minimal example that reproduces the issue, and then post a question. – Björn Pollex May 08 '19 at 06:19
  • it would be nice to add error handling to those lines of code! – ElectRocnic Oct 27 '20 at 22:13
15

Here is a short example, the C++ way using rdbuf. I got this from the web. I can't find my original source on this:

#include <fstream>
#include <iostream>

int main () 
{
  std::ifstream f1 ("C:\\me.txt",std::fstream::binary);

  std::ofstream f2 ("C:\\me2.doc",std::fstream::trunc|std::fstream::binary);

  f2<<f1.rdbuf();

  return 0;
}
Thomas Matthews
  • 52,985
  • 12
  • 85
  • 144
  • 9
    The best, non portable, method is to let the OS copy your file. After all, that is part of what it does for a living; no need to *reinvent the wheel*. – Thomas Matthews Mar 24 '11 at 17:08
14
 sizeof(buffer) == sizeof(char*) 

Use length instead.

Also, better to use fopen with "wb"....

NullPoiиteя
  • 53,430
  • 22
  • 120
  • 137
Alexey Sudachen
  • 344
  • 2
  • 5
9

sizeof(buffer) is the size of a pointer on your last line NOT the actual size of the buffer. You need to use "length" that you already established instead

jcoder
  • 28,098
  • 16
  • 76
  • 120
5

You should pass length into fwrite instead of sizeof(buffer).

retrodrone
  • 5,639
  • 8
  • 36
  • 64
0

Here is implementation of standard C++ 14 using vectors and tuples to Read and Write Text,Binary and Hex files.

Snippet code :

try {
if (file_type == BINARY_FILE) {

    /*Open the stream in binary mode.*/
    std::ifstream bin_file(file_name, std::ios::binary);

    if (bin_file.good()) {
        /*Read Binary data using streambuffer iterators.*/
        std::vector<uint8_t> v_buf((std::istreambuf_iterator<char>(bin_file)), (std::istreambuf_iterator<char>()));
        vec_buf = v_buf;
        bin_file.close();
    }

    else {
        throw std::exception();
    }

}

else if (file_type == ASCII_FILE) {

    /*Open the stream in default mode.*/
    std::ifstream ascii_file(file_name);
    string ascii_data;

    if (ascii_file.good()) {
        /*Read ASCII data using getline*/
        while (getline(ascii_file, ascii_data))
            str_buf += ascii_data + "\n";

        ascii_file.close();
    }
    else {
        throw std::exception();
    }
}

else if (file_type == HEX_FILE) {

    /*Open the stream in default mode.*/
    std::ifstream hex_file(file_name);

    if (hex_file.good()) {
        /*Read Hex data using streambuffer iterators.*/
        std::vector<char> h_buf((std::istreambuf_iterator<char>(hex_file)), (std::istreambuf_iterator<char>()));
        string hex_str_buf(h_buf.begin(), h_buf.end());
        hex_buf = hex_str_buf;

        hex_file.close();
    }
    else {
        throw std::exception();
    }
}

}

Full Source code can be found here

HaseeB Mir
  • 675
  • 12
  • 17
-2

It can be done with simple commands in the following snippet.

Copies the whole file of any size. No size constraint!

Just use this. Tested And Working!!

#include<iostream>
#include<fstream>
using namespace std;
int main()
{
  ifstream infile;
  infile.open("source.pdf",ios::binary|ios::in);

  ofstream outfile;
  outfile.open("temppdf.pdf",ios::binary|ios::out);

  int buffer[2];
  while(infile.read((char *)&buffer,sizeof(buffer)))
  {
      outfile.write((char *)&buffer,sizeof(buffer));
  }

  infile.close();
  outfile.close();
  return 0;
}

Having a smaller buffer size would be helpful in copying tiny files. Even "char buffer[2]" would do the job.

iMajetyHK
  • 139
  • 1
  • 1
  • 7
  • 8
    And what if file size isn't multiple of buffer size? Moreover, why do you have to declare your buffer as `int[]` instead of `char[]`? – firegurafiku May 13 '16 at 11:33
  • I already mentioned it works with `char[]` too and files of any size which means there's no condition that file size should be a multiple of buffer size. – iMajetyHK Sep 09 '18 at 16:04
  • 2
    The fact that you said it works does not mean it works. The fact that it does not work means it does not work. – nunojpg May 27 '20 at 11:42
-2

There is a much simpler way. This does not care if it is binary or text file.

Use noskipws.

char buf[SZ];
ifstream f("file");
int i;
for(i=0; f >> noskipws >> buffer[i]; i++);
ofstream f2("writeto");
for(int j=0; j < i; j++) f2 << noskipws << buffer[j];

Or you can just use string instead of the buffer.

string s; char c;
ifstream f("image.jpg");
while(f >> noskipws >> c) s += c;
ofstream f2("copy.jpg");
f2 << s;

normally stream skips white space characters like space or new line, tab and all other control characters. But noskipws makes all the characters transferred. So this will not only copy a text file but also a binary file. And stream uses buffer internally, I assume the speed won't be slow.

Zeta
  • 701
  • 7
  • 21