C++ FILE readInt function? (from a binary file) - c++

Is there a function for FILE (fopen?) that allows me to just read one int from a binary file?
So far I'm trying this, but I'm getting some kind of error I can't see cause the program just crashes without telling me.
void opentest()
{
FILE *fp = fopen("dqmapt.mp", "r");
int i = 0;
int j = 0;
int k = 0;
int * buffer;
if (fp)
{
buffer = (int *) (sizeof(int));
i = (int) fread(buffer,1, (sizeof(int)), fp);
fscanf(fp, "%d", &j);
fclose(fp);
}
printf("%d\n", i);
printf("%d\n", j);
}

Now that you have changed your question, let me ask one. What is the format of the file you are trying to read?
For a binary file there are some changes required how you open the file:
/* C way */
FILE *fp = fopen("text.bin", "rb"); /* note the b; this is a compound mode */
/* C++ way */
std::ifstream ifs("test.txt", ios::in | ios::binary);
Reading in the contents is easy. But remember, your file has 2 integers at the begining -- width, height which determine how many more to read i.e. another width * height number of integers. So, your best bet is to read the first two integers first. You will need to use two buffers -- one for the width and height and then depending on their value another one to read the rest of the file. So, lets read in the first two integers:
char buf[ 2 * sizeof(int) ]; /* will store width and height */
Read in the two integers:
/* C way */
fread(buf, sizeof(int), 2, fp); /* the syntax changes, FILE pointer is last */
/* C++ way*/
ifs.read(buf, sizeof buf);
Now, the tricky part. You have to convert the stuff to double. This again depends on your system endianness -- whether a simple assignment works or whether a byte swapping is necessary. As another poster has pointed out WriteInt() writes integers in big-endian format. Figure out what system you are on. And then you can proceed further.
FILE is a C datastructure. It is included in C++ for C compatibility. You can do this:
/* The C way */
#include <stdio.h>
#include <stdlib.h>
int main(void) {
FILE *fp = fopen("test.txt", "r");
int i = 0;
if (fp) {
fscanf(fp, "%d", &i);
fclose(fp);
}
printf("%d\n", i);
}
You can use the std::ifstream thing to open a file for reading. You have to read in the contents using some other incantation to read the file contents and extract the desired information out of it yourself.
/* The C++ way */
#include <fstream>
#include <iostream>
int main() {
std::ifstream ifs("test.txt");
int i = 0;
if (ifs.good()) {
ifs >> i;
}
std::cout << i << std::endl;
}
Note you can use the C style functions in C++ as well, though this is the least recommended way:
/* The C way in C++ */
#include <cstdio>
#include <cstdlib>
int main() {
using namespace std;
FILE *fp = fopen("test.txt", "r");
int i = 0;
if (fp) {
fscanf(fp, "%d", &i);
fclose(fp);
}
printf("%d\n", i);
}
[Note: Both examples assume you have a text file to read from]

Do you want to read a textual representation of an int? Then you can use fscanf, it's sort of the opposite of printf
int n;
if( fscanf(filePointer, "%d", &n) == 1 )
// do stuff with n
If you want to read some binary data and treat it as an int, well that's going to depend how it was written in the first place.
I am not a Java programmer, so this is just based on what I've read in the [docs](http://java.sun.com/j2se/1.4.2/docs/api/java/io/DataOutputStream.html#writeInt(int)).
That said, it says
Writes an int to the underlying output stream as four bytes, high byte first. If no exception is thrown, the counter written is incremented by 4.
So it's a big endian four byte integer. I don't know if it's two's complement or not, but that's probably a safe assumption (and can probably be found somewhere in the java docs/spec). Big endian is the same as network byte order, so you can use ntohl to convert it the endianness of your C++ platform. Beyond that, you just need to read the four bytes, which can be done with fread.

Int represented as text or binary?
For text, use fscanf; for binary, use fread.

Related

Reading and Writing any file in C++

