I have a .crl file which I want to copy to another location. From all the posts which I have seen till now, it can't be done without copying the contents. Is there any method in which I can transfer the file to another location in cpp without copying the contents?
I tried by copying the contents by using the usual fopen method. But the data was not being written to the buffer . If there is no direct method, could anyone please tell me how to read the certificate file and write the contents to another file in a different location?
I have also tried the fstream methods
std::ofstream dest("destination.crl", std::ios::trunc|std::ios::binary);
if(!dest.good())
{ std::cerr << "error opening output file\n";
//std::exit(2);
}
std::fstream src("sourcec.crl", std::ios::binary);
if(!src.good())
{ std::cerr << "error opening input file\n";
//std::exit(1);
}
dest << src.rdbuf();
if(!src.eof()) std::cerr << "reading from file failed\n";
if(!dest.good()) std::cerr << "writing to file failed\n";
But it displayed the errors:
error opening input file
reading from file failed
writing to file failed
Thank you in advance
I found this here.
See, this might help you. As you do not want to read, I thought you do not want to perform read and write operation yourself.
#include <istream>
#include <iostream>
#include <fstream>
#include <iterator>
using namespace std;
int main()
{
fstream f("source.crl", fstream::in|fstream::binary);
f << noskipws;
istream_iterator<unsigned char> begin(f);
istream_iterator<unsigned char> end;
fstream f2("destination.crl",
fstream::out|fstream::trunc|fstream::binary);
ostream_iterator<char> begin2(f2);
copy(begin, end, begin2);
}
Based on your response, I write another answer.
For Window, there is function [CopyFile][1]. You can use this function to copy the file without reading the content by yourself.
For linux/unix based, I am unable to find the direct equivalent of CopyFile.
I believe that this question might help you.
Related
I'm facing a problem using std::ifstream to read a file. I have a zip file called "nice_folder.zip" (71.6MB) and the following code that reproduces the issue:
#include <filesystem>
#include <fstream>
#include <iostream>
#include <memory>
#include <unistd.h>
int main() {
size_t read = 0;
size_t f_size = std::filesystem::file_size("nice_folder.zip");
std::shared_ptr<char[]> buffer{new char[4096]};
std::ifstream file{"nice_folder.zip"};
while (read < f_size) {
size_t to_read = (f_size - read) > 4096 ? 4096 : (f_size - read);
file.read(buffer.get(), to_read);
sleep(2);
std::cout << "read: " << std::to_string(to_read) << "\n";
}
}
The problem is the following: after some read cycles I delete the file from the folder but it keeps reading it anyway. How is it possible ? How can I catch an error if an user delete a file while reading using ifstream ? I guess that ifstream takes the content of the file into memory before start reading but i'm not sure.
If you're doing this on e.g. linux, then the OS will not actually delete the file until you've closed all file handles to it. So it might seem like the file is deleted, but it's still stored somewhere on disk. See e.g. What happens internally when deleting an opened file in linux.
So if you're trying to detect this file deletion to prevent wrong reads, then don't worry, the file won't actually be deleted.
If you close the stream, and then try and open it again for that file, you'll get an error. But that also means you won't be able to read from it...
Hello and sorry if the answer is clear to those out there. I am still fairly new to programming and ask for some guidance.
This function should write just one of the three string parameters it takes in to the txt file I have already generated. When I run the program the function seems to work fine and the cout statement shows the info is in the string and does get passes successfully. The issue is after running the program I go to check the txt file and find it is still blank.
I am using C++17 on visual studio professional 2015.
void AddNewMagicItem(const std::string & ItemKey,
const std::string & ItemDescription,
const std::string &filename)
{
const char* ItemKeyName = ItemKey.c_str();
const char* ItemDescriptionBody = ItemDescription.c_str();
const char* FileToAddItemTo = filename.c_str();
std::ofstream AddingItem(FileToAddItemTo);
std::ifstream FileCheck(FileToAddItemTo);
AddingItem.open(FileToAddItemTo, std::ios::out | std::ios::app);
if (_access(FileToAddItemTo, 0) == 0)
{
if (FileCheck.is_open())
{
AddingItem << ItemKey;
std::cout << ItemKey << std::endl;
}
}
AddingItem.close(); // not sure these are necessary
FileCheck.close(); //not sure these are necessary
}
This should print out a message onto a .txt file when you pass a string into the ItemKey parameter.
Thank you very much for your help and again please forgive me as I am also new to stackoverflow and might have made some mistakes in formatting this question or not being clear enough.
ADD ON: Thank you everyone who has answered this question and for all your help. I appreciate the help and would like to personally thank you all for your help, comments, and input on this topic. May your code compile every time and may your code reviews always be commented.
As mentioned by previous commenters/answerers, your code can be simplified by letting the destructor of the ofstream object close the file for you, and by refraining from using the c_str() conversion function.
This code seems to do what you wanted, on GCC v8 at least:
#include <string>
#include <fstream>
#include <iostream>
void AddNewMagicItem(const std::string& ItemKey,
const std::string& ItemDescription,
const std::string& fileName)
{
std::ofstream AddingItem{fileName, std::ios::app};
if (AddingItem) { // if file successfully opened
AddingItem << ItemKey;
std::cout << ItemKey << std::endl;
}
else {
std::cerr << "Could not open file " << fileName << std::endl;
}
// implicit close of AddingItem file handle here
}
int main(int argc, char* argv[])
{
std::string outputFileName{"foobar.txt"};
std::string desc{"Description"};
// use implicit conversion of "key*" C strings to std::string objects:
AddNewMagicItem("key1", desc, outputFileName);
AddNewMagicItem("key2", desc, outputFileName);
AddNewMagicItem("key3", desc, outputFileName);
return 0;
}
Main Problem
std::ofstream AddingItem(FileToAddItemTo);
opened the file. Opening it again with
AddingItem.open(FileToAddItemTo, std::ios::out | std::ios::app);
caused the stream to fail.
Solution
Move the open modes into the constructor (std::ofstream AddingItem(FileToAddItemTo, std::ios::app);) and remove the manual open.
Note that only the app open mode is needed. ofstream implies the out mode is already set.
Note: If the user does not have access to the file, the file cannot be opened. There is no need to test for this separately. I find testing for an open file followed by a call to perror or a similar target-specific call to provide details on the cause of the failure to be a useful feature.
Note that there are several different states the stream could be in and is_open is sort of off to the side. You want to check all of them to make sure an IO transaction succeeded. In this case the file is open, so if is_open is all you check, you miss the failbit. A common related bug when reading is only testing for EOF and winding up in a loop of failed reads that will never reach the end of the file (or reading past the end of the file by checking too soon).
AddingItem << ItemKey;
becomes
if (!(AddingItem << ItemKey))
{
//handle failure
}
Sometimes you will need better granularity to determine exactly what happened in order to properly handle the error. Check the state bits and possibly perror and target-specific
diagnostics as above.
Side Problem
Opening a file for simultaneous read and write with multiple fstreams is not recommended. The different streams will provide different buffered views of the same file resulting in instability.
Attempting to read and write the same file through a single ostream can be done, but it is exceptionally difficult to get right. The standard rule of thumb is read the file into memory and close the file, edit the memory, and the open the file, write the memory, close the file. Keep the in-memory copy of the file if possible so that you do not have to reread the file.
If you need to be certain a file was written correctly, write the file and then read it back, parse it, and verify that the information is correct. While verifying, do not allow the file to be written again. Don't try to multithread this.
Details
Here's a little example to show what went wrong and where.
#include <iostream>
#include <fstream>
int main()
{
std::ofstream AddingItem("test");
if (AddingItem.is_open()) // test file is open
{
std::cout << "open";
}
if (AddingItem) // test stream is writable
{
std::cout << " and writable\n";
}
else
{
std::cout << " and NOT writable\n";
}
AddingItem.open("test", std::ios::app);
if (AddingItem.is_open())
{
std::cout << "open";
}
if (AddingItem)
{
std::cout << " and writable\n";
}
else
{
std::cout << " and NOT writable\n";
}
}
Assuming the working directory is valid and the user has permissions to write to test, we will see that the program output is
open and writable
open and NOT writable
This shows that
std::ofstream AddingItem("test");
opened the file and that
AddingItem.open("test", std::ios::app);
left the file open, but put the stream in a non-writable error state to force you to deal with the potential logic error of trying to have two files open in the same stream at the same time. Basically it's saying, "I'm sorry Dave, I'm afraid I can't do that." without Undefined Behaviour or the full Hal 9000 bloodbath.
Unfortunately to get this message, you have to look at the correct error bits. In this case I looked at all of them with if (AddingItem).
As a complement of the already given question comments:
If you want to write data into a file, I do not understand why you have used a std::ifstream. Only std::ofstream is needed.
You can write data into a file this way:
const std::string file_path("../tmp_test/file_test.txt"); // path to the file
std::string content_to_write("Something\n"); // content to be written in the file
std::ofstream file_s(file_path, std::ios::app); // construct and open the ostream in appending mode
if(file_s) // if the stream is successfully open
{
file_s << content_to_write; // write data
file_s.close(); // close the file (or you can also let the file_s destructor do it for you at the end of the block)
}
else
std::cout << "Fail to open: " << file_path << std::endl; // write an error message
As you said being quite new to programming, I have explicitly commented each line to make it more understandable.
I hope it helps.
EDIT:
For more explanation, you tried to open the file 3 times (twice in writing mode and once in reading mode). This is the cause of your problems. You only need to open the file once in writing mode.
Morever, checking that the input stream is open will not tell you if the output stream is open too. Keep in mind that you open a file stream. If you want to check if it is properly open, you have to check it over the related object, not over another one.
This question already has answers here:
How to append text to a text file in C++?
(5 answers)
Closed 7 years ago.
I have created a code writing stuff in a .txt file and read from it. But if I close the program and start to write again, it deletes the old text and overwrites it with the new one.
Is there a way to not overwrite existed data?
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
void check() {
string text;
ifstream file;
file.open("test.txt");
getline(file, text);
if (text == "") {
cout << "There's no data in file" << endl;
} else {
cout << "File contains:" << endl;
cout << text << endl;
}
}
int main() {
check();
string text;
ofstream file;
file.open("test.txt");
cout << "Type some text" << endl;
getline(cin, text);
file << text;
return 0;
}
You need to open the file in 'append' mode like in the following example
#include <fstream>
int main() {
std::ofstream outfile;
outfile.open("yourfile.txt", std::ios_base::app);//std::ios_base::app
outfile << "your data";
return 0;
}
You can read here about fstream flagshttp://www.cplusplus.com/reference/fstream/fstream/open/
Keep in mind that in c++ there are several ways to open, save, and read text data to and from a file. It sounds like you opened with with a function (and its options) to always create a new file. One thing you could do is run your program and then close the program and use a text editor to open the file to verify whether the text you wrote to the file is actually there. Also take a look at the code that was provided by Evyatar. That example uses ofstream which allows options for read, write, and append. The "app" parameter tells the program to keep what is already in the file and append any new data that you add in the next run. When testing files where you are appending, be careful you don't end up with a huge file you did not intend to have so large.
In the code that you posted in your revised question, be sure to close the file in your check function and at the end of the program. It is possible to get things hung up if you don't. As a precaution, I usually close a file prior to opening it, just to be sure it is closed with no problems. This practice comes form my days programming in BASIC where it was an essential. If the program crashed, you couldn't open it again until you got it closed. Also, of course, close the file after you're done with it and before the end of the program. Then, when you open it in main, open with the append option.
Please, insert code for next time. If you open file in write mode, than is normal that every time you write to file, the content of file is changed. You need to use append mode.
Can anyone tell me what is wrong with this code? I always get not open.
#include <iostream>
#include <fstream>
using namespace std;
int main(){
fstream fs;
fs.open("fsfile2",ios::in|ios::out|ios::binary);
if(fs.is_open()){
fs.write("wow",sizeof("wow"));
char str[20];
fs.read((char*)str,sizeof(str));
cout<<str<<endl;}
else
cout<<"Not open\n";
return 0;
}
Try this code
fs.open("fsfile2", ios::app|ios::in|ios::out|ios::binary);
By using the open() like you are that file will not be created if that is your goal.
If you want to create a new file please look at: fstream won't create a file
If the file exists, you are not looking for it in the right path. Or change the file name to the full path or put the executable in the folder where the file is.
Hope this helps.
Probably, you do not have permissions to create files in the directory, where your executable is.
Solution:
Please add a file extension to the filename.
If it's a text file, it will be
"fsfile2.txt"
Then, I tried removing
ios::in
since the first process only writes to file, and by removing that, the file is created and "wow" is also written at it.
In order for these lines
fs.read((char*)str,sizeof(str));
cout<<str<<endl;
to work,
You need to close the stream after writing to it, then open the stream in read mode, then read the contents. Take note that closing the stream will save the edited file.
Additional:
You can also change
fs.write("wow",sizeof("wow"));
to
fs << "wow";
You can do the same when reading from file,
fs >> str;
You can also use the string class of C++, instead of char array so that the number of characters inside the file won't be your problem anymore.
#include <string>
string str;
Checking for EOF (end-of-file) is recommended since files are read line by line. Once you add a new line and add a character to the line, the code that doesn't loop until EOF will only read the first line of the file.
In order to solve this, it is recommended to loop until EOF is reached.
while(!fs.eof()) {
fs >> str;
cout << str << endl;
}
So here is the improved snippet:
#include <string>
fs.open("fsfile2.txt", ios::out); // ios::out for write only
if(fs.is_open()) {
// writes "wow" to file
fs << "wow";
// closes the file
fs.close();
// ios::in for read only
fs.open("fsfile2.txt", ios::in);
// better to define variable just before using it
string str;
// loops until end-of-file
while(!fs.eof()) {
// reads a line from file, stores it to str
fs >> str;
// shows str to screen
cout << str << endl;
}
}
*Note: I removed
ios::binary
Since your code is not dealing with binary files yet.
I tried these and it worked fine! Have a nice day!
fstream fs; does not create a new file for you.
You need to make sure that the file exists in your project directory.
On the other hand, if you were to use ofstream fs("file.txt"); it would create the file for you. Or use only ios::out when you open fstream fs, this will create the file for you.
I am stumped by this simple problem. I am reading a text file with C++:
std::ifstream stream;
stream.open(filename);
if (!stream)
cout << "Invalid stream" << endl;
And !stream is true but there seems to be nothing wrong with the text file. Under what circumstances can stream be false?
Note: is_open returns true
You have not provided enough information. Nevertheless, my psychic powers reveal:
filename is a relative path, and your current working directory is not what you think it is.
Inside your if clause, before printing via std::cout, add this:
perror(filename.c_str());
This code works for me:
#include<iostream>
#include<string>
#include<fstream>
using namespace std;
int main()
{
std::ifstream infilestream;
std::string line;
infilestream.open("test.txt");
while(infilestream)
{
std::getline(infilestream, line);
cout<<line<<"\n";
}
infilestream.close();
return(0);
}
chances are your file is inaccessible OR you might not have enough privileges to access the file.
Maybe its open somewhere else? Check if the path to the file is right.