Read binary data from a binary file - c++

I am writing a structure into a file using the following line:
std::fstream snif::fileHandler;
fileHandler.write(reinterpret_cast<char*>(rawData), sizeof(rawDataStruct));
where rawdataStruct is:
typedef struct _rawData rawDataStruct;
now after writing the structures into the file, I am reading the structure from the beginning of the binary file using:
std::cout << "going for print data read from file\n";
snif::fileHandler.seekg(0); //, std::ios::beg);
snif::fileHandler.read(reinterpret_cast<char*>(rawData), sizeof(rawDataStruct));
if (snif::fileHandler.fail()) {
std::cerr << "reading error\n";
exit(0);
}
std::cout << "PSH flag = " << rawData->tcpFlag.PSH << std::endl
<< "source port " << rawData->sourcePort << std::endl
<< "destination port " << rawData->destinationPort << std::endl
<< " sequence number " << rawData->sequenceNumber << std::endl
<< " Acknowledge number " << rawData->acknowledgeNumber << std::endl
<< " acknowledge flag " << rawData->tcpFlag.ACK << std::endl
<< " SYN flag " << rawData->tcpFlag.SYN << std::endl
<< "FIN flag " << rawData->tcpFlag.FIN << std::endl;
but if I check my standard output, the last line geting printed is:
"going for print data read from file";

There is no code showing it, but what mode is the file opened? Hopefully it is configured for binary. To see the available options, review std::basic_fstream and std::ios_base::openmode. I suggest to make sure that the following open modes are set:
ios::binary | ios::out | ios::in | ios::trunc
Depending on what purpose is happening, ios::trunc (truncate) may have to be replaced by ios::app (append).
While doing some basic testing, it has been discovered on my C++11 compliant compiler that the
fileHandler.write(reinterpret_cast<char*>(rawData), sizeof(rawDataStruct));
has a potential problem that is easily solved by adding the & operator in front of the rawData like this:
fileHandler.write(reinterpret_cast<char*>(&rawData), sizeof(rawDataStruct));
The compiler should have given a warning, but that is contingent on the compiler version, and whether the -Wall option or better is used. This may explain how the screen output seemingly stops at the
"going for print data read from file"
message. The read function also needs the & operator in front of rawData:
snif::fileHandler.read(reinterpret_cast<char*>(&rawData), sizeof(rawDataStruct));
Perhaps a run-time exception from the reinterpret_cast<> operator is being thrown that is not being caught. It is difficult to know until the system and compiler are documented.
Additionally, if rawData is declared as a pointer, then a better variable name is pRawData, as well as posting more of the code. For example, if the pRawData is never pointing to a valid instance of the rawDataStruct, then unpredictable things will occur.

Related

Repeatedly write and read to/from QBuffer via QTextStream

I am trying to repeatedly write and read to/from a QBuffer object via QTextStream. First I construct both objects:
QBuffer b;
b.open(QIODevice::ReadWrite);
QTextStream s(&b);
// Setup text stream here
Then I write three different portions of information and read them back:
s << "Test" << 666 << endl << flush;
s.seek(0);
qDebug() << s.readAll();
s << "X" << endl << flush;
s.seek(0);
qDebug() << s.readAll();
s << "Test" << 777 << endl << flush;
s.seek(0);
qDebug() << s.readAll();
Of course I do not get the data portion I wrote immediately before, but the cumulated data:
"Test666\n"
"Test666\nX\n"
"Test666\nX\nTest777\n"
I could do adaptive seek calls to get the correct data but I do not want the QBuffer to grow infinitely.
I tried a s.reset() call between writes but the result is the same. Calling reset() or open()/close() directly on the buffer gives a crippled result (which is expected since the stream is bypassed):
"Test666\n"
"X\nst666\n"
"Test777\n"
I could probably build a new buffer for every cycle, open it and attach it to the stream but that is slow.
Is there a proper and fast solution for this use case?
You can access QBuffer's internal QByteArray storage directly with QBuffer::buffer() and then delete everything with QByteArray::clear(). Then manually seek() back to the start.
QBuffer b;
b.open(QIODevice::ReadWrite);
QTextStream s(&b);
s << "Test" << 666 << endl << flush;
s.seek(0);
qDebug() << s.readAll();
b.buffer().clear();
s.seek(0);
s << "X" << endl << flush;
s.seek(0);
qDebug() << s.readAll();
b.buffer().clear();
s.seek(0);
s << "Test" << 777 << endl << flush;
s.seek(0);
qDebug() << s.readAll();
"Test666\n"
"X\n"
"Test777\n"
QTextStream also has a constructor which takes a QByteArray directly and creates the QBuffer automatically, which may save a little code in this case.

