So the read is working for Windows but it's not working for Linux. In GDB the ulTop variable is shown as 0 even though it should be 512 (the value of Constants::INITIAL_READ_SIZE).
std::basic_ifstream<unsignedchar> file (szFileName, std::ios::in|std::ios::binary);
if (!file)
{
if (m_iDisplayType != ConsoleOutput::NO_DISPLAY)
{
std::cout << "There was a problem opening the file." << std::endl;
std::cerr << "Error: " << strerror(errno) << std::endl;
}
returnfalse;
}
long lFileSize;
// Grab the file size
file.seekg( 0, std::ios::end );
lFileSize = file.tellg();
file.seekg( 0, std::ios::beg );
unsignedlong ulTop = 0; // how much of the file is in the pszBuffer
// Do an initial read of the file, to get some data in our pszBuffer, ready for processing...
file.read( &m_szContents[ ulTop ], Constants::INITIAL_READ_SIZE );
ulTop += file.gcount();
memcpy(m_szPcapHeader, m_szContents, Constants::PCAP_HEADER_SIZE);
Weird thing is it prints out the correct file size, but ulTop after the increment from file.gcount() is 0 - in Windows it's correctly 512. I really can't figure out what's happening. Any ideas?
Thanks
PS: m_szContents is an unsigned char m_szContents [Constants::LARGE_BUFFER_SIZE] and ulTop is an unsigned long.
What do you expect std::basic_ifstream<unsignedchar> to do? There are no traits or facets to support such a type. It does not even compile with clang/libc++.
Use std::ifstream file(szFileName, std::ios::binary);.
The char trait is not explicitly specified so std::char_traits<unsigned char> will be used in this case. As far as I can see the C++ standard only talks about specializations of std::char_traits for the types char, char16_t, char32_t and wchar_t so I guess it's not clear what will happen if you use another type.
Can't you use a stream of char instead of unsigned char? You could still read the data into an array of unsigned char by simply casting the pointer before passing it to the read function.
it compiles for me on Windows and on Linux as well... Why would it not work?
Because when you write std::basic_ifstream<unsignedchar> you're actually writing std::basic_ifstream<unsignedchar, std::char_traits<unsignedchar>>, where std::char_traits<unsignedchar> does not exist.
In addition, when executing the actual I/O (istream::read in your case), the stream will be converting between the internal character type (the unsignedchar you requested) and the external character type (which is always char), so it will attempt to use the current locale's facet std::codecvt< unsignedchar, char, std::mbstate_t>, which also doesn't exist.
(as far as I recall exploring this topic in the past, that last one is the direct reason you're getting a zero in GNU libstdc++.. oh, here it is: http://stackoverflow.com/a/19254009/273767 )
I find that it's never good to assume that a piece of code works, no matter how certain you are that it can't possibly be wrong. Believe what the output is telling you. In this case, file.gcount() is zero. That's a very good indication that the read() is failing. You have to swallow that pride and check the return value.
I once had a colleague come to me with a problem. Something along the lines of
1 2 3 4 5
a = 1;
// Lots of intervening code
if (a == 1) {
doSomething();
}
Line 4 wasn't executing and he just couldn't figure out why. After convincing me that a could not change between lines 1 and 4, I told him that line 1 was not being executed. He told me that couldn't possibly be true. Well days later he sheepishly admitted that I was right.