Stopping and Starting read / copy on binary file - c++

So i'm attempting to copy a binary file up to a certain point...stop...perform some operations, then copy the remaining contents from the original binary out to my new binary. However when i perform my second read operation, my read buffer is empty. Can someone point out what I'm doing wrong here? Thanks so much...
ifstream fin;
fin.open(argv[1], ios::in | ios::binary);
ofstream fout("test.bin", ios::out | ios::binary);
int position = getPositionX();
fin.seekg(position);
streamoff initialCopyLength = fin.tellg();
char * readBuffer = new char[initialCopyLength];
fin.seekg(0, fin.beg);
fin.read(readBuffer, initialCopyLength);
fout.write(readBuffer, initialCopyLength);
///perform some operations, then copy out the rest of the binary
int currentPosition = fin.tellg();
fin.seekg(0, fin.end);
streamoff length = fin.tellg();
readBuffer = new char[length];
fin.read(readBuffer, length);
//write out last part of file
fout.write(readBuffer, length);
fin.close();
fout.close();

You seek to the end of the file with fin.seekg(0, fin.end); but you never seek back to the read position before you try to read() so you read nothing as you are at the end. You need another seekg call before you read() so you get back to where you were. Adding
fin.seekg(currentPosition, fin.beg);
will get you back to where you were.
You also have a mistake with
streamoff length = fin.tellg();
this is giving you the total file size. To get what is left you need
streamoff length = fin.tellg() - currentPosition;

Related

saving file with ofstream

I'm new to C++, I have an image named "test.jpg", i convert it to base64 and decode it again like this:
std::ifstream inputFile;
inputFile.open("test.jpg",std::ios::binary);
std::filebuf* pbuf = inputFile.rdbuf();
inputFile.seekg (0, ios::end);
int length = inputFile.tellg();
// allocate memory to contain file data
char* buffer=new char[length];
// get file data
pbuf->sgetn (buffer,length);
inputFile.close();
CBase64 base64;
string encodedData = base64.base64_encode((unsigned char*)buffer,length);
delete[] buffer;
string decodedData = base64.base64_decode(encodedData);
ofstream outPutFile;
outPutFile.open("test2.jpg",ios::binary | ios::out);
outPutFile.write(decodedData.c_str(), decodedData.length());
outPutFile.close();
the "test2.jpg" has exact same size as "test.jpg"(the original file) but, i can't open it.
i couldn't find what is the problem.
i got it working. i just replaced:
outPutFile.open("test2.jpg",ios::binary | ios::out);
with
outPutFile.open("test2.jpg", ios_base::out | ios_base::binary);
std::string path = "file.txt";
std::string cfgString = "data";
std::ofstream output(path.c_str(), ios_base::out | std::ios::binary);
if (output.is_open()) {
output.write(cfgString.data(), cfgString.length());
}
output.close();
Apparently, there is no superficial problem with your file writing logic even though there are some irregularities. The biggest problem is in your main logic.
The program seems to be simple program of copying a file. What you are doing is reading a file, converting its data to base64 string and then again decoding the data to std::string. Now one small problem. Conversion of base64 string cannot be successfully done into a null terminated ANSI string for obvious reasons that any 0 in decoded binary data will terminate the string prematurely. Secondly you are opening a file in binary mode to write but trying to write std::string in the file. But that doesn't matter as you data has already been corrupted in your previous operation.
To solve this, you can simply use file copying example as this or make sure you write only binary data with care to your output file which means read in binary from input file and write to output file the same buffer. No base64 encoding decoding is required.
it looks like you forgot to write
inputFile.seekg (0, ios::beg);
after getting file length. it means you try to read from the end of the file instead of its beginning.

How to write NULL character '\0' to a text file

I have to write some data to a text file, and at the end of each output I have to append a NULL terminating character '\0'. Currently this is what I have come up so far. It works well for some inputs, however for some it sometimes write the whole text file with garbage value. I there a better way to do this?? In my program I have to write some data, store its location on file and use that for some operations. the next write operation starts at address = address + 500;
long int address = get_address();
void write_to_file()
{
fstream pFILE ("my file.txt");
char * buffer = new char [500];
cin.getline(buffer,500);
pFILE.seekp(address);
pFILE << buffer;
pFILE.seekp(address + strlen(buffer));
pFILE << '\0';
address += 500;
}
To write a '\0' to file:
fstream output_file("output_file.txt", ios::binary);
output_file.put('\0');
The ios::binary prevents the compiler or OS from translating the '\0'.

Split a File and put it back together in c++

