Reading .raw file in C++ - c++

I am new in C++ in general, and thus, also in file handling in C++.
I need to read a .raw file which has 16-bit integers, and have dimension 512 x 512.
For that I am using following code:
ifstream myData("myData.raw");
short value;
int i = 0;
char buf[sizeof(short)];
while (myData.read(buf,sizeof(buf)))
{
memcpy(&value, buf, sizeof(value));
cout << value << " ";
i++;
}
cout << endl << "Total count: " << i << endl;
The value i am getting for i is not 512 x 512. So I guess something is not right.
Can someone please help me in this regard?

The default open mode is "text" and some characters will be possibly dropped or treated as end of file. ios::binary stops these alterations.
#include <iostream>
#include <fstream>
using namespace std;
int main() {
ifstream myData("myData.raw", ios::binary);
short value;
int i = 0;
char buf[sizeof(short)];
while (myData.read(buf, sizeof(buf)))
{
memcpy(&value, buf, sizeof(value));
cout << value << " ";
i++;
}
cout << endl << "Total count: " << i << endl;
}

Related

Cannot read a string from a binary file using fstream, it is showing weird symbols instead

I'm trying to read a .bin file that I have made that include two integers and one string inside a struct. The int shows fine, but somehow the string output shows weird symbols.
This is the write script:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
struct student{
int no;
string name;
int score;
};
int main(){
fstream myFile;
myFile.open("data.bin", ios::trunc | ios::out | ios::in | ios::binary);
student jay, brad;
jay.no = 100;
jay.name = "Jay";
jay.score = 95;
brad.no = 200;
brad.name = "Brad";
brad.score = 83;
myFile.write(reinterpret_cast<char*>(&jay),sizeof(student));
myFile.write(reinterpret_cast<char*>(&brad),sizeof(student));
myFile.close();
cin.get();
return 0;
}
and this is the read script:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
struct student{
int no;
string name;
int score;
};
int main(){
fstream myFile;
myFile.open("data.bin", ios::in | ios::binary);
student readFile;
myFile.seekp(1*sizeOf(student)); //I use this because I want only specific position
//to be shown, for example I put 1 to show only Brad
myFile.read(reinterpret_cast<char*>(&readFile),sizeof(student));
cout << "No : " << readFile.no << endl;
cout << "Name : " << readFile.name << endl;
cout << "Score: " << readFile.score << endl;
myFile.close();
cin.get();
return 0;
}
The result would be like this:
No : 200
Name : ñ∩K
Score: 83
The string showed "ñ∩K" instead of "Brad".
I tried not to use seekp, and using read twice:
myFile.read(reinterpret_cast<char*>(&readFile),sizeof(student));
cout << "No : " << readFile.no << endl;
cout << "Name : " << readFile.name << endl;
cout << "Score: " << readFile.score << endl;
myFile.read(reinterpret_cast<char*>(&readFile),sizeof(student));
cout << "No : " << readFile.no << endl;
cout << "Name : " << readFile.name << endl;
cout << "Score: " << readFile.score << endl;
The result would be:
No : 100
Name : Jay
Score: 95
No : 200
Name : ε#
Score: 83
As you can see, the first position shows "Jay" fine but the next one is not. Any idea what went wrong? I'm new to C++.
What you're writing to the file is not a string, but the internal structure of the std::string object. Likely that's a pointer. When you read it back in, the pointer will be pointing to something that isn't valid. You're lucky to get any output at all rather than a crash, or demons flying from your nostrils.

How to seek and read from binary file?

I'm still new to advance file and structures. I'm just having trouble figuring out how to seek and read specific records from a file. and how to display the information of a specific record through it's record number?
#include <iostream>
#include <fstream>
using namespace std;
struct catalog
{
char title[50];
char author[50];
char publisher[30];
int yearpublish;
double price;
};
void showRec(catalog);
long byteNum(int);
int main()
{
catalog book;
fstream fbook("book.dat",ios::in|ios::binary);
if (!fbook)
{
cout <<"Error opening file";
return 0;
}
//Seek and read record 2 (the third record)
showRec(book); // Display record 2
//Seek and read record 0 (the first record)
showRec(book); // Display record 0
fbook.close();
return 0;
}
void showRec(catalog record)
{
cout << "Title:" << record.title << endl;
cout << "Author:" << record.author << endl;
cout << "Publisher name:" << record.publisher << endl;
cout << "Year publish:" << record.yearpublish << endl;
cout << "Price:" << record.price << endl << endl;
}
long byteNum(int recNum)
{
return sizeof(catalog) * recNum;
}
Please Help. Thank you.
The C++ istream methods you need for this are seekg and read.
// Seek and read record 2
fbook.seekg(byteNum(2));
fbook.read((char*)&book, sizeof(book));

C++ converting binary(P5) image to ascii(P2) image (.pgm)