I have a program where I need to operate on different types of files.
I want the input and output files of the following program to be the same.
#include<iostream>
#include<string>
#include<fstream>
#include<sstream>
typedef unsigned char u8;
using namespace std;
char* readFileBytes(string name)
{
ifstream fl(name);
fl.seekg( 0, ios::end );
size_t len = fl.tellg();
char *ret = new char[len];
fl.seekg(0, ios::beg);
fl.read(ret, len);
fl.close();
return ret;
}
int main(int argc, char *argv[]){
string name = "file.pdf";
u8* file = (u8*) readFileBytes(name);
// cout<<str<<endl;
int len = 0;
while(file[len] != '\0')
len++;
cout<<"FILESIZE : "<<len<<endl;
string filename = "file2.pdf";
ofstream outfile(filename,ios::out | ios::binary);
outfile.write((char*) file,len);
outfile.close();
exit(0);
}
The difference between the output and input files is checked using diff
diff file.pdf file2.pdf
What should I do to make file2.pdf the same as file.pdf?
I have tried using xxd to change the binary into hexadecimal but the disadvantage is that the overall size doubles. So therefore I want to operate in binary only.
size_t len = fl.tellg();
char *ret = new char[len];
In this manner the shown code determines the number of characters in the file. This is fine. The only problem with it is that after this number of characters is read, this very important information is completely forgotten and thrown away. This function returns only this ret pointer, and the actual number of characters in it is now an unsolvable mystery.
But then, main() attempts to solve this mystery as follows:
int len = 0;
while(file[len] != '\0')
len++;
This attempts to reverse-engineer the number of characters by looking for the first 0 byte in the buffer.
Which has absolutely nothing to do with anything. The first character in the file may be a 0 byte, so this will calculate that the file is empty, and not ten gigabytes in size.
Or the file can contain just a string "Hello world", which this for loop will happily blow past, then start rooting around in some random memory after this buffer, resulting in undefined behavior.
That's the fatal logical flaw in the shown code: the actual size of the file is thrown away, and instead reverse-engineered in a flawed way.
You will need to rework the code so that the number of characters in the file, the original len, is also returned to main(), and it uses that, instead of attempting to guess what it originally was.
P.S. delete-ing the ret buffer, after you're done with it, would also be a good idea too. An even better idea is to avoid using new, using vector instead, which will happily give you its size() any time you ask for it, and you won't have to worry about deleting the allocated memory.
In order to correctly process binary data, the size must be stored and cannot be computed from a sentinel null byte, because null bytes can be legimate bytes in a binary file. So you should return the read lenght in addition to the buffer, or even better copy each buffer to the new file until you have exhausted the input file:
int main(int argc, char *argv[]){
constexpr size_t sz = 10240; // size of buffer
char buffer[sz];
string name = "file.pdf";
string filename = "file2.pdf";
ifstream fl(name);
ofstream outfile(filename,ios::out | ios::binary);
int len = 0, buflen;
for (;;) {
buflen = fl.read(buf, len);
if (buflen == 0) break; // reached EOF
len += buflen;
if (buflen != outfile.write(buf, buflen)) {
// display an error message
return 1;
}
}
fl.close();
outfile.close()
cout<<"FILESIZE : "<<len<<endl;
exit(0);
}

C++ Attempt to optimize printing data to binary file for every frame