I want to copy a file by reading blocks of data, sending it and than put it back together again. Sending is not part of the problem, so I left it out in the code. It should work with any type of file and arbitrary piece_lengths.
This is just a pre-stage. In the end data block should not be chosen sequentially but at random. There could be some time between receiving another block of data.
I know the example just makes sense if size % piece_length != 0.
I'm getting crashed files of the same size as the original file at the other end.
Does anyone see the problem?
int main ()
{
string file = "path/test.txt"
string file2 = "path2/test.txt";
std::ifstream infile (file.c_str() ,std::ifstream::binary);
//get size of file
infile.seekg (0,infile.end);
long size = infile.tellg();
infile.seekg (0);
size_t piece_length = 5;
for (int i = 0; i < ((size / piece_length) + 1); i++)
{
if ( i != (size / piece_length))
{
std::ifstream infile (file.c_str() ,std::ifstream::binary);
infile.seekg((i * piece_length) , infile.beg);
char* buffer = new char[piece_length];
infile.read(buffer, piece_length);
infile.close();
std::ofstream outfile (file2.c_str() ,std::ofstream::binary);
outfile.seekp((i * piece_length), outfile.beg);
outfile.write(buffer, piece_length);
outfile.close();
}
else
{
std::ifstream infile (file.c_str() ,std::ifstream::binary);
infile.seekg((i * piece_length) , infile.beg);
char* buffer = new char[size % piece_length];
infile.read(buffer, size % piece_length);
infile.close();
std::ofstream outfile (file2.c_str() ,std::ofstream::binary);
outfile.seekp((i * piece_length), outfile.beg);
outfile.write(buffer, size % piece_length);
outfile.close();
}
}
return 0;
}
To answer your specific question, you need to open outfile with ios::in | ios::out in the flags, otherwise it defaults to write-only mode and destroys what was already in the file. See this answer for more details: Write to the middle of an existing binary file c++
You may want to consider the following though:
If you are just writing parts to the end of the file, just use ios::app (append). Don't even need to seek.
You don't need to keep reopening infile or even outfile, just reuse them.
You can also reuse buffer. Please remember to delete them, or better yet use a std::vector.

Can Not Open File in Loop C++

I have a c++ application which have the following code:
for (int i = 0; i < ALL_EPID_CERTS_LENGTH; i++)
{
std::ifstream file(;
file.open(path.append(ALL_EPID_CERTS_1_0[i]), std::ios::in | std::ios::binary);
if(file.is_open())
{
// get the length of the file
file.seekg(0, ios::end);
size_t fileSize = file.tellg();
file.seekg(0, ios::beg);
// create a vector to hold all the bytes in the file
vector<byte> data(fileSize, 0);
// read the file
file.read(reinterpret_cast<char*>(&data[0]), fileSize);
byte *tempCerts = new byte[data.size()+1];
memset(tempCerts,0,fileSize+1);
std::copy(data.begin(), data.begin()+(data.size()), tempCerts);
// !!!!check if NULL and place for NULL are needed
for (int j = 0; j < data.size(); j++)
{
list.push_back(tempCerts[j]);
}
file.close();
}
}
In the first iteration the loop does the expected, but since the second one - file.is_open() returns false.
All the files are existing.
Sould you explain me please what is wrong???
You do path.append - what is path? What do you expect it to be after first iteration - is it ok that ALL_EPID_CERTS_1_0[1] is appended to ALL_EPID_CERTS_1_0[0]?
You may need to call infile.clear(); to clear the state bits after closing the stream, otherwise you can't open a new file with the same stream.
Also: Are you sure you need to append to the path at every iteration? Output your path variable after every append call and check if the paths are correct. I expect that at the second iteration the path string will look something like this: "c:/some/path/file1.txtfile2.txt"
In cases like this I would use a stringstream or sprintf to generate the path, and make sure not to change the path variable.

C++: Everytime I read in by fstream I got 1 extra character at the end

Everytime I read in by fstream I got 1 extra character at the end, How can I avoid this?
EDIT:
ifstream readfile(inputFile);
ofstream writefile(outputFile);
char c;
while(!readfile.eof()){
readfile >> c;
//c = shiftChar(c, RIGHT, shift);
writefile << c;
}
readfile.close();
writefile.close();
This typically results from testing for the end of file incorrectly. You normally want to do something like:
while (infile>>variable) ...
or:
while (std::getline(infile, whatever)) ...
but NOT:
while (infile.good()) ...
or:
while (!infile.eof()) ...
The first two do a read, check whether it failed, and if so exit the loop. The latter two attempt a read, process what's now in the variable, and then exit the loop on the next iteration if the previous attempt failed. On the last iteration, what's in the variable after the failed read will normally be whatever was in it previously, so loops like either of the second two will typically appear to process the last item in the file twice.
To copy one file to another easily, consider using something like this:
// open the files:
ifstream readfile(inputFile);
ofstream writefile(outputFile);
// do the copy:
writefile << readfile.rdbuf();
This works well for small files, but can slow down substantially for a larger file. In such a case, you typically want to use a loop, reading from one file and writeing to the other. This also has possibilities for subtle errors as well. One way that's been tested and generally work reasonably well looks like this:
std::ifstream input(in_filename, std::ios::binary);
std::ofstream output(out_filename, std::ios::binary);
const size_t buffer_size = 512 * 1024;
char buffer[buffer_size];
std::size_t read_size;
while (input.read(buffer, buffer_size), (read_size = input.gcount()) > 0)
output.write(buffer, input.gcount());
Based on the code, it appears what you're trying to do is copy the contents of one file to another?
If so, I'd try something like this:
ifstream fin(inputFile, ios::binary);
fin.seekg(0, ios::end);
long fileSize = fin.tellg();
fin.seekg(0, ios::beg);
char *pBuff = new char[fileSize];
fin.read(pBuff, fileSize);
fin.close();
ofstream fout(outputFile, ios::binary)
fout.write(pBuff, fileSize);
fout.close;
delete [] pBuff;