How to copy files in Visual C++? - c++

I am using Visual C++. How to copy the content of this file to another file?
UINT32 writeToLog(wstring log)
{
wfstream file1 (LOG_FILE_NAME, ios_base::out);
file1 << log;
file1.close();
// want to copy file1 to file2
return 0;
}

What exactly do you want to do? If you need a copy of the data, you can read it in and write it back out again. If you really need a copy of the file, you have to use OS specific calls.
In many cases, reading in the file data and then writing it out again to a different file is a close enough approximation to a copy - like this:
ifstream file1(...);
ofstream file2(...);
std::copy(istream_iterator<char>(file1),istream_iterator<char>(),ostream_iterator<char>(file2));
However that really isn't a copy - it's creating a new file with the same contents. It won't correctly handle hard links or symlinks, it won't correctly handle metadata and it will only 'copy' the default file stream.
If you need a file copy on Windows you should call one of CopyFile, CopyFileEx or CopyFileTransacted depending on your exact requirements.

Standard C++ has no file copying facility, other than reading the file into memory and writing it out again to a different file. As you are using Windows, you can use the CopyFile function - other OSs have similar, OS-specific functions.

The above code from Joe Gauterin did not work for me. I was trying to copy a .tga image file, so maybe something about istream_iterator<char> screwed it up. Instead I used:
ifstream file1(...);
ofstream file2(...);
char ch;
while(file1 && file1.get(ch))
{
file2.put(ch);
}

Related

How to get raw bytes written to ostream by an external library without creating a file

(My previous questions was closed as a duplicate of Are there binary memory streams in C++ which is ridiculous, since i can't change the implementation of the library I'm using)
I'm using a library (Poco) to create zip files. It takes ostream as an input and writes the data of the zip file into it. Something like:
std::ofstream ofs("file.zip", std::ios::binary);
Compress compress(ofs);
// add data to compress ...
compress.close();
// now file.zip contains added file
This works. But I want to be able to create a zip in memory without creating a file. I tried using stringstream instead of ofstream, i get additionl newline characters in the data in the zip file is corrupted. Is there any other stream i can use?
(If someone still thinks it's a duplicate, I'm gonna need an explanation, since I don't see how this other question is helpful for me)
Use a std::stringstream -- that will create an in-memory string that you can write to as an ostream, and WILL NOT add extra newlines. If you later copy the string to an fstream that was opened in text mode (such as std::cout), then that process may add extra CR characters that are not in the string (nor in the original output).
If you are seeing extra characters corrupting your stream, they are coming from somewhere else -- something besides you compress call/lib is writing to the stream, or something with how you are looking at your stream is doing something.
If you're on linux, how about creating an anonymous file using memfd_create? You can then open /proc/self/fd/<fd> and do your stuff. Some implementations of std::ofstream may even provide a constructor that takes a FILE*, you can check if that's the case on your system.

Write to the start of a textfile in c++

I was looking for an easy way to write something into the first line of an already existing textfile. I tried using ofstream like this:
ofstream textFileWriter("Data/...txt");
if (textFileWriter.is_open())
{
textFileWriter << "HEADER: stuffstuff";
}
But it would delete everything which used to be in that file, even though the ofstream wasn't constructed with std::ofstream::trunc. I cannot use std::ofstream::app, since it is important to write into the first line.
Copying the whole textfile into a vector which has the line already and then writing it back would be my last option, but something I would really like to avoid, since the textfiles are quite large.
You can't simply "append" to the beginning of a file.
The common solution is to open a new (temporary) file, write your new header, write the rest of the original file to the temporary file, and then "rename" (using the OS system calls) the temporary file as the original file.
Or as you say in your question, read the original file into an in-memory buffer (e.g. a vector) and do the modification in that buffer, and then write the buffer to the file.

Read and write image data C++

I've just started learning C++, and I'm working on a program that is supposed to grab an image from the hard disk and then save it as another name. The original image should still remain. I've got it work with text files, because with those I can just do like this:
ifstream fin("C:\\test.txt");
ofstream fout("C:\\new.txt");
char ch;
while(!fin.eof())
{
fin.get(ch);
fout.put(ch);
}
fin.close();
fout.close();
}
But I suppose that it's not like this with images. Do I have to install a lib or something like that to get it work? Or can I "just" use the included libraries? I know I'm not really an expert of C++ so please tell me if I'm totally wrong.
I hope someone can and want to help me! Thanks in advance!
Btw, the image is a .png format.
You can use the std streams but use the ios::binary argument when you open the stream. It's well documented and there is several examples around the internet
You are apparently using MS Windows: Windows distinguishes between "text" and "binary" files by different handling of line separators. For a binary file, you do not want it to translate \n\r to \n on reading. To prevent it, using the ios::binary mode when opening the file, as #Emil tells you.
BTW, you do not have to use \\ in paths under windows. Just use forward slashes:
ifstream fin("C:/test.txt");
This worked even back in WWII using MS-DOS.
If the goal is just to copy a file then CopyFile is probably better choice than doing it manually.
#include <Windows.h>
// ...
BOOL const copySuccess = CopyFile("source.png", "dest.png", failIfExists);
// TODO: handle errors.
If using Windows API is not an option, then copying a file one char at a time like you have done is very inefficient way of doing this. As others have noted, you need to open files as binary to avoid I/O messing with line endings. A simpler and more efficient way than one char at a time is this:
#include <fstream>
// ...
std::ifstream fin("source.png", std::ios::binary);
std::ofstream fout("dest.png", std::ios::binary);
// TODO: handle errors.
fout << fin.rdbuf();

