reading and writing to the same file c++ - c++

I have small app which at begin will read text file (with serialized objects) in which im storing some obejcts (im doing it by overloading << and >> operators). This text file has to be updated each time new object is created:
fstream m_haystackMapFile;
m_haystackMapfile.open(haystackMapFile, std::ios::binary | std::ios::in | std::ios::out);
first i do read:
WHaystackFile f;
m_haystackMapfile.seekg(0, std::ios::beg);
std::copy(std::istream_iterator<WHaystackFile>(m_haystackMapfile), std::istream_iterator<WHaystackFile>(), std::back_inserter(m_haystackFiles));
std::cout << "reading input file, no of files: " << m_haystackFiles.size() << std::endl;
for(std::vector<WHaystackFile>::iterator it = m_haystackFiles.begin(); it != m_haystackFiles.end(); ++it){
f = *it;
std::cout << "key: " << f.getKey() << " cookie: " << f.getCookie() << " path: " << f.getPath() << " size: " << f.getSize()<< std::endl;
}
then after creating new object I do write:
void WhaystackMap::addEntry(WHaystackFile &f){
std::cout << "adding entry to index file" << std::endl;
m_haystackMapfile.seekp(std::ios::end);
m_haystackMapfile << f;
std::cout << f;
}
unfortunatelly file in which I want to write is never updated and it always has size 0. Maybe im messing up something, but after googling i can't find answer how to using fstream I can read and write to same file...
any help is welcomed :)
regards
J.

It's very important to check success of I/O operations. For example, if seekp is unable to seek to the desired position, it will set the failbit, and then all subsequent writes will fail. Or, as #Christophe points out, if you read the file to the end, you will cause the eofbit to be set. Unless that bit is cleared, the next I/O operation (even seekp) will fail.
Even if the eofbit had been reset, the seek probably would fail because the call should have been m_haystackMapfile.seekp(0, std::ios::end);.