I am writing a simple program to convert grayscale binary (P5) to grayscale ascii (P2) but am having trouble reading in the binary and converting it to int.
#include <iostream>
#include <fstream>
#include <sstream>
using namespace::std;
int usage(char* arg) {
// exit program
cout << arg << ": Error" << endl;
return -1;
}
int main(int argc, char* argv[]) {
int rows, cols, size, greylevels;
string filetype;
// open stream in binary mode
ifstream istr(argv[1], ios::in | ios::binary);
if(istr.fail()) return usage(argv[1]);
// parse header
istr >> filetype >> rows >> cols >> greylevels;
size = rows * cols;
// check data
cout << "filetype: " << filetype << endl;
cout << "rows: " << rows << endl;
cout << "cols: " << cols << endl;
cout << "greylevels: " << greylevels << endl;
cout << "size: " << size << endl;
// parse data values
int* data = new int[size];
int fail_tracker = 0; // find which pixel failing on
for(int* ptr = data; ptr < data+size; ptr++) {
char t_ch;
// read in binary char
istr.read(&t_ch, sizeof(char));
// convert to integer
int t_data = static_cast<int>(t_ch);
// check if legal pixel
if(t_data < 0 || t_data > greylevels) {
cout << "Failed on pixel: " << fail_tracker << endl;
cout << "Pixel value: " << t_data << endl;
return usage(argv[1]);
}
// if passes add value to data array
*ptr = t_data;
fail_tracker++;
}
// close the stream
istr.close();
// write a new P2 binary ascii image
ofstream ostr("greyscale_ascii_version.pgm");
// write header
ostr << "P2 " << rows << cols << greylevels << endl;
// write data
int line_ctr = 0;
for(int* ptr = data; ptr < data+size; ptr++) {
// print pixel value
ostr << *ptr << " ";
// endl every ~20 pixels for some readability
if(++line_ctr % 20 == 0) ostr << endl;
}
ostr.close();
// clean up
delete [] data;
return 0;
}
sample image - Pulled this from an old post. Removed the comment within the image file as I am not worried about this functionality now.
When compiled with g++ I get output:
$> ./a.out a.pgm
filetype: P5
rows: 1024
cols: 768
greylevels: 255
size: 786432
Failed on pixel: 1
Pixel value: -110
a.pgm: Error
The image is a little duck and there's no way the pixel value can be -110...where am I going wrong?
Thanks.
greylevels: 255
-110 is 146 as an unsigned char. It appears you are on a platform where char is a signed type, try using unsigned char.
If you cannot have negative values , use an unsigned int * instead of int* for your pixel pointers. This way you won't have values read as signed values
You need a correction in output:
ostr << "P2\n" << rows << " "<< cols << " "<< greylevels << endl;

fstream get(char*, int) how to operate empty line?

code in strfile.cpp:
#include <fstream>
#include <iostream>
#include <assert.h>
#define SZ 100
using namespace std;
int main(){
char buf[SZ];
{
ifstream in("strfile.cpp");
assert(in);
ofstream out("strfile.out");
assert(out);
int i = 1;
while(!in.eof()){
if(in.get(buf, SZ))
int a = in.get();
else{
cout << buf << endl;
out << i++ << ": " << buf << endl;
continue;
}
cout << buf << endl;
out << i++ << ": " << buf << endl;
}
}
return 0;
}
I want to operate all file
but in strfile.out:
1: #include <fstream>
2: #include <iostream>
3: #include <assert.h>
4: ...(many empty line)
I know that fstream.getline(char*, int) this function can manage it,but I want to know how to do this just use the function "fstream.get()".
Because ifstream::get(char*,streamsize) will leave the delimiter (in this case \n) on the stream, your call never advances and thus it appears to your calling program that you are endlessly reading blank lines.
Instead you need to determine if a newline is waiting on the stream, and move past it using in.get() or in.ignore(1):
ifstream in("strfile.cpp");
ofstream out("strfile.out");
int i = 1;
out << i << ": ";
while (in.good()) {
if (in.peek() == '\n') {
// in.get(buf, SZ) won't read newlines
in.get();
out << endl << i++ << ": ";
} else {
in.get(buf, SZ);
out << buf; // we only output the buffer contents, no newline
}
}
// output the hanging \n
out << endl;
in.close();
out.close();

how to read binary file content as strings?

I need to read 16 bits from the binary file as std::string or char *. For example, a binary file contains 89 ab cd ef, and I want to be able to extract them as std::strings or char *. I have tried the following code:
ifstream *p = new ifstream();
char *buffer;
p->seekg(address, ios::beg);
buffer = new char[16];
memset(buffer, 0, 16);
p->read(buffer, 16);
When I try to std::cout the buffer, nothing appeared. How can I read these characters in the binary file?
EDIT: I was looking for the buffer to be a int type such as "0x89abcdef". Is it possible to achieve?
Something like:
#include <string>
#include <iostream>
#include <fstream>
#include <iomanip>
int main()
{
if (ifstream input("filename"))
{
std::string s(2 /*bytes*/, '\0' /*initial content - irrelevant*/);
if (input.read(&s[0], 2 /*bytes*/))
std::cout << "SUCCESS: [0] " << std::hex << (int)s[0] << " [1] " << (int)s[1] << '\n';
else
std::cerr << "Couldn't read from file\n";
}
else
std::cerr << "Couldn't open file\n";
}
You can't read a binary stream as though it were text.
You can, of course, read as binary (by using "file.read()" and "file.write()" methods on your stream object). Just like what you're doing now :)
You can also convert binary to text: "convert to hex text string" and "uuencode base 64" are two common ways to do this.
You'll want to read the bytes as numbers (of type long long probably).
Then you can print those using formatting specifiers like this:
#include <iostream>
#include <iomanip>
int main()
{
using namespace std;
int x = 2;
int y = 255;
cout << showbase // show the 0x prefix
<< internal // fill between the prefix and the number
<< setfill('0'); // fill with 0s
cout << hex << setw(4) << x << dec << " = " << setw(3) << x << endl;
cout << hex << setw(4) << y << dec << " = " << setw(3) << y << endl;
return 0;
}