void demodlg::printData(short* data)
{
FILE* pF;
char buf[50];
snprintf(buf, sizeof(buf), "%s\\%s\\%s%d.binary", "test", "data", "data", frameNum++);
pF = fopen(buf, "wb");
int lines = frameDescr->m_numLines;
int samples = frameDescr->m_pLineTypeDescr[0].m_numSamples;
int l, s;
fprintf(pF, "\t");
for (l = 0; l < lines; l++)
{
fprintf(pF, "%d\t", l);
}
fprintf(pF, "\n");
for (s = 0; s < samples; s++)
{
fprintf(pF, "%d)\t", s);
for (l = 0; l < lines; l++)
{
fprintf(pF, "%d\t", *(data + l * samples + s));
}
fprintf(pF, "\n");
}
fclose(pF);
}
I have the code snippet above which just takes in some data and then writes it out to a binary file. This function gets called about 20-30 times per second, so I'm trying to optimize it as much as possible. Each file that it writes to is about 1 MB in size. Ideally, I'd be able to write 20-30 MB per second. As of now, it's not at that rate.
Does anyone have any ideas on how I can optimize this further?
I originally was writing to a txt file before changing to a binary file, but the different isn't too noticeable, surprisingly.
Also, frameDescr gets updated for every frame so I believe I do need to get access to the lines and samples variables from inside, unfortunately.
I found this post to refer to (Writing a binary file in C++ very fast) but I'm not sure how I can apply it to mine.
Here is a short example of how I would write an array of data to a binary file and how I would read it back.
I do not understand the concept or purpose of lines in your code so I did not attempt to replicate it. If you do have additional data you need to write to allow it to be reconstructed when read I have placed comments to note where you could insert that code.
Keep in mind that the data when written as binary must be read the same way, so if you were writing the text in a particular format to consume it from another program then a binary file will not work for you unless you modify that other program or create an additional step to read the binary data and write the text format before consumption.
Assuming there is a speed advantage to writing the data as binary then adding an additional step to convert the binary data to text format is beneficial because you can do it offline when you're not trying to maintain a particular frame rate.
Normally since you tagged this c++ I would prefer manipulating the data in a vector and perhaps using c++ streams to write and read the data, but I tried to keep this as similar to your code as possible.
#include <cstdio>
#include <stdint.h>
const size_t kNumEntries = 128 * 1024;
void writeData(const char *filename, int16_t *data, size_t numEntries)
{
FILE *f = fopen(filename, "wb");
if (!f)
{
fprintf(stderr, "Error opening file: '%s'\n", filename);
return;
}
//If you have additional data that must be in the file write it here
//either as individual items that are mirrored in the reader,
//or using the pattern showm below for variable sized data.
//Write the number of entries we have to write to the file so the reader
//will know how much memory to allocate how many to read.
fwrite(&numEntries, sizeof(numEntries), 1, f);
//Write the actual data
fwrite(data, sizeof(*data), numEntries, f);
fclose(f);
}
int16_t* readData(const char *filename)
{
FILE *f = fopen(filename, "rb");
if (!f)
{
fprintf(stderr, "Error opening file: '%s'\n", filename);
return 0;
}
//If you have additional data to read, do it here.
//This code whould mirror the writing function.
//Read the number of entries in the file.
size_t numEntries;
fread(&numEntries, sizeof(numEntries), 1, f);
//Allocate memory for the entreis and read them into it.
int16_t *data = new int16_t[sizeof(int16_t) * numEntries];
fread(data, sizeof(*data), numEntries, f);
fclose(f);
return data;
}
int main()
{
int16_t *dataToWrite = new int16_t[sizeof(int16_t) * kNumEntries];
int16_t *dataRead = new int16_t[sizeof(int16_t) * kNumEntries];
for (int i = 0; i < kNumEntries; ++i)
{
dataToWrite[i] = i;
dataRead[i] = 0;
}
writeData("test.bin", dataToWrite, kNumEntries);
dataRead = readData("test.bin");
for (int i = 0; i < kNumEntries; ++i)
{
if (dataToWrite[i] != dataRead[i])
{
fprintf(stderr,
"Data mismatch at entry %d, : dataToWrite = %d, dataRead = %d\n",
i, dataToWrite[i], dataRead[i]);
}
}
delete[] dataRead;
return 0;
}

Reading and Writing to a File using C++