The problem is the wrong usage of seekp():
you use it with one single parameter ios::end in m_haystackMapfile.seekp(std::ios::end)
but single parameter only works for absolute positionning. So ios::end is converted into an integer and will locate you at an unexpected place (on my implementation it's 2).
you have to use m_haystackMapfile.seekp(0, std::ios::end) instead
There is another problem: the istream_iterator<>() that you use in your std::copy() will read the stream until it reaches its end. So the failbit and eofbit will be set.
Connsequently, no stream operation will succed until you clear the flags: m_haystackMapfile.clear();

Related

the characters in a c++ string are being ignored

I'm trying to write to a hid device using signal11's hidapi (here).
In my troubleshooting, I've noticed that part of a string isn't being displayed to the console.
Here is a sample of my code
//device is a hid device and is assigned to in another part of the program.
//dataBuffer is a struct with only a char array called "buffer" and an int which is the size of the array called "size"
void DeviceCommands::Write(hid_device* device, dataBuffer* buf)
{
std::cout << "Attempting write >> buffer...\n";
buf->buffer[0] = 0;
std::cout << "Written to buffer...\n" << "writing buffer to device\n";
int res = hid_write(device, buf->buffer, sizeof(buf->buffer));
std::cout << "Write success: " + '\n';
std::cout << "Write complete\n";
}
I'm expecting for the console to return the following:
Attempting write >> buffer...
Written to buffer...
writing buffer to device
Write success: (0 if the write succeeds, -1 if it fails)
Write complete
But instead, this happens:
Attempting write >> buffer...
Written to buffer...
writing buffer to device
ess: Write complete
The "Write succ", result, and the line break are missing, I'm somewhat new to c++ but I have experience with c#. I'm just confused and some help would be much appreciated, thanks in advance and ask if you need more information!
This line:
std::cout << "Write success: " + '\n';
will print the string "Write success: " with an offset of 10 characters, which is the ascii value of \n. Hence you see ess on the screen.
You probably want:
std::cout << "Write success: " << res << "\n";
assuming res returns 0 or -1 as needed.
Do not 'add' a character to a string. It will not do what you expect.
Here you are thinking you are adding the line feed character to your string "Write success" when in fact you are telling the compiler to take your constant string and only stream from the 10th character. Remember a constant string here is just an array of characters and the single character '\n' is converted to the number 10.
You are also missing the result out of the streaming.
So your second to last line should read:
std::cout << "Write success: " << res << std::endl;

Need to convert char* to string or other type in order to run hash on it

I need to read in an mp3 file so that I can run the hash(). I do not need to parse the mp3 tag data out of this so I can just read the whole thing all together.
Currently I am using ifstream() to open the file in binary mode. I then get the size of the file, allocate enough space with a char* and read it all at once.
I know that when I run cout on this data I can only see "ID3 and some gibberish." I opened the mp3 file up in a hex editor and ID3 and the gibberish was what was at the beginning of the file. The next binary data I believe is being interpreted as end of line/string and does not print.
This is okay because I don't need to print it. I need to get the data in a format that I can run the Hash function on. Any ideas on a type I can convert it to that will not interpret the end of the file being a couple bytes in?
Here is code of what I have so far.
bool Sender::openSoundFile(){
streampos size;
soundSampleStream.open(soundFilePath.c_str(), ios::in|ios::binary|ios::ate);
if(!soundSampleStream.is_open()){
return false;
}
size = soundSampleStream.tellg();
cout << "Size of MP3: " << size << endl;
soundFileInMemory = new char [size];
soundSampleStream.seekg (0, ios::beg);
soundSampleStream.read(soundFileInMemory, size);
cout << "Error is: " << strerror(errno) << endl;
cout << "gcount: " << soundSampleStream.gcount() << endl;
soundSampleStream.close();
cout << soundFileInMemory << endl;
return true;
}
I get no error on reading the file and gcount() comes back with the correct numbers of bytes for the file.
Edit 1:
To add some more on this. The hash() seems to hash the char* and not the data being pointed at because the hash value changes on different program runs. This is why I need to convert to some other thing. I also don't think that a vector is supported by the c++11 hash().
std::string has a constructor that takes a char * and a size_t. See the fourth item in http://en.cppreference.com/w/cpp/string/basic_string/basic_string.
std::string file_contents(soundFileInMemory, size);
That will convert your char array to a string.

unexpected behavior when read a character from istringstream

I have a question on the stream behavior, see the following example. What I was expecting is the ss_char and ss_int will be eof state, but just the ss_int will be eof state.
My question is, why isn't ss_char eof state?
Can't I use the operator>>, only the istringstream::get() function, but then why read the value successfully?
Output:
char value: a
int value: 42
ss_char eof: false // why false?
ss_int eof: true
Sorry for my poor English. I’m working on improving my English.
#include <iostream>
#include <sstream>
int main(int /*argc*/, char const * /*argv*/[])
{
char c;
int num;
std::istringstream ss_int("42");
std::istringstream ss_char("a");
if (ss_char >> c)
{
std::cout << "char value: " << c << std::endl;
}
else
{
std::cout << "cannot read char" << std::endl;
}
if (ss_int >> num)
{
std::cout << "int value: " << num << std::endl;
}
else
{
std::cout << "cannot read int" << std::endl;
}
std::cout << std::endl;
std::cout << "ss_char eof: " << std::boolalpha << ss_char.eof() << std::endl; // why false
std::cout << "ss_int eof: " << std::boolalpha << ss_int.eof() << std::endl;
return 0;
}
CppReference says: "This function only reports the stream state as set by the most recent I/O operation, it does not examine the associated data source. For example, if the most recent I/O was a get(), which returned the last byte of a file, eof() returns false. The next get() fails to read anything and sets the eofbit. Only then eof() returns true."
oefbit will turn true when a read operation attempts to read beyond end of file, but not when it reads exactly to the end of file without trying to go further. When you read the char, it knows it should read a single byte, so this read operation is ok, the read position advance 1 byte, goes to the end, but let say the the stream still haven't noticed that it is indeed the end, it will if you try to read something else. When you read an integer, it tries to read beyond 42 because the length of the integer is not clear, it could have been 42901, so it has to read until it sees an space, and end of line, or eventually the end of the file/stream if there's nothing else to read.
And the result of the operator >> is the stream itself. When it is converted to void* (or bool, depends on c++11 or previous) it works as !fail(), so it tells you if the read or write operation was ok, regardless of whether it reached the end of file (next read operation will fail if it is now at the end).
The EOF condition doesn't actually occur until you try to read past the end of the stream.
In the char case you read exactly one character, the only one available. You don't try to read past the end because there is no need to.
Extracting an int on the other hand attempts to consume as many digits as possible. It reads the 4 and the 2, and then it tries to read again to see if there is another digit to consume, it does attempt to read past the end in this case. It notices that the input came to an end and so finishes the conversion of 42.
when extracting chars, it will pull a single character at a time and skip white spaces on consecutive calls.
when extracting int, the parser attempts to pull as many characters out to form the number. this causes the integer extraction to hit the eof in your test case.

Can not read enough data from a file when the file has enough data c++

I have this code in c++ ( it is after I did some tests to see why I can not read enough data from file, so it is not final code and I am looking to find why I am getting this result)
size_t readSize=629312;
_rawImageFile.seekg(0,ifstream::end);
size_t s=_rawImageFile.tellg();
char *buffer=(char*) malloc(readSize);
_rawImageFile.seekg(0);
int p=_rawImageFile.tellg();
_rawImageFile.read(buffer,readSize);
size_t extracted = _rawImageFile.gcount();
cout << "s="<< s <<endl;
cout << "p="<< p <<endl;
cout << "readsize="<< readSize<<endl;
cout << "extracted="<< extracted <<endl;
cout << "eof ="<< _rawImageFile.eofbit<<endl;
cout << "fail="<< _rawImageFile.failbit <<endl;
The output is as follow:
s=3493940224
p=0
readsize=629312
extracted=2085
eof =1
fail=2
As you can see the file size is 3493940224 and I am at the start of file (p=0) and I am trying to read 629312 bytes, but I can only read 2085?
What is the problem with this code? I did open this file in other methods and read some data out of it, but am using seekg to move pointer to the beginning of file.
The file was opened as binary.
edit 1
To find a solution, I put all code inside a function and here is it:
_config=config;
ifstream t_rawImageFile;
t_rawImageFile.open(rawImageFileName,std::ifstream::in || std::ios::binary );
t_rawImageFile.seekg (0);
size_t readSize=629312;
t_rawImageFile.seekg(0,ifstream::end);
size_t s=t_rawImageFile.tellg();
char *buffer=(char*) malloc(readSize);
t_rawImageFile.seekg(0);
size_t p=t_rawImageFile.tellg();
t_rawImageFile.read(buffer,readSize);
size_t x=t_rawImageFile.tellg();
size_t extracted = t_rawImageFile.gcount();
cout << "s="<< s <<endl;
cout << "p="<< p <<endl;
cout << "x="<< x <<endl;
cout << "readsize="<< readSize<<endl;
cout << "extracted="<< extracted <<endl;
cout << "eof ="<< t_rawImageFile.eof()<<endl;
cout << "fail="<< t_rawImageFile.fail() <<endl;
and the result is:
s=3493940224
p=0
x=4294967295
readsize=629312
extracted=2085
eof =1
fail=1
Interestingly, after read the file pointer moves to a very big value. is it possible that since the file size is very big, the application fails?
edit 2
Tested the same code with another file. the result is as follow:
s=2993007872
p=0
x=4294967295
readsize=629312
extracted=1859
eof =1
fail=1
What I can read from this test is that:
after read the file pointer moves to a big number which is always the same. The amount that it reads depend on file (!).
edit 3
After changing the size_t to fstream::pos_type the result is as follow:
s=2993007872
p=0
x=-1
readsize=629312
extracted=1859
eof =1
fail=1
Why file position goes to -1 after a read?
t_rawImageFile.open(rawImageFileName, std::ifstream::in || std::ios::binary );
...does not open the file in binary mode. Since || is the lazy or operator and std::ifstream::in is non zero, the whole expression has the value 1.
t_rawImageFile.open(rawImageFileName, std::ifstream::in | std::ios::binary );
...will surely work better.
You don't show the part where your file is being opened, but I'm pretty sure it is missing ios::binary to make sure the C runtime code doesn't interpret CTRL-Z (or CTRL-D) as end of file.
Change this line:
t_rawImageFile.open(rawImageFileName,std::ifstream::in || std::ios::binary );
into this:
t_rawImageFile.open(rawImageFileName,std::ifstream::in | std::ios::binary );

Why is 'source_stringstream' is empty after 'dest_stringstream << source_stringstream.rdbuf()'? Why eofbit is not set?

1) I would like to send information from one stringstream to several another stringstreams. But in the exapmle below it seems that after << in_contents.rdbuf();, in_contests is empty. What operation should I use in order to I avoid it?
2)Why eofbit and failbit is not set in in_contents after abovementioned operation as may be in the case std::getline(in_contents, word)? I've moved an entire buffer, but ...
Thank you!
std::stringstream in_contents("gg");
std::stringstream out_contents1;
std::stringstream out_contents2;
out_contents1 << in_contents.rdbuf(); //make in_contents buffer empty?
in_contents.seekg(0);
out_contents2 << in_contents.rdbuf();//out_contents2 has nothing
cout << endl << in_contents.eof();//zero?
cout << endl << in_contents.fail();//zero?
//std::getline(in_contents, word);//failbit=1; eofbit=1?