tellg() returns -1 only for small files

I ran across a peculiar issue. Let's say I'm reading a file like this:
std::ifstream in("file.txt", std::ios::binary);
std::string text;
in.seekg(0, std::ios::end);
text.resize(in.tellg());
in.seekg(0, std::ios::beg);
in.read(&text[0], text.size());
The problem arises when the file contains less than 4 characters, i.e. "ab" or "abc", but works in other cases as intended, i.e. "abcd" or larger.
Why is tellg returning -1 for such a situation (ultimately causing my string to throw a std::length_error)?
Additional info:
I'm working with MSVC 15.5.3 (if not the latest, one of the more contemporary). Reproduced with GCC 5.1 as well.
This error doesn't occur with the equivalent C-style:
FILE* f = fopen("text.txt", "rb");
fseek(f, 0, SEEK_END);
long fsize = ftell(f);
EDIT:
failbit is set right before the first call to seekg, meaning opening the file failed? Why would that be the case for a file of less than 3 bytes...
After a few comments, it's clear that the ifstream constructor itself is failing in some way, as failbit is set even before the seekg call.
Since pretty much all I/O operation first construct a sentry object before proceeding, that will be why your operations are failing.
So I have a few suggestions.
First, use the full path name to your file just to ensure there's no possibility you're running it in a directory other than where the input file is.
Second, try the following complete program which works under g++ 5.4(a) to see if it exhibits the same problem (your code, while indicative, was not really complete).
#include <iostream>
#include <fstream>
int main() {
std::ifstream in("/full/path/to/file.txt", std::ios::binary);
std::cout << "after open, good=" << in.good() << ", bad=" << in.bad()
<< ", fail=" << in.fail() << ", eof=" << in.eof() << std::endl;
std::cout << "seekg returns " << in.seekg(0, std::ios::end) << std::endl;
std::cout << "after seek, good=" << in.good() << ", bad=" << in.bad()
<< ", fail=" << in.fail() << ", eof=" << in.eof() << std::endl;
std::cout << "tellg returns " << in.tellg() << std::endl;
std::cout << "after tell, good=" << in.good() << ", bad=" << in.bad()
<< ", fail=" << in.fail() << ", eof=" << in.eof() << std::endl;
}
Try this both with a two-byte and ten-byte file.
If none of that gives you any joy, Microsoft and/or GNU should be made aware of the issue. The former can be done here, the latter here.
Just for completeness, the only possibility that originally came to my mind was that the file, although three bytes long, is invalid in some way. This depends on the actual content so, if it is just abc, you can safely ignore this.
What I was thinking is something along the lines of a Unicode file with two byte BOM and the first byte of a multi-byte Unicode code point (e.g., UTF-16), or the first three bytes of of UTF-8 four-byte code point.
However, that seems incredibly unlikely if you're opening it in binary mode, so you can probably safely ignore it.
(a) For what it's worth, the only way I could get this to have failbit set after the open was to delete the file. Even using an empty file did not exhibit the problem you're describing.

ofstream/fstream simply will not work, no matter what solution is tried

Okay guys, I've tried everything I can think of. I'm passing in a file name into this function. A little context: hash_table is an already initialized and filled vector with key pairs, and the 'value' part of the pair is a Linked List that has the field "bucket_size". When I use cout to check if these fields are actually being accessed, they are; even the debugger lists them as being filed into the output stream. I have flush() and close() in there, but it doesn't write anything to the file. Returns true, indicating no errors in the stream. Anyone have nay ideas?
string line;
std::ofstream ofs;
if(ofs.is_open())
ofs.close();
ofs.open(filename);
if (ofs.is_open())
{
cout << "File Opened" << endl;
for (double i = 0; i < hash_table.capacity(); ++i)
{
ofs << "Bucket Number " << i;
if (hash_table[i].value != NULL)
ofs << " Bucket Size: " << hash_table[i].value->bucket_size << endl;
else
ofs << " Bucket Size: 0" << endl;
ofs.flush();
}
cout << "closing file stream" << endl;
ofs.flush();
ofs.close();
if (ofs.good())
return true;
else
return false;
}
else
{
cout << "File not opened" << endl;
return false;
}
}
You're almost certainly examining the wrong file. Remember that relative paths are relative to the working directory of the process, which is not necessarily the same as where the executable lives on disk.
I compiled and ran it by the console and now it works, with no edits made. It seems my IDE doesn't like something in the code. Regardless, thank you everyone for the response.s

