The Shed is going Social! Join us on FaceBook and Twitter and chime in on the conversation.
|
 |
|
Dev Shed Forums
> Programming Languages
> C Programming
|
C++ binary file reader
Discuss C++ binary file reader in the C Programming forum on Dev Shed. C++ binary file reader C programming forum discussing all C derivatives, including C#, C++, Object-C, and even plain old vanilla C. These languages are low level languages, and used on projects such as device drivers, compilers, and even whole computer operating systems.
|
|
 |
|
|
|
|

Dev Shed Forums Sponsor:
|
|
|

October 17th, 2012, 04:54 PM
|
 |
The bad and the ugly...
|
|
Join Date: Jan 2007
Location: Oz... No??? Neverland then?
Posts: 142
Time spent in forums: 1 Day 6 h 21 m 2 sec
Reputation Power: 0
|
|
|
C++ binary file reader
Hello again dev-shed users,
I was tasked with writing a binary file viewer for homework. I've got my code running, and everything works great... but it seems to read/print out past the end of the file.
Basically, it displays 20 lines at a time, with 16 bits of hex followed by 16 bits of ASCII. After the 20 lines have printed, it pauses and waits for you to hit enter before printing the following 20 lines. Once it reaches the end of the file it quits.
Code:
#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>
#include <ios>
//
//function prototype
void PressEnterToContinue();
using namespace std;
void main(int argc, char *argv[])
{
int n = 0; //used for prompting input file name
int r;
int x = 0, m = 0, a = 0;
ifstream filename; //start filestream
int size; //for file size
char *file_buffer; //buffer for storing file
//if user calls program from cmd prompt incorrectly or with "/?"
if((argc < 2) || (strcmp(argv[1],"/?") == 0))
{
cout << "This program reads a file and prints each character as a hexadecimal\n";
cout << "\n";
cout << "Usage: hw5 [input filename]\n";
exit(0);
}
//
//prompt user for file name and continue to do so until a valid file name is given
do
{
filename.open(argv[1], ios::binary | ios::ate); //open file in binary mode
if ( !filename )
{
cout << "Please enter a valid file name.\n";
cin >> argv[1];
}
else
{
n = 1; //end while loop since file is open
}
} while (n != 1);
filename.seekg(0, ios::end); //seek EOF
size = filename.tellg(); //return pointer at that position
file_buffer = new char[size];
filename.seekg(0, ios::beg); //seek beginning of file
filename.read(file_buffer, size); //read file, up to int size, into file_buffer
//print 20 lines in binary followed by ASCII
do
{
for (int g = 0; g <= 20; g++)
{
for (x; x < 16 + a; x++)
{
r = file_buffer[x]; //caste cout to type int, so 'hex' can work
cout << hex << setw(2) << uppercase << r << " ";
}
cout << "\t"; //align ASCII portion on right
for (m; m < 16 + a; m++)
{
//catch control character (endet/new line) and print '.' in it's place
if (iscntrl(file_buffer[m]))
cout << ".";
else
cout << file_buffer[m];
}
//increment a to print the next 16 bits
a+=16;
cout << endl;
}
//pause and wait for 'Enter' to continue
PressEnterToContinue();
//EOF is an int. file_buffer only stores characters.
//can't use file_buffer[x]
} while (x <= size );
//
//close file at program exit
filename.close();
}
void PressEnterToContinue( )
{
cout << "Press ENTER to continue... ";
cin.ignore( std::numeric_limits <std::streamsize> ::max(), '\n' );
}
Phew, so everything works great except when it reach the end of the file. Say there's not a full 20 lines left to print, it runs over and displays gobledeegook before exiting.
I think I'm going to need an if/else statement in my for loops to catch an EOF, but I'm having trouble wrapping my head around what flag to actually use.
file buffer is a type char * array, so it's an array of type string.
EOF is an int, in my case -1... so its going to stop at it, but not read it into the array. so i can't use:
Code:
file_buffer[x] != EOF
since there is no -1 in my buffer.
help??
Thanks
~Tim
__________________
"Life is not a journey with the intent on arriving at the finish line in a pretty and well preserved body. But rather to skid in broadside, totally worn out, thoroughly used up and loudly proclaiming, "Wow! What a ride!" -Anonymous
Halo! || Diablo 2 LOD Modding || OLGA's BACK!
|

October 17th, 2012, 05:28 PM
|
|
Contributing User
|
|
Join Date: Oct 2012
Posts: 71
Time spent in forums: 1 Day 7 h 39 m 39 sec
Reputation Power: 1
|
|
Are you saving the amount of bytes read with each filename.read(file_buffer, size) ? You need this value when you display your buffer so that you only display the values read.
Actually my bad, you have to call gcount() to find the number of characters read. Something like below:
Code:
#include <iostream>
#include <fstream>
int main(int argc, char** argv)
{
char buffer[100];
std::ifstream fin ("testfile", std::ifstream::binary);
fin.read(buffer, 100);
std::cout << fin.gcount() << std::endl;
for (size_t i = 0; i < fin.gcount(); ++i)
std::cout << (unsigned long)buffer[i] << std::endl;
fin.close();
return 0;
}
|