I need to read each line in the "test.txt" file using fscanf and print to new files using fprintf. If the read line is an integer, it is written to the integer file.
Float to the float file and string to string file respectively. However, when i try to compile it and run it, nothing happens and it goes to infinite loop.
Here is my code
#include <iostream>
#include <stdio.h>
using namespace std;
void writeFloat(){
FILE *file;
FILE *file2;
float value;
file = fopen("test.txt", "r");
file2 = fopen("float.out.txt", "w");
while(!feof(file)){
fscanf(file, "%f", &value);
fprintf(file2,"%f", value);
}
fclose(file);
fclose(file2);
}
void writeInteger(){
FILE *file;
FILE *file2;
int value;
file = fopen("test.txt", "r");
file2 = fopen("int.out.txt", "w");
while(!feof(file)){
fscanf(file, "%d", &value);
fprintf(file2, "%d", value);
}
fclose(file);
fclose(file);
}
void writeString(){
FILE *file;
FILE *file2;
char value;
file = fopen("test.txt", "r");
file2 = fopen("string.out.txt", "w");
while(!feof(file)){
fscanf(file, "%s", &value);
cout<<value<<endl;
fprintf(file2, "%s", value);
}
fclose(file);
fclose(file2);
}
int main(){
writeFloat();
writeInteger();
writeString();
return(0);
}
The test.txt file contains the values:
100
1.6E-10
hey nice to meet you.
43
56
4.5E-09
what is going on?
I don't know what wrong with my code. Please help me to achieve my requirement.
feof() is never true because fscanf in writefloat() refuses to read the first letter of "hey": It's not part of a legal number. scanf then returns with 0 ("no item could be read"). That is not EOF yet, though. But you should do something about it ;-).
Besides you must check for eof after you try to read something, before you try to use it. Not before the first failed read will the eof flag be turned on, but those variables will not be assigned.
I think, adopting a different strategy might be more appropriate for your needs.
Just have one function that reads the contents of the file line by line. It checks whether the line contains an integer or a floating point number. It line does not contain any numbers, the line is written out to "string.out.txt". If the number is an integer, it is written out to "int.out.txt". If the number is a floating point number, it is written out to "float.out.txt".
With this strategy, you have to read the contents of the input file only once and process the contents of the file only once.
It also simplifies the reading of the data and checking when you have reached EOF.
#include <stdio.h>
void writeData()
{
FILE *file1 = NULL;
FILE *file2 = NULL;
FILE *file3 = NULL;
FILE *file4 = NULL;
char value;
double realNum = 0.0;
int intNum = 0;
int n = 0;
char line[256];
file1 = fopen("test.txt", "r");
file2 = fopen("string.out.txt", "w");
file3 = fopen("int.out.txt", "w");
file4 = fopen("float.out.txt", "w");
while ( fgets(line, 255, file1) != NULL )
{
// Each line can be plain old text, a floating point number, or an
// integer.
// If the line does not contain a number, assume it is a float.
// Try to read a real number.
n = sscanf(line, "%lf", &realNum);
if ( n == 0 )
{
// The line does not have a number.
// Write the line to the text file.
fputs(line, file2);
}
else
{
// We have a real number.
// Could it be just an integer?
// Read the integer.
sscanf(line, "%d", &intNum);
// How do we decide whether the number is a real number or an
// integer?
// Is 1.0 a real number or an integer?
// Assume for now it is an integer.
if ( realNum == intNum )
{
// We have an integer.
fprintf(file3, "%d\n", intNum);
}
else
{
// We have a real number.
fprintf(file4, "%lG\n", realNum);
}
}
}
fclose(file4);
fclose(file3);
fclose(file2);
fclose(file1);
}
int main()
{
writeData();
return(0);
}
That is not the common way to open and close a file in C++. It looks like a c program. Try using functions from fstream and iostream libraries. See http://www.tutorialspoint.com/cplusplus/cpp_files_streams.htm.

Trouble with C++ file I/O

