So I'm writing a function to read a file and put its content into another file. Here's what I've got so far:
void myFile::printWords(string input, string output) {
ifstream file(input.c_str());
ofstream file_out(output.c_str());
string word;
if(!file.is_open())
{
printf("File can't be opened\n");
exit(o);
}
while(file >> word) {
cout<< word << '\n';
}
file.close();
}
Question is how do I proceed with writing to a file?
You don't quite need iostreams to copy files; you just need raw stream buffers. For example, here's a complete copy program:
#include <algorithm> // for std::copy
#include <cstdlib> // for EXIT_FAILURE
#include <fstream> // for std::filebuf
#include <iterator> // for std::{i,o}streambuf_iterator
int main(int argc, char *argv[])
{
if (argc != 3) { return EXIT_FAILURE; }
std::filebuf infile, outfile;
infile.open(argv[1], std::ios::in | std::ios::binary);
outfile.open(argv[2], std::ios::out | std::ios::binary);
std::copy(std::istreambuf_iterator<char>(&infile), {},
std::ostreambuf_iterator<char>(&outfile));
}
rather than doing this on a word to word bassis, which doesn't work weel with whitespaces, you could (if you really waht to use c++) use a char[] dump of the file
std::fstream ifile(input.c_str(), std::ios::in | std::ios::binary | std::ios::ate);
std::fstream ofile(output.c_str(), std::ios::out | std::ios::binary);
if (!(ifile.is_open() && ofile.is_open())) { handle_error(); }
size_t size = ifile.tellg();
char* buffer = new char[size];
ifile.seekg(0, std::ios::beg);
ifile.read(buffer, size);
ofile.write(buffer, size);
ifile.close();
ofile.close();
Still it would make much more sense to use your OS functionality
Related
i tried to open and read an application in binary mode and get 100 characters(For a large file, i did this so that i could read all the characters) in binary mode and then transfer them to new file(in fact, this program will be the same as the previous program, but with a different name ) to find out if it works properly or not
so anyway my source code is:
#include <iostream>
#include <vector>
#include <fstream>
using namespace std;
int main()
{
//Vector of 100 characters initialised to 0
vector<char> ch(100, 0);
ifstream file("example.exe",ios::in|ios::binary);
if (file.is_open())
{
while (file)
{
file.read(ch.data(), 100);
// Get the number of bytes actually read
size_t count = file.gcount();
ch[file.gcount()] = '\0';
//cout << ch.data() << endl;
ofstream output("output.exe", ios::out | ios::binary | ios::app);
output.write(ch.data(), sizeof(100));
output.close();
}
}
file.close();
}
my problem is the output with the correct information is not included and the size is smaller than the original application(example.exe) what is happening?
The line output.write(ch.data(), sizeof(100));
should be replaced with output.write(ch.data(), count);
Since sizeof(100) only returns 4, which is the size in bytes of an integer.
You should also remove the line ch[file.gcount()] = '\0'; since file.gcount() might be out of bound.
I just tested it and this works for me
#include <iostream>
#include <vector>
#include <fstream>
using namespace std;
int main()
{
vector<char> ch(100, 0);
ifstream file("app.exe",ios::in|ios::binary);
if (file.is_open())
{
ofstream output("app_copy.exe", ios::out | ios::binary | ios::trunc);
while (file)
{
file.read(ch.data(), 100);
output.write(ch.data(), file.gcount());
}
output.close();
}
file.close();
}
Notice that ios::app is replaced by ios::trunc, which will delete the content of the file when opening.
std::string uncomment(std::ifstream& infile)
{
std::fstream outfile;
std::string buffer;
std::string tmp;
while(getline(infile, buffer)) {
if(!(buffer[0] == '#')) {
buffer += tmp;
}
}
return buffer;
}
int main(int argc, char const *argv[])
{
std::string filename = argv[1];
std::ifstream infile(filename);
std::fstream outfile("outfile.txt");
std::string buffer = uncomment(infile);
std::cout << buffer << std::endl;
outfile << buffer << std::endl;
outfile.close();
infile.close();
}
Why this code does not produce a new file "outfile.txt"?
Why this code does not print uncommented string on line 22?
I am not sure what std::fstream does but I think you want to use std::ofstream instead.
Looking quickly at docs your outfile constructor is using the default fstream constructor and you don't specify the mode (http://www.cplusplus.com/reference/fstream/fstream/fstream/)
Have you tried using an ofstream constructor since this is an output file?
To create file (if not exist) with fstream you need to pass std::ios::out as open mode to your fstream constructor. like this
std::fstream outfile("outfile.txt", std::ios::out);
Note : Here you don't specified the path to your desired outfile.txt, so it will be generate in your project directory, make sure you check there.
First of all you need to use std::ofstream object to create output file. Or you need to use something like this
std::fstream fs;
fs.open ("outfile.txt", std::fstream::out);
#include <iostream>
#include <fstream>
int main() {
std::ofstream outfile("text.txt", ios::trunc);
std::ifstream infile("text.txt", ios::trunc);
outfile.seekp(0);
std::cout << "This is a file";
infile.seekg(0, ios::end);
int length = infile.tellg();
infile.read(0, length);
infile.close();
outfile.close();
return 0;
}
I think I get the idea behind this, but I feel like (and I'm pretty sure) I have no idea what I'm doing. I've looked it up and everything has confused me. I've read through a C++ reference, and then I googled it, but I still don't understand what I'm doing wrong.
#include <iostream>
#include <fstream>
#include <cstring>
int main() {
std::fstream file("text.txt", std::ios_base::in | std::ios_base::out);
file << "This is a file";
int length = file.tellg();
std::string uberstring;
file >> uberstring;
std::cout << uberstring;
char *buffer = new char[length + 1];
file.read(buffer, length);
buffer[length] = '\0';
file.close();
delete [] buffer;
return 0;
}
I tried this, but it isn't printing anything. Why isn't this working?
If you want to read and write to the same file, just use a normal std::fstream ... there is no need to attempt and open the same file as both a ifstream and ofstream. Also if you want to write data to the file, use the operator<< on the actual fstream instance object, not std::cout ... that will simply write to wherever std::cout is set, which is typically the console. Finally, the call to read has to go back into a buffer, you can't use NULL as an argument. So your code would change to the following:
int main()
{
std::fstream file("text.txt", ios_base::in | ios_base::out);
//outfile.seekp(0); <== not needed since you just opened the file
file << "This is a file"; //<== use the std::fstream instance "file"
//file.seekg(0, ios::end); <== not needed ... you're already at the end
int length = file.tellg();
//you have to read back into a buffer
char* buffer = new char[length + 1];
infile.read(buffer, length);
buffer[length] = '\0'; //<== NULL terminate the string
file.close();
delete [] buffer;
return 0;
}
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;
}`
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 );
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), {});
}
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;
}
sizeof(buffer) == sizeof(char*)
Use length instead.
Also, better to use fopen with "wb"....
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
You should pass length into fwrite instead of sizeof(buffer).
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
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.
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.