0

I'm trying to make a program that would load an entire binary form of a file into the memory and then put it into a newly created file and test if it would behave the same But when I look at the files i see that they aren't the same and that the copy has just a part of the original file

Any Ideas how can I make It work?

Content of an original exe (Part of it there is more)

Content of a copy

The Code that I'm useing:

#include <iostream>
#include <string>
#include <sstream>
#include <fstream>

int main()
{
    bool end = 0;
    std::string line;
    std::stringstream ss;
    std::string Tfile = "Touhou/Touhou06.exe";
    std::fstream In_stream(Tfile, std::ios::in, std::ios::binary);

    while (std::getline(In_stream, line))
    {
        ss << line;
    }

    In_stream.close();
    std::string File_content;
    ss >> File_content;
    ss.clear();

    std::fstream Out_stream("TheLong.exe", std::ios::out);
    Out_stream << File_content;
    Out_stream.close();
}

EDIT: After the changes Code has ended looking like that

#include <iostream>
#include <string>
#include <sstream>
#include <fstream>

int main()
{
    int length;
    bool end = 0;
    std::string line;
    std::string Tfile = "Touhou/Touhou06.exe";
    std::fstream In_stream(Tfile, std::ios::in | std::ios::binary);

    In_stream.seekg(0, std::ios::end);
    length = In_stream.tellg();
    In_stream.seekg(0, std::ios::beg);

    std::string buffer(length, '\0');
    In_stream.read(&buffer[0], length);
    In_stream.close();

    std::fstream Out_stream("TheLong.exe", std::ios::out);
    Out_stream.write(&buffer[0], length);
    Out_stream.close();
}

And it still doesn't work correctly and there is a shift to the content of a copy and I don't know why. At least It seems that there is the full content of the original file

Original

Copy after changes

1 Answers1

2

First of all, the line

std::fstream In_stream(Tfile, std::ios::in, std::ios::binary);

is wrong. In ISO C++, there is no constructor for the class std::fstream that takes 3 parameters. If this code compiles on your platform, then you are probably (unintentionally) using a platform-specific constructor. You should write this instead:

std::fstream In_stream(Tfile, std::ios::in | std::ios::binary);

The flags of the second parameter should always be combined with the bitwise-OR operator.

Also, you are opening the output file in text mode, whereas you are opening the input file in binary mode. You should open both files in binary mode.

Another problem is that the function std::getline will consume and discard any newline characters. Therefore, all bytes of the binary file that have a value that is equal to the character code of the newline character will not be written to ss.

Additionally, the line

ss >> File_content;

won't extract the entire content of the stream ss, but will only extract a single word (i.e. a sequence of bytes until the character code of a whitespace character is encountered).

In your posted binary files, the copying is cut off as soon as the byte value 09 is encountered. In ASCII, this is the character code for a tab, which is a whitespace character.

The problem is that you are using functions that are intended for formatted I/O. However, you want to perform unformatted I/O. Therefore, you should be using functions such as std::istream::read and std::ostream::write instead.

Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39
  • How do I declare an std::istream? because I can't understand It – themakabrapl Jan 09 '22 at 14:25
  • @themakabrapl: [`std::fstream`](https://en.cppreference.com/w/cpp/io/basic_fstream) inherits from `std::istream` and `std::ostream`. So you can just declare an `std::fstream`, as you do now. – Andreas Wenzel Jan 09 '22 at 14:32
  • @themakabrapl: I just noticed that you had an additional bug: You were calling the constructor of `std::fstream` incorrectly. I have edited my answer accordingly. – Andreas Wenzel Jan 09 '22 at 15:14
  • Some weird complications have occurred and I have described them in the main post – themakabrapl Jan 09 '22 at 16:33
  • @themakabrapl: You are opening the output file in text mode. This is causing `0A` (`\n`) to get expanded to `0D 0A` (`\r\n`). You should open it in binary mode, as you are doing with the input file. I have updated my answer to mention this additional bug. – Andreas Wenzel Jan 10 '22 at 02:03
  • Using `std::string` to hold the contents of a binary file is a bit odd. If you are just reading a file of text all at once, no problem, otherwise you may not want the data held in a nul-terminated string. – David C. Rankin Jan 10 '22 at 03:39
  • @DavidC.Rankin: In contrast to null-terminated C-style strings, `std::string` can also handle null characters inside the string (though it may be prone to errors in certain situations). However, you are right that a `std::vector` or a dynamically allocated buffer of type `char[]` or `unsigned char[]` would probably be more meaningful for handling binary data. – Andreas Wenzel Jan 10 '22 at 03:44