File not saving, or not

I cannot seem to figure out why, during the while loop at the bottom,
std::cout << line;
does not print anything.
I believe that the test.txt file is not actually being written to because when I open test.txt in my folder, its empty. Any thoughts?
void Ticket::WriteTicket()
{
std::string ticketInput;
std::ofstream ticketFile("test.txt");
ticketFile.open("test.txt");
std::cout << "Please Enter Ticket Information: " << std::endl;
getline(std::cin, ticketInput);
std::cout << ticketInput << std::endl; //does print out the line
ticketFile << ticketInput;
ticketFile.close();
//here for testing only
std::string line;
std::ifstream ticketRead("test.txt");
while(getline(ticketRead, line));
{
std::cout << "something here?: " << line; // there is nothing here when it outputs
}
}
EDIT (SOLUTION):
After using some of the information that was given above, mainly from Basile Starynkevitch (I put this here because I cannot upvote yet), I was able to get the code to work!
I also did some research in my book and copied a similar program's style. Aka where to put what part of the code, and then the input worked. I continued on with the output and the key part was the std::ifstream::in in the opening of the file for output.
void Ticket::WriteTicket()
{
std::string ticketInput;
std::cout << "Please Enter Ticket Information: " << std::endl;
getline(std::cin, ticketInput);
std::ofstream ticketFile("Ticket.txt");
ticketFile << ticketInput << std::endl;
ticketFile.close();
//here for testing
std::ifstream ticketRead;
ticketRead.open("Ticket.txt", std::ifstream::in);
std::string line;
while(getline(ticketRead, line))
{
std::cout << line << std::endl;
}
}
Thank you for the help everyone!
You need to flush the output buffer.
ticketFile << ticketInput;
should be
ticketFile << ticketInput << std::endl;
std::endl flushes the output buffer.See std::flush if you don't want the new line.
C++ I/O is buffered. At least code
std::cout << "something here?: " << line << std::flush;
but in your case
std::cout << "something here?: " << line << std::endl;
would be better.
Also
std::ofstream ticketFile("test.txt")
should probably be
std::ofstream ticketFile("test.txt", std::ios_base::out);
I strongly suggest taking some hours to read more about C++ libraries before coding. Check every function or class that you are using. Of course, you also need to std::flush on ticketFile.
Maybe the file need to be openned in write mode.
Try this
std::ofstream ticketFile("test.txt","w");

How to read and write input file and output file

I am trying to run the following program:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ifstream inFile;
ofstream outFile;
double first=1.49, second=2.59, third=3.69, fourth=4.79;
inFile.open("prices.txt");
char response;
if(!inFile.fail())
{
cout << "A file by the name prices.txt exists.\n" << "Do you want to continue and overwrite it\n" << " with the new data (y or n);"; cin >> response;
if(tolower(response) == 'n')
{
cout << "The existing file will not be overwritten." << endl;
return -1;
}
}
outFile.open("prices.txt");
if (inFile.fail())
{
cout << "\n The file does not exist and can not be opened" << endl;
cout << "The file has been successfully opened for output." << endl;
outFile << first << "\n" << second << "\n" << fourth << "\n" << endl;
outFile.close();
exit(1);
cout << "The file has been successfully opened for output. " << endl;
outFile << first << "\n" << second << "\n" << third << "\n" << fourth << endl;
outFile.close();
return 0;
}
}
Yet this program will not write the values to the prices.txt file. If you run the program once it says the file does not exist. Running it a second time says the file is already there and if you want to overwrite it. The thing is searching my Mac I cannot find this file anywhere.
Any ideas what I am doing wrong with running it in Xcode? A friend runs the exact same code in Visual Studio 2008 and it works. Any help is appreciated.
You need to set the working directory for the executable since you are assuming that your data files are in the current working directory. In Xcode 3.x you set this in the first tab of Get Info for the executable. In Xcode 4.x it has been moved, but the principle is the same.
Alternatively you can change your data file paths (e.g. make them absolute) so that you do not make assumptions about the current working directory.
You may not have permission to write into the directory that you are trying to save the file too.
Also, there is an error in your program and I am sure if it is there for debugging reasons. You have
outFile.close();
exit(1);
But then shortly there after you try to write to the file, then close it again.