Vector mat in txt - c++

I ve got a vector Mat file and I want to store it in txt file. Every mat file has size 1x4500 and I ve got in total 5000 vectors. I tried to store in txtfile with the above code:
void writeMatToFile(cv::Mat& m, const char* filename){
ofstream fout(filename);
for(int i=0; i<m.rows; i++){
for(int j=0; j<m.cols; j++){
fout<<m.at<float>(i,j)<<"\t";
}
fout<<endl;
}
fout.close();
}
In main:
string file = "output.txt";
writeMatToFile(image,file.c_str());
However, I got unhandled exception errors.

Write your data in binary mode using your own format. Something like : mat_count|shape1|data1(row_first)|shape2...
std::fstream will do the harder job for you in text mode or binary mode. You should try both to see the final size.
If your Mat data is something like uint8, uint16, the binary mode will be much better. The problem with text-mode is that you need a separator for each single data which add additional bytes to your file. However text-mode can compress data : "1.5" 3 vs 8 bytes (double).
Last thing, if you want absolutely a file in text-mode, you can zip it at the end of your process and see the ratio.

Related

C++: FStream thinks it has reached EOF of binary file

I'm trying to read a binary file with the following format:
-64 bit integer
-3276 32-bit floats
-(Repeat last 2 lines until eof)
This is the block where I interpret the file:
ifstream bbrFile;
ofstream csvFile;
bbrFile.open(inFilename);
csvFile.open(dataFilename);
//yes I did actually check to make sure that the files had opened.
//I omitted it here for brevity
long long int time;
float point;
while (bbrFile)
{
bbrFile.read((char*)&time, sizeof(time));
csvFile << time;
for (int i = 0; i < 3276; i++) {
bbrFile.read((char*)&point, sizeof(point));
csvFile << ',' << point;
}
csvFile << "\n";
}
So far, my code is working fine, except that it thinks it's reached the end of file after reading in about 53 floats, and then just outputs the last float it read until the 'for' loop ends. I've tried using fread and FILE* instead of read and fstream, and gotten identical results. I've also tried replacing
while (bbrFile)
with
while (!bbrFile.eof())
To no avail.
Since the binary file is about 12 megabytes, I'm somewhat as a loss as to why it stops reading here.
To read the file as a binary file, you should add binary to the file mode:
bbrFile.open(inFilename, ios::binary);
otherwise it will be read as a text file, and some codes could be interpreted as an end-of-file mark.

Editing bmp pixel by pixel [C++]

I want to make a program that will take an image and replace the Blue component of every pixel with 0.
So I wrote this. I have one bmp image in the folder and a copy of it and as the input file i put in the name of the original and as the output name i write the copy. But when i try to open the second one after the program works it doesnt open properly. Could anyone help?
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
int main()
{
ifstream ifs;
ofstream ofs;
char input[80];
char output[80];
cout<<"Input file name"<<endl;
cin>>input;
ifs.open(input, ios::binary);
if(!ifs)
{
cout<<"Error in opening file"<<endl;
system("pause");
return 0;
}
cout<<"Output file name"<<endl;
cin>>output;
ofs.open(output, ios::binary);
ifs.seekg(2);
int file_size;
ifs.read((char*)&file_size, sizeof(int));
ofs<<"Bitmap size: "<<file_size<<"\r\n";
ifs.seekg(10);
int beg;
ifs.read((char*)&beg, sizeof(int));
ofs<<"Beggining of image: "<<beg<<"\r\n";
ifs.seekg(18);
int columns;
ifs.read((char*)&columns, sizeof(int));
ofs<<"Column number: "<<columns<<"\r\n";
ifs.seekg(22);
int rows;
ifs.read((char*)&rows, sizeof(int));
ofs<<"Row number: "<<rows<<"\r\n";
int image_size=0;
columns+=(3*columns)%4;
image_size=3*columns*rows;
ofs<<"Size of image"<<image_size<<"\r\n";
ifs.seekg(beg);
unsigned char R,G,B;
for(int i=beg; i<image_size+beg; i+=3)
{
ofs.seekp(i);
ofs<<char(0);
}
system("pause");
return 0;
}
There is no image file format that contains text like "Bitmap size: ", "Beginning of image: ", "Column number: ", "Row number: ", and "Size of image".
Even if there was such a file format, you are not writing "Beginning", you are writing "Beggining", and that would not work. Computers tend to be very partial to proper spelling.
Even if there was such a file format, it would not be the same as the file format that you are reading, because you are reading an int at offset 2 and interpreting it as some kind of file size, but you are not writing any size at offset 2 of your output file.
So, to cut a long story short, you have to have a very clear specification of the file format you are reading, (which you have told us nothing about,) and you also have to follow this exact same specification in writing the file.
Making up your own file format specification as you go along will not work.
Also, in the future, keep in mind that on stackoverflow, phrases like "it doesnt open properly" are not considered valid descriptions of technical issues. Be specific about precisely what is happening.
Hint: you appear to be trying to edit the file in-place, by seeking to individual bytes and overwriting them with zero. That won't work on an empty file. Copy the entire contents of the original file to the new filename, and then go seeking and overwriting bytes on the copy.
So I'll post my comment as answer:
I don't know much about BMP format, but... does it really contains strings such a "Size of image" or "Row number: "?
If not, remove ofs<<"Beggining of image: "<<beg<<"\r\n"; etc., I think that you meant cout instead of ofs.
Ok so in stead of reading a file to modify I just copy the whole content of the original file to the output file name and modify that. Thanks guys, and thanks Mike, I did that at your suggestion.

