reading non-text file in c++

Viewed 449

I open the mp3 file by mistake with notepad++ ( Open with ) and show the entire file in text inside the notepad it was so cool. since I am learning c++ again, I told myself let write a program that opens any file inside the console and display their content on the console so I begin my code like this :

int readAndWrite() {

    string filename(R"(path\to\a\file)");

    ifstream file(filename);



    string line;

    if (!file.is_open()) {
        cerr << "Could not open the file - '"
             << filename << "'" << endl;
        return EXIT_FAILURE;
    }

    while (getline(file, line)){
        cout << line;
    }

    return EXIT_SUCCESS;
}

but it only shows 3 or 4 lines of the file and then exits the program I check my notepad++ again and find out about 700,000 line is in there. I told myself maybe there is a character inside the file so I start writing the above code with the below changes. instead of displaying the file let's wrote inside a text file.

int readAndWrite() {

    string filename(R"(path\to\a\file)");
    string filename2(R"(path\to\a\file\copy)");

    ifstream file(filename);
    ofstream copy(filename2);


    string line;

    if (!file.is_open()) {
        cerr << "Could not open the file - '"
             << filename << "'" << endl;
        return EXIT_FAILURE;
    }

    while (getline(file, line)){
        copy << line;
    }

    return EXIT_SUCCESS;
}

and again the same results. next try I give up on reading the file line by line so I start copying with this function.

void copyStringNewFile(ifstream& file, ofstream& copy)
{
    copy << file.rdbuf();
}

and their results did not change a bit. At this point, I told myself the problem is from file maybe and it is kinda is because when I use a simple text file all of the above codes work.

1 Answers

Like all other non-text files, mp3 files don't contain lines so you shouldn't use std::getline. Use istream::read and ostream::write. You can use istream::gcount to check how many characters that was actually read.

Since you are dealing with non-text files, also open the files in binary mode.

You should also test if opening both files works - that is, both the input and the output file.

Example:

#include <cerrno>
#include <cstring>
#include <fstream>
#include <iostream>

int readAndWrite() {
    std::string filename(R"(path\to\a\file)");
    std::string filename2(R"(path\to\a\file_copy)");

    std::ifstream file(filename, std::ios::binary);
    if(!file) {
        std::cerr << '\'' << filename << "': " << std::strerror(errno) << '\n';
        return EXIT_FAILURE;
    }

    std::ofstream copy(filename2, std::ios::binary);
    if(!copy) {
        std::cerr << '\'' << filename2 << "': " << std::strerror(errno) << '\n';
        return EXIT_FAILURE;
    }

    char buf[1024];
    while(file) {
        file.read(buf, sizeof(buf));
        // write as many characters as was read above
        if(!copy.write(buf, file.gcount())) {
            // write failed, perhaps filesystem is full?
            std::cerr << '\'' << filename2 << "': " << std::strerror(errno) << '\n';
            return EXIT_FAILURE;
        }
    }

    return EXIT_SUCCESS;
}

int main() {
    return readAndWrite();
}
Related