I'm simply trying to read a small 1KB binary file into a buffer and then write the buffer back to the disk. It seems that for some files the outputfile is completely different from the Inputfile, what am I doing wrong?
Thank you very much.
std::ifstream myfile;
myfile.open (testinput.rar);
myfile.seekg (0, myfile.end);
filesize = myfile.tellg();
myfile.seekg (0, myfile.beg);
char *mybuffer= new char[filesize];
myfile.read(mybuffer,filesize);
myfile.close();
ofstream myfile3;
myfile3.open ("testoutput.rar");
for(unsigned int i=0; i<filesize; i++)
myfile3 << mybuffer[i];
myfile3.close();
You have to open the file as binary.
myfile.open ("testinput.rar", std::ios::binary);
myfile3 should be opened in binary mode:
myfile3.open("testoutput.rar", ios::out | ios::binary);
Additionally, you may want to consider using write() to modify files:
myfile3.write(mybuffer[i], sizeOfBuffer);
Related
How might I read any file type as binary in C++? So far, I've been able to read .txt files in binary using std::bitset like so:
std::ifstream myfile;
myfile.open("example.txt", std::ios::binary);
while (getline (myfile, line) ) {
for (std::size_t i = 0; i<line.size(); ++i) {
std::bitset<8> a = std::bitset<8>(line[i]); //convert every character to binary, save it in a
std::cout<<((char)std::bitset<8>(a).to_ulong())<<'\n';
}
}
In the first line, how might I read a file like sound.mp3 or word.docx as a binary file? I understand that in they really just are binary files, but how can I read them as such?
Thanks!
By casting from a block of memory of chars to binary, you can read a file as binary.
std::streampos size;
char * memblock;
std::ifstream myfile ("sound.mp3", std::ios::in|std::ios::binary|std::ios::ate);
//ios::ate puts the reader at the end of the file
if (file.is_open())
{
size = myfile.tellg();
memblockChar = new char [size];
myfile.seekg (0, std::ios::beg);
myfile.read (memblockChar, size);
myfile.close();
for (int i = 0; i<size; i++) {
std::cout << (((std::bitset<8>)memblockChar[i]).to_ulong()) << '\n';
}
delete[] memblockChar;
}
else std::cout<<"Unable to open file"<<std::endl;
This could be used in a main method, or anywhere else.
I'm trying to use this code to read from the file and store values in a vector. This works once and displays everything correctly.
void SongList::LoadSongsFromFile()
{
song temp;
string line;
ifstream myFile("SongListFile.txt");
while (getline(myFile, line)) {
myFile >> temp.title;
myFile >> temp.artist;
myFile >> temp.genre;
songs.push_back(temp);
}
}
I then want to append to the file, using the following:
void SongList::AddSong(song tmp)
{
cout << "Enter the title, artist then genre of the song, each on a new line.\n";
cin >> tmp.title;
cin >> tmp.artist;
cin >> tmp.genre;
songs.push_back(tmp);
ofstream myFile("SongListFile.txt");
myFile.open("SongListFile.txt", ios::app);
myFile << tmp.title << " " << tmp.artist << " " << tmp.genre;
cout << tmp.title << " by " << tmp.artist << " is now a part of the song library! ";
}
Everything works fine, but the file will wipe and have nothing in it once I finish the program, even if I have tried to append to the file. To be clear, I need the previous contents, and new lines that I have added to be there every time I reopen the program.
std::ofstream myFile("SongListFile.txt"); opens the file and truncates. You should use std::ofstream myFile("SongListFile.txt", std::ios::app);
Otherwise you can declare the myFile object with std::ofstream myFile; and then open a file using it and the append option: myFile.open("SongListFile.txt", std::ios::app);
replace
ofstream myFile("SongListFile.txt");
myFile.open("SongListFile.txt", ios::app);
with
ofstream myFile("SongListFile.txt",ios::app);
or
ofstream myFile;
myFile.open("SongListFile.txt", ios::app);
what happens in your code is that the ofstream myFile("SongListFile.txt") opens the file with default mode ios::out and then the attempt to open the file with myFile.open("SongListFile.txt", ios::app); in the next line fails because the file is already opened by the previous line making the ios::app ineffective for the file and thus every time you open the file using ofstream, the file gets truncated.
Actually ofstream constructor has 3 parameters: (const char *_Filename, ios_base::openmode _Mode = ios_base::out, int _Prot = (int)ios_base::_Openprot).
So the call std::ofstream myFile("SongListFile.txt"); is equavalent to
std::ofstream myFile("SongListFile.txt", std::ios::out);
Remark: std::ios::out == ios_base::out.
Other possible values for the second argument are:
std::ios::app
std::ios::trunc
Deeper in CRT code this parameter is first translated according to this:
std::ios::out --> std::ios::out
std::ios::trunc --> std::ios::trunc | std::ios::out
std::ios::app --> std::ios::app | std::ios::out
And a bit more deeper it is translated into good old fopen modes according to this:
std::ios::out --> "w"
std::ios::trunc | std::ios::out --> "w"
std::ios::app | std::ios::out --> "a"
fopen modes description from MSDN:
"w" - Opens an empty file for writing. If the given file exists, its contents are destroyed.
"a" - Opens for writing at the end of the file (appending) without removing the end-of-file (EOF) marker before new data is written to the file. Creates the file if it does not exist.
TL;DR:
std::ofstream myFile("SongListFile.txt"); - reset the file content.
std::ofstream myFile("SongListFile.txt", std::ios::out); - reset the file content.
std::ofstream myFile("SongListFile.txt", std::ios::trunc); - reset the file content.
std::ofstream myFile("SongListFile.txt", std::ios::app); - don't reset the file content.
First 3 variants are equivalent (for std::ofstream!).
I have a project witch I have to back up my text files in binary mode with the destination that is getting from the user.
I was thinking to open my text files in binary and close them in the address that I have got from the user. but I don't know how to do that.
is there a way to close the files in a new address(saving them where ever I want) and not set an address directly because it's suppose to set by the user
Here is sample code to save the file:
#include <fstream>
int main () {
std::ofstream ofs;
ofs.open ("test.txt", std::ofstream::out | std::ofstream::binary | std::ofstream::trunc);
ofs << " data goes here";
ofs.close();
return 0;
}
The following is sample code to copy files:
ifstream source("from.txt", ios::binary);
ofstream dest("to.txt", ios::binary);
source.seekg(0, ios::end);
ifstream::pos_type size = source.tellg(); // file size
source.seekg(0);
char* buffer = new char[size]; // allocate memory for buffer
// copy file
source.read(buffer, size);
dest.write(buffer, size);
// clean up
delete[] buffer;
source.close();
dest.close();
I convert this code in python to c++:
content = file(filename, "rb").read()
this is the code in c++:
ifstream file;
file.open(filename, fstream::binary);
file.seekg (0, ios::end);
long fileLength = file.tellg();
file.seekg(0, ios_base::beg);
char *content = new char[fileLength];
file.read(content, fileLength);
when I run the python code I get a long string in the content (500 characters~) while the c++ code return only 4 characters.
any suggestion?
thanks
The simplest way to read an entire file is:
std::string content(
std::istreambuf_iterator<char>(std::ifstream(filename, std::fstream::binary).rdbuf()),
std::istreambuf_iterator<char>());
I'm trying to open a binary file for writing without erasing the content. But I do not want to write to eof. I want to write to a specific position in file.
Here is a litte example:
ofstream out("test.txt", ios::binary | ios::app);
for(int i = 0; i < 100; i++)
out.put('_');
out.write("Hallo", 5);
out.close();
ofstream out2("test.txt", ios::binary | ios::app);
out2.seekp(10);
out2.write("Welt", 4);
out2.close();
If using app, seek doesn't work. If not using app opening file erases data. Does anybody know an answer?
try the second overload of seekp, which allows you to provide an offset and a direction, this could be begining of file in your case (i.e. ios_base::beg). This of course assumes you know what you are doing and all you want to do is overwrite an existing number of characters.
EDIT: here is fully working example:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
{
ofstream out("test.txt", ios::binary);
for(int i = 0; i < 100; i++)
out.put('_');
out.write("Hallo", 5);
}
{
fstream out2("test.txt", ios::binary | ios::out | ios::in);
out2.seekp(10, ios::beg);
out2.write("Welt", 4);
}
}
When opening with ios::app, it is as if you open a new file that just happened to be attached to an existing file: you can not access the existing file. I'm not sure, because I would do as in Kerrek's answer, but if you really want to try, you probably have to open with "ios::in | ios::out", similar to fopen("test.txt", "rw").
Or as crashmstr points out: ios::out might be enough.
You cannot magically extend the file from the middle. Perhaps easiest to write to a new file: First copy the initial segment, then write your new data, then copy the remaining segment. When all is done, you can overwrite the original file.
According to the specification of fstream here
fstream::open
the ios::app "Sets the stream's position indicator to the end of the stream before EACH output operation." So ios::app doesn't work for replacing, seeks of any sort fail, at least for me.
Just using ios::out does wipe out the file contents preserving only the size, basically turning the file into trash.
ios::in|ios::out turned out as the only working thing for me.
Working Code: This code searches for a string (OLD-STRING) in cout.exe and replaces with a new string (NEW-STRING).
`#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main(int argc, char *argv[])
{
fstream ifs;
ifs.open ("C:\\Users\\user\\Desktop\\cout.exe", fstream::binary | fstream::in | fstream::out);
std::string str((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
size_t pos = str.find("OLD-STRING");
if (pos != string::npos)
{
cout << "string found at position: " << int(pos) << endl;
ifs.seekp(pos);
ifs.write("NEW-STRING", 10);
}
else
{
cout << "could not find string" << endl;
}
if (ifs.is_open())
ifs.close();
return 0;
}`