Noobie Alert.
Ugh. I'm having some real trouble getting some basic file I/O stuff done using <stdio.h> or <fstream>. They both seem so clunky and non-intuitive to use. I mean, why couldn't C++ just provide a way to get a char* pointer to the first char in the file? That's all I'd ever want.
I'm doing Project Euler Question 13 and need to play with 50-digit numbers. I have the 150 numbers stored in the file 13.txt and I'm trying to create a 150x50 array so I can play with the digits of each number directly. But I'm having tons of trouble. I've tried using the C++ <fstream> library and recently straight <stdio.h> to get it done, but something must not be clicking for me. Here's what I have;
#include <iostream>
#include <stdio.h>
int main() {
const unsigned N = 100;
const unsigned D = 50;
unsigned short nums[N][D];
FILE* f = fopen("13.txt", "r");
//error-checking for NULL return
unsigned short *d_ptr = &nums[0][0];
int c = 0;
while ((c = fgetc(f)) != EOF) {
if (c == '\n' || c == '\t' || c == ' ') {
continue;
}
*d_ptr = (short)(c-0x30);
++d_ptr;
}
fclose(f);
//do stuff
return 0;
}
Can someone offer some advice? Perhaps a C++ guy on which I/O library they prefer?
Here's a nice efficient solution (but doesn't work with pipes):
std::vector<char> content;
FILE* f = fopen("13.txt", "r");
// error-checking goes here
fseek(f, 0, SEEK_END);
content.resize(ftell(f));
fseek(f, 0, SEEK_BEGIN);
fread(&content[0], 1, content.size(), f);
fclose(f);
Here's another:
std::vector<char> content;
struct stat fileinfo;
stat("13.txt", &fileinfo);
// error-checking goes here
content.resize(fileinfo.st_size);
FILE* f = fopen("13.txt", "r");
// error-checking goes here
fread(&content[0], 1, content.size(), f);
// error-checking goes here
fclose(f);
I would use an fstream. The one problem you have is that you obviously can't fit the numbers in the file into any of C++'s native numeric types (double, long long, etc.)
Reading them into strings is pretty easy though:
std::fstream in("13.txt");
std::vector<std::string> numbers((std::istream_iterator<std::string>(in)),
std::istream_iterator<std::string>());
That will read in each number into a string, so the number that was on the first line will be in numbers[0], the second line in numbers[1], and so on.
If you really want to do the job in C, it can still be quite a lot easier than what you have above:
char *dupe(char const *in) {
char *ret;
if (NULL != (ret=malloc(strlen(in)+1))
strcpy(ret, in);
return ret;
}
// read the data:
char buffer[256];
char *strings[256];
size_t pos = 0;
while (fgets(buffer, sizeof(buffer), stdin)
strings[pos++] = dupe(buffer);
Rather than reading the one hundred 50 digit numbers from a file, why not read them directly in from a character constant?
You could start your code out with:
static const char numbers[] =
"37107287533902102798797998220837590246510135740250"
"46376937677490009712648124896970078050417018260538"...
With a semicolon at the last line.

Reading and printing an entire file in binary mode using C++

a follow up to my previous question (Reading an entire file in binary mode using C++)
After reading a jpg file in binary mode, the result of the read operation is always 4 bytes. The code is:
FILE *fd = fopen("c:\\Temp\\img.jpg", "rb");
if(fd == NULL) {
cerr << "Error opening file\n";
return;
}
fseek(fd, 0, SEEK_END);
long fileSize = ftell(fd);
int *stream = (int *)malloc(fileSize);
fseek(fd, 0, SEEK_SET);
int bytes_read = fread(stream, fileSize, 1, fd);
printf("%x\n", *stream);
fclose(fd);
The second last printf statement is always printing the first 4 bytes and not the entire file contents. How can I print the entire content of the jpg file?
Thanks.
You want it in C++? This opens a file, reads the entire contents into an array and prints the output to the screen:
#include <fstream>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
void hexdump(void *ptr, int buflen)
{
unsigned char *buf = (unsigned char*)ptr;
int i, j;
for (i=0; i<buflen; i+=16) {
printf("%06x: ", i);
for (j=0; j<16; j++) {
if (i+j < buflen)
printf("%02x ", buf[i+j]);
else
printf(" ");
}
printf(" ");
for (j=0; j<16; j++) {
if (i+j < buflen)
printf("%c", isprint(buf[i+j]) ? buf[i+j] : '.');
}
printf("\n");
}
}
int main()
{
ifstream in;
in.open("C:\\ISO\\ITCHOUT.txt", ios::in | ios::binary);
if(in.is_open())
{
// get the starting position
streampos start = in.tellg();
// go to the end
in.seekg(0, std::ios::end);
// get the ending position
streampos end = in.tellg();
// go back to the start
in.seekg(0, std::ios::beg);
// create a vector to hold the data that
// is resized to the total size of the file
std::vector<char> contents;
contents.resize(static_cast<size_t>(end - start));
// read it in
in.read(&contents[0], contents.size());
// print it out (for clarity)
hexdump(contents.data(), contents.size());
}
}
stream is a pointer to an int (the first element of the array you allocated1). *stream dereferences that pointer and gives you the first int.
A pointer is not an array. A pointer is not a buffer. Therefore, it carries no information about the size of the array it points to. There is no way you can print the entire array by providing only a pointer to the first element.
Whatever method you use to print that out, you'll need to provide the size information along with the pointer.
C++ happens to have a pointer + size package in its standard library: std::vector. I would recommend using that. Alternatively, you can just loop through the array yourself (which means using the size information) and print all its elements.
1Make sure the size of the file is a multiple of sizeof(int)!
Something like the following should do it. bytes_read() gives you the number of blocks read, in your case the block size is the file size so only one block can be read.
You should use a for loop to print the whole file. You're only printing one pointer address.
char *stream = (char *)malloc(fileSize);
fseek(fd, 0, SEEK_SET);
int bytes_read = fread(stream, fileSize, 1, fd);
for(int i=0; i<fileSize; i++){
printf("%d ", stream[i]);
}
I print the chars as numbers as binary data is not readable in the console. I don't know how you wanted the data to be formatted.
This is just meant as reference to your sample. You should really consider using Chad's sample. This is a far worse solution (as mixing C/C++ far too much) just for sake of completeness.