First, I would like to express that I come to post my question, after a lot of searching on the internet, without finding a proper article or solution to what I'm looking for.
As mentioned in the title, I need to convert an ASCII file to Binary file.
My file is composed of lines, every line contain float separated by space.
I found that many people use c++ since it's more easy for this kind of task.
I tried the following code, but the generated file is so big.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main(int argc, char const *argv[])
{
char buffer;
ifstream in("Points_in.txt");
ofstream out("binary_out.bin", ios::out|ios::binary);
float nums[9];
while (!in.eof())
{
in >> nums[0] >> nums[1] >> nums[2]>> nums[3] >> nums[4] >> nums[5]>> nums[6] >> nums[7] >> nums[8];
out.write(reinterpret_cast<const char*>(nums), 9*sizeof(float));
}
return 0;
}
I found those 2 resources :
http://www.eecs.umich.edu/courses/eecs380/HANDOUTS/cppBinaryFileIO-2.html
https://r3dux.org/2013/12/how-to-read-and-write-ascii-and-binary-files-in-c/
I appreciate if you have any others resources ?
lines in my ASCII input file are as below :
-16.505 -50.3401 -194 -16.505 -50.8766 -193.5 -17.0415 -50.3401 -193.5
Thank you for your time
Here is a simpler method:
#include <iostream>
#include <fstream>
int main()
{
float value = 0.0;
std::ifstream input("my_input_file.txt");
std::ofstream output("output.bin");
while (input >> value)
{
output.write(static_cast<char *>(&value), sizeof(value));
}
input.close(); // explicitly close the file.
output.close();
return EXIT_SUCCESS;
}
In the above code fragment, a float is read using formatted read into a variable.
Next, the number is output in its raw, binary form.
The reading and writing repeat until there is no more input data.
Exercises for the reader/OP:
1. Error handling for opening of files.
2. Optimize the reading and writing (read & write using bigger blocks of data).
Related
I am curious to know from the more experienced c++ programmers out there if there is a way to have a function read in files that have different formats. Example is one file has a template of house # then street name and the other file is the opposite, house name then street #. Again, just curious if there was some sleek code that I could add to my knowledge and tool box, instead of writing two different inFile functions.
Thank you all for your time.
EDIT
Here is some of the code:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
struct WH
{
int inum;
string iname;
string warname;
int quant;
float whole;
float markup;
float retail;
};
void readinprime(WH);
ifstream inFile;
ofstream outFile;
int main()
{
WH ware[100];
//inFile.open("WLL1.txt", ios::in);
//inFile.open("WLL2.txt", ios::in);
//inFile.open("WLL3.txt", ios::in);
//inFile.open("WLL4.txt", ios::in);
return 0;
}
void readinprime(WH ware[])
{
int c;
for(c = 0; c < 100; c++)
{
inFile << ware.inum[c] << ware.iname[c];
}
}
So essentially the first file (WLL1.txt) has the format integer->string and then the next file (WLL2.txt) will have the format string->integer. My question is, is there another way to write the read in function where it can read in int then string & string then int without writing another function? I dont mind writing another function for every file format, but I was just curious if someone had some good tricks that I could add to my tool box. Again thank you for your time.
you can use the getline method to read every line from the text and store it in a variable
I made this problem by myself!
I'm reading a file, in C, where each line contains a number (random between 0 to 1000000):
1121
84
928434
9999
70373
...
I read line by line, and for each line, I do some calculation and write a big chuck of data into a file named d_file.txt where d is the list significant digit of the read number. Assume writing in file takes a long time, so I want to write a the code in a multi-thread so I can write in multiple files (~10) at the same time. While the single thread C code is obvious, I'm wondering how multi-thread code using pthread looks like.
single-thread C code:
#include <fstream>
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int func(int a)
{
//assume the data is big and writing takes a long time
int data = a;
return data;
}
int main()
{
ifstream in("numbers.txt");
int a;
while(in >> a)
{
stringstream ss;
ss << a%10;
string str;
ss >> str;
str += "_File.txt";
ofstream out(str.c_str(), fstream::in | fstream::out | fstream::trunc);
//This is blocking, if write takes long
//but can be rewritten in a multi-thread fashion
// to allow upto 10 simultaneous file write
out << func(a) << endl;
}
return 0;
}
You can definitely read a file, and multiple sections of a file, at the same time. Check out this SO answer. If that isn't enough for you there are lots more on SO and across the web explaining how to both read and write to ASCII in parallel.
In my project i need to write to a binary file sequential unsigned ints, and it's important that each number takes exact 4 bytes.
But when i open the binary file with a hex editor, i see this strange happening:
the numbers are written correctly just up to number 9; before number 10 he will add another extra byte and write '13' (and already messed up with my file).
And strange things continue to happen- from number 30 and on will be written different characters, one aside each number.
why is that? how to fix, at least the size issue?
Here is my simple sample code:
int main()
{
string filename;
cin >> filename;
fstream mystream;
mystream.open(filename, ios::out);
if (mystream)
for (unsigned int i = 0; i < 3200; i++)
mystream.write((char*)&i, sizeof(unsigned int));
mystream.close();
return 0;
}
and is attached an image of what i see in the file:
file capture on hex editor
thanks
The number 10 is a newline character LF, and it is converted to CRLF because the file is opened in text mode.
Open files in binary mode to deal with binary files.
#include <iostream>
#include <fstream>
#include <string>
using std::string;
using std::cin;
using std::fstream;
using std::ios;
int main()
{
string filename;
cin >> filename;
fstream mystream;
mystream.open(filename, ios::out | ios::binary); // add OR with ios::binary
if (mystream)
for (unsigned int i = 0; i < 3200; i++)
mystream.write((char*)&i, sizeof(unsigned int));
mystream.close();
}
I need to read a jpg file to a string. I want to upload this file to our server, I just find out that the API requires a string as the data of this pic. I followed the suggestions in a former question I've asked Upload pics to a server using c++ .
int main() {
ifstream fin("cloud.jpg");
ofstream fout("test.jpg");//for testing purpose, to see if the string is a right copy
ostringstream ostrm;
unsigned char tmp;
int count = 0;
while ( fin >> tmp ) {
++count;//for testing purpose
ostrm << tmp;
}
string data( ostrm.str() );
cout << count << endl;//ouput 60! Definitely not the right size
fout << string;//only 60 bytes
return 0;
}
Why it stops at 60? It's a strange character at 60, and what should I do to read the jpg to a string?
UPDATE
Almost there, but after using the suggested method, when I rewrite the string to the output file, it distorted. Find out that I should also specify that the ofstream is in binary mode by ofstream::binary. Done!
By the way what's the difference between ifstream::binary & ios::binary, is there any abbreviation for ofstream::binary?
Open the file in binary mode, otherwise it will have funny behavior, and it will handle certain non-text characters in inappropriate ways, at least on Windows.
ifstream fin("cloud.jpg", ios::binary);
Also, instead of a while loop, you can just read the whole file in one shot:
ostrm << fin.rdbuf();
You shouldn't read the file to a string because it is legal for a jpg to contain values that are 0. However in a string, the value 0 has a special meaning (it's the end of string indicator aka \0). You should instead read the file into a vector. You can do this easily like so:
#include <algorithm>
#include <iostream>
#include <fstream>
#include <vector>
int main(int argc, char* argv[])
{
std::ifstream ifs("C:\\Users\\Borgleader\\Documents\\Rapptz.h");
if(!ifs)
{
return -1;
}
std::vector<char> data = std::vector<char>(std::istreambuf_iterator<char>(ifs), std::istreambuf_iterator<char>());
//If you really need it in a string you can initialize it the same way as the vector
std::string data2 = std::string(std::istreambuf_iterator<char>(ifs), std::istreambuf_iterator<char>());
std::for_each(data.begin(), data.end(), [](char c) { std::cout << c; });
std::cin.get();
return 0;
}
Try opening the file in binary mode:
ifstream fin("cloud.jpg", std::ios::binary);
At a guess, you were probably trying to read the file on Windows and the 61st character was probably 0x26 -- a control-Z, which (on Windows) will be treated as marking the end of the file.
As far as how to best do the reading, you end up with a choice between simplicity and speed, as demonstrated in a previous answer.
So I have made a program that opens up a text file using ifstream. Now I want to make it so it outputs this file in binary. I have tried ofstream and using .write() but when I do the program crashes. I set it up correctly when using .write() as I have seen online but I haven't seen anyone do it with what I was working with. Anybody have a solution to this? Also, I do not know why 'InputFile' and 'OutputFile' are both highlighted blue like that.
#include <iostream>
#include <fstream>
#include <string>
#include <bitset>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
int main(int argc, char* argv[])
{
if (argc < 2)
{
cout << "Error 1";
return 0;
}
else
{
int WIDTH, HEIGHT;
ifstream InputFile;
InputFile.open(argv[1], ios::in);
ofstream OutputFile;
OutputFile.open("OUTPUT.raw", ios::binary | ios::app);
cout << "Enter Width" << endl;
WIDTH = cin.get();
HEIGHT = WIDTH;
for (int x = 0; x < WIDTH; x++)
{
for (int y = 0; y < HEIGHT; y++)
{
OutputFile.write((char*)InputFile.get(), sizeof(InputFile));
}
}
}
//cout << bitset<8>(txt[i]);
return 0;
};
OutputFile.write((char*)InputFile.get(), sizeof(InputFile));
First, istream::get() extracts one characters from the stream and returns its value casted to an integer. The result is a temporary, which you cast to a pointer to char! It compiles, because the C-style cast basically tells the compiler "shoosh, I know what I'm doing!", but it will certainly do weird things at run-time. You need to get an adress of some object where the value you want to write is stored in, and cast that adress.
The second thing, sizeof(InputFile) returns size of ifstream class that manages the file stream. It's not in any way related to how many data is in the stream's buffer.
If you open a stream in text mode, then the correct way to extract data from it is to use extraction operator (>>). Then it's pretty simple:
std::ifstream in_file("numbers.txt");
std::ofstream out_file("numbers.bin", std::ios::binary);
int i;
while (in_file >> i)
out_file.write(reinterpret_cast<char*>(&i), sizeof(int));
The above snippet will work with an input text file like this: -4 21 1990 5425342 -3432 0 100.
You will have to parse your text file to get int for every string in file and just create a new file and write your binary data with fputc() or fwrite() functions.