October 19th, 2012, 10:37 AM
|
 |
The bad and the ugly...
|
|
Join Date: Jan 2007
Location: Oz... No??? Neverland then?
Posts: 142
Time spent in forums: 1 Day 6 h 21 m 2 sec
Reputation Power: 0
|
|
that would work. I just ended up using the same closing statement as my do/while loop in an if/else inside my for loops.
only issue now is spacing for that last line. say i only write out 6 hex instead of 16, that
is no longer enough to get the ASCII portion to line up with the right side of the screen.
|

October 20th, 2012, 03:16 PM
|
|
Registered User
|
|
Join Date: Oct 2012
Posts: 1
Time spent in forums: 9 m 9 sec
Reputation Power: 0
|
|
|
Use a check inside the 2nd for loop.
Quote: | Originally Posted by ChokolAwt Hello again dev-shed users,
I was tasked with writing a binary file viewer for homework. I've got my code running, and everything works great... but it seems to read/print out past the end of the file.
Basically, it displays 20 lines at a time, with 16 bits of hex followed by 16 bits of ASCII. After the 20 lines have printed, it pauses and waits for you to hit enter before printing the following 20 lines. Once it reaches the end of the file it quits.
Code:
#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>
#include <ios>
//
//function prototype
void PressEnterToContinue();
using namespace std;
void main(int argc, char *argv[])
{
int n = 0; //used for prompting input file name
int r;
int x = 0, m = 0, a = 0;
ifstream filename; //start filestream
int size; //for file size
char *file_buffer; //buffer for storing file
//if user calls program from cmd prompt incorrectly or with "/?"
if((argc < 2) || (strcmp(argv[1],"/?") == 0))
{
cout << "This program reads a file and prints each character as a hexadecimal\n";
cout << "\n";
cout << "Usage: hw5 [input filename]\n";
exit(0);
}
//
//prompt user for file name and continue to do so until a valid file name is given
do
{
filename.open(argv[1], ios::binary | ios::ate); //open file in binary mode
if ( !filename )
{
cout << "Please enter a valid file name.\n";
cin >> argv[1];
}
else
{
n = 1; //end while loop since file is open
}
} while (n != 1);
filename.seekg(0, ios::end); //seek EOF
size = filename.tellg(); //return pointer at that position
file_buffer = new char[size];
filename.seekg(0, ios::beg); //seek beginning of file
filename.read(file_buffer, size); //read file, up to int size, into file_buffer
//print 20 lines in binary followed by ASCII
do
{
for (int g = 0; g <= 20; g++)
{
for (x; x < 16 + a; x++)
{
r = file_buffer[x]; //caste cout to type int, so 'hex' can work
cout << hex << setw(2) << uppercase << r << " ";
}
cout << "\t"; //align ASCII portion on right
for (m; m < 16 + a; m++)
{
//catch control character (endet/new line) and print '.' in it's place
if (iscntrl(file_buffer[m]))
cout << ".";
else
cout << file_buffer[m];
}
//increment a to print the next 16 bits
a+=16;
cout << endl;
}
//pause and wait for 'Enter' to continue
PressEnterToContinue();
//EOF is an int. file_buffer only stores characters.
//can't use file_buffer[x]
} while (x <= size );
//
//close file at program exit
filename.close();
}
void PressEnterToContinue( )
{
cout << "Press ENTER to continue... ";
cin.ignore( std::numeric_limits <std::streamsize> ::max(), '\n' );
}
Phew, so everything works great except when it reach the end of the file. Say there's not a full 20 lines left to print, it runs over and displays gobledeegook before exiting.
I think I'm going to need an if/else statement in my for loops to catch an EOF, but I'm having trouble wrapping my head around what flag to actually use.
file buffer is a type char * array, so it's an array of type string.
EOF is an int, in my case -1... so its going to stop at it, but not read it into the array. so i can't use:
Code:
file_buffer[x] != EOF
since there is no -1 in my buffer.
help??
Thanks
~Tim |
You can put a check inside the 2nd for loop. Like this:
if (x>size) {return 0;}..Here is what you can try for the following part of your code and it should work:
Code:
while (x <= size )
{
for (int g = 0; g <= 20; g++)
{
for (x; x < 16 + a; x++)
{
if (x>size) {
return 0;
}
else{
r = file_buffer[x]; //caste cout to type int, so 'hex' can work
cout << hex << setw(2) << uppercase << r << " ";
}
}
cout << "\t"; //align ASCII portion on right
for (m; m < 16 + a; m++)
{
//catch control character (endet/new line) and print '.' in it's place
if (iscntrl(file_buffer[m]))
cout << ".";
else
cout << file_buffer[m];
}
//increment a to print the next 16 bits
a+=16;
cout << endl;
}
//pause and wait for 'Enter' to continue
PressEnterToContinue();
//EOF is an int. file_buffer only stores characters.
//can't use file_buffer[x]
}
|
Developer Shed Advertisers and Affiliates
| Thread Tools |
Search this Thread |
|
|
|
| Display Modes |
Rate This Thread |
Linear Mode
|
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
|
|