Binary file not holding data properly

Im currently trying to replace a text based file in my application with a binary one. Im just doing some early tests so the code isn't exactly safe but I'm having problems with the data.
When trying to read out the data it gets about half way before it starts coming back with incorrect results.
Im creating the file in c++ and my client application is c#. I think the problem is in my c++ (which I haven't used very much)
Where the problem is at the moment is I have a vector of a struct that is called DoubleVector3 which consists of 3 doubles
struct DoubleVector3 {
double x, y, z;
DoubleVector3(std::string line);
};
Im currently writing the variables individually to the file
void ObjElement::WriteToFile(std::string file) {
std::ofstream fileStream;
fileStream.open(file); //, ios::out | ios::binary);
// ^^problem was this line. it should be
// fileStream.open(file, std::ios_base::out | std::ios_base::binary);
fileStream << this->name << '\0';
fileStream << this->materialName << '\0';
int size = this->vertices.size();
fileStream.write((char*)&size,sizeof(size));
//i have another int written here
for (int i=0; i<this->vertices.size(); i++) {
fileStream.write((char*)&this->vertices[i].x, 8);
fileStream.write((char*)&this->vertices[i].y, 8);
fileStream.write((char*)&this->vertices[i].z, 8);
}
fileStream.close();
}
When I read the file in c# the first 6 sets of 3 doubles are all correct but then I start getting 0s and minus infinities
Am I doing anything obviously wrong in my WriteToFile code?
I have the file uploaded on mega if anyone needs to look at it
https://mega.co.nz/#!XEpHTSYR!87ihtCfnGXJJNn13iE6GIpeRhlhbabQHFfN88kr_BAk
(im writing the name and material in first then the number of vertices before the actual list of vertices)
Small side question - Should I delimit these doubles or just add them in one after the other?
To store binary data in a stream, you must add std::ios_base::binary to the stream's flags when opening it. Without this, the stream is opened in text mode and line-ending conversions can happen.
On Windows, line-ending conversions mean inserting a byte 0x0D (ASCII for carriage-return) before each 0x0A byte (ASCII for line-feed). Needless to say, this corrupts binary data.

Converting between text files and binary files in C++