Writing at the beginning of a file, keeping file contents

I have a text file where I want to write. I want to keep the file content always. I want to write following a "FIFO" (last write always on the top line of the file).
I try using fout.open("filename"); with ate mode to keep file content, after that use seekg(0) trying to take back writing cursor to the begining of the file. Didn't work.
The unique way I found to do that I think it's so time-expensive, copy all the file content to a temporary file. Write want I want to write and after that write the content of the temp file at the end of the target file.
There must be an easy way do this operation?
Jorge, no matter what you will have to rewrite the entire file in memory. You cannot simply keep the file where it is and prepend memory, especially since it's a simple text file (maybe if there was some form of metadata you could...)
Anyways, your best chance is to flush the old contents into a temporary location, write what you need and append the old contents.
I'm not sure what you're asking for. If you want to add a
line to the beginning of the file, the only way is to open a
new, temporary file, write the line, copy the old file into
after the new line, then delete the old file and rename the
temporary.
If the original line has a fixed length, and you want to replace
it, then all you have to do is open the file with both
ios_base::in and ios_base::out.
First, you should realize that files are historically streams, i.e. they can only be read and written in one direction. This comes from the times when files were stored on tapes, which could move in one direction (at that time).
However, if you only want to prepend, then you can just store your file backwards. Sounds silly? Maybe, but this would work with just a little overhead.
Apart from that, with current OS's you will need to make a copy to prepend. While files are not streams anymore, and can be accessed randomly on a harddisk, they are still made to grow in one direction. Of course you could make a filesystem, where files grow in both directions, but I have not heard of one.
With <fstream> you may use the filebuf class.
filebuf myfile;
myfile.open ("test.txt", ios::in | ios::out);
if (!myfile.is_open()) cout << "cannot open" << endl;
myfile.sputn("AAAA", 4);
myfile.close();
filebuf myfile2;
myfile2.open ("test.txt", ios::in | ios::out);
if (!myfile2.is_open()) cout << "cannot open 2" << endl;
myfile2.sputn("BB", 2);
myfile2.close();
write to a string in order you want, then flush to the file

how do i legitimately change filename value of ofstream object?

I'm having troubles with ofstream , which is - when I change value of ofstream object like this
ofstream o_save;
/*code*/
o_save = ofstream(filename); //Problem is here
...the line above completely erase contents of file.
The question is how do I legitimately change filename value of ofstream object ?
P.S. I cant define it when I declare it, because I want it global and I'm not sure which save file I select.
The question is quite vague and contradictory, and the OP seems to have slept after asking the question. So I shall try to peek inside his head and try to elaborate what he wants.
For opening a file, there are many modes for that. Open it like this.
ofstream o_value ;
o_value.open("file.txt") ;
If you want to preserve the original contents of that file, use..
o_value.open("file.txt", ios::app) ;
If you want to close it later and open another one, close using...
o_value.close() ;
Chaning of file names is normally not allowed in case of ofstream. You can use rename from <cstdlib>. You can delete a file though using remove("file.txt") in <cstdio> .
What does it mean to "change the name" of an ofstream object?
The only "name" an ofstream object has is the name of the
variable. An ofstream object is a data stream. You can (on
some systems) change the name of the file it is associated with,
using rename, but somehow, I don't think this is what you want
either. You can also close the stream, and reopen it on another
file.
You cannot assign between iostream objects. If worse comes to
worse, you can declare the global object as a pointer, and
assign to it (using *o_save to write to it).
Finally, the standard says that when you open an ofstream, you
truncate the file, if one exists. If this is not what you want
to do, then you have to add some flags to the open mode. If you
add std::ios_base::app, for example, you will no longer
truncate the file, and all writes will be to the end of file
(atomically, if the system supports it). Alternatively (albeit
quite surprising), you could add std::ios::in to the flags;
this will fail if the file doesn't exist, but will allow writing
anywhere in the file. This is the only way to open a file for
writing if you want to be able to write anywhere in the file,
even if you don't want to read it.
The ofstream does not have some kind of an abstract name attribute, the name is just a parameter to some of its member functions, in that sense asking how to
change filename value of ofstream object
is meaningless.
In general you can rename files with std::rename from <cstdlib> or use Boost.Filesystem.