For converting an ordinary text file into binary and then convert that binary file back to a text file so that the first text file equals with the last text file, I have wrote below code.
But the bintex text file and the final text file aren't equal. I don't know which part of code is incorrect.
Input sample ("bintex") contains this: 1983 1362
The result ("final") contains this: 959788084
which of course are not equal.
#include <iostream>
#include <fstream>
using namespace std;
int main() try
{
string name1 = "bintex", name2 = "texbin", name3 = "final";
ifstream ifs1(name1.c_str());
if(!ifs1) error("Can't open file for reading.");
vector<int>v1, v2;
int i;
while(ifs1.read(as_bytes(i), sizeof(int)));
v1.push_back(i);
ifs1.close();
ofstream ofs1(name2.c_str(), ios::binary);
if(!ofs1) error("Can't open file for writting.");
for(int i=0; i<v1.size(); i++)
ofs1 << v1[i];
ofs1.close();
ifstream ifs2(name2.c_str(), ios::binary);
if(!ifs2) error("Can't open file for reading.");
while(ifs2.read(as_bytes(i), sizeof(int)));
v2.push_back(i);
ifs2.close();
ofstream ofs2(name3.c_str());
if(!ofs2) error("Can't open file for writting.");
for(int i=0; i<v2.size(); i++)
ofs2 << v2[i];
ofs2.close();
keep_window_open();
return 0;
}
//********************************
catch(exception& e)
{
cerr << e.what() << endl;
keep_window_open();
return 0;
}
What is this?
while(ifs1.read(as_bytes(i), sizeof(int)));
It looks like a loop that reads all input and throws it away. The line afterward suggests that you should be using braces instead of a semicolon there, and doing the write in the block.
Your read and write operations aren't symmetric.
ifs1.read(as_bytes(i), sizeof(int))
grabs 4 bytes, and dumps the values into the char* its passed.
ofs1 << v1[i];
output the integer in v[i] as text. Those are very very different formats.
If you used >> to read you would have a lot more success.
To expound, the first read might look like this {'1','9','8','3'}, which I would guess would be the 959788084 you are seeing when you pun it to an int. Your second read would be {' ','1','3','6'}, like not what you'd hoped for either.
It's not clear (to me, at least), what you are trying to do.
When you say that the orginal file contains 1983 1262, what do
you really mean? That it contains two four byte integers, in
some unspecified format, whose values are 1983 and 1262? If so,
the problem is probably due to your machine not using the same
format. You cannot, in general, just read bytes (using
istream::read) and expect them to mean anything in your
machine's internal format. You have to read the bytes into
a buffer, and unformat them, according to the format with which
they were written.
Of course, opening a stream in binary mode doesn't mean that
the actual data are in some binary format; it just affects
things like how (or more strictly speaking, whether) line
endings are encoded, and how end of file is recognized.
(Strictly speaking, a binary file is not divided into lines. It
is just a sequence of bytes. Of course, some of those bytes
might have values that you, in your program, interpret and new
line characters.) If your file actually contains nine bytes
with characters corresponding to "1983 1362", then you'll have
to parse them as a text format, even if the file is written in
binary. You can do this by reading the entire file into
a string, and usingstd::istringstream; _or_, on most common
systems (but not necessarily on all exotics) by using>>` to
read, just as you would with a text file.
EDIT:
Just a simple reminder: you don't show the code for as_bytes,
but I'm willing to guess that there's a reinterpret_cast in
it. And any time you have to use a reinterpret cast, you can be
very sure that what you're doing isn't portable, and if it's
supposed to be portable, you're doing it wrong.

Problem with iostream,first write file in Binary mode then convert to and save ASCII

I am using iostream to collect data from a device.First I Write file in ASCII mode,it works well,but taking quite alot of time.Then I switsch to write in Binary mode and it is faster.
float dist[41616];
ofstream d_ofs( "numbers.dat",ios::out |ios::app|ios::binary);
// this is from the device API getting distance datas
res = GetDistances (hnd, dist, sizeof dist);
d_ofs.write((char*)&dist,sizeof dist);
d_ofs.close();
After the data collection,I have to convert the data inside "numbers.txt" to be readable by my tutor, in a txt file.I assume it is to change binary raw data to ASCII. so I read the file first and then write in ASCII format.
I get numbers,but unfortunately they are not the right numbers.I guess there should be special format for this convert process.But so far I have not found the solution due to my poor coding knowledge.So can anyone give me a hand? Many thanks in advance.
Here is my code:
double fnum[41616]; // here is the mistake,it should be float[]
ifstream in("numbers.dat", ios::in | ios::binary);
in.read((char *) &fnum, sizeof fnum);
MessageBox("Read File done");
ofstream fout("output.txt");
for(int k=0; k<41616; k++) // show values read from file
fout <<dec<<"\t" << fnum[k] ;
in.close();
fout.close();
Conclude:
The stupid mistake by me is in the data type.I wrote double[] instead of float[] in the second part.It is really embarrasing.Hopefully this post can help beginners like me.
You seem to be saving as float and reading as double. The read will (usually) be twice as large as the write so every double you read will actually be reading two of the written floats. You will get the wrong numbers because of this.
try changing the
double fnum[41616]
to
float fnum[41616]
Also, its probably for the best not to call a binary file *.txt as its a little confusing.
Its also confusing calling a double array fnum - as the f suggests floats