I created a binary file using a c++ program using protocol buffers. I had issues reading the binary file in my C# program, so I decided to write a small c++ program to test the reading.
My proto file is as follows
message TradeMessage {
required double timestamp = 1;
required string ric_code = 2;
required double price = 3;
required int64 size = 4;
required int64 AccumulatedVolume = 5;
}
When writing to protocol buffer, I first write the object type, then object length and the object itself.
coded_output->WriteLittleEndian32((int) ObjectType_Trade);
coded_output->WriteLittleEndian32(trade.ByteSize());
trade.SerializeToCodedStream(coded_output);
Now, when I am trying to read the same file in my c++ program i see strange behavior.
My reading code is as follows:
coded_input->ReadLittleEndian32(&objtype);
coded_input->ReadLittleEndian32(&objlen);
tMsg.ParseFromCodedStream(coded_input);
cout << "Expected Size = " << objlen << endl;
cout<<" Trade message received for: "<< tMsg.ric_code() << endl;
cout << "TradeMessage Size = " << tMsg.ByteSize() << endl;
In this case, i get following output
Expected Size = 33
Trade message received for: .CSAP0104
TradeMessage Size = 42
When I write to file, I write trade.ByteSize() as 33 bytes, but when I read the same object, the object ByteSize() is 42 bytes, which affects the rest of the data. I am not sure what is wrong in this. Please advice.
Regards,
Alok
This is guesswork, based on the above: when you use ParseFromCodedStream, you aren't actually limiting that to the objlen that you previously found; thus, if the stream contains any more data than this (i.e. that isn't the end of the file), the engine will try to keep reading to the EOF. You must cap the length to your expectation. I am not a C++ expert, so I can't offer direct guidance, but if this was C# (using protobuf-net):
objType = ProtoReader.DirectReadLittleEndianInt32(file);
len = ProtoReader.DirectReadLittleEndianInt32(file);
// assume GetObjectType returns typeof(TradeMessage) for our objType
Type type = GetObjectType(objType);
msg = RuntimeTypeModel.Default.Deserialize(file, null, type, len, null);
So apparently, i was doing a very silly mistake while creating the binary files. I did not open the file in binary mode when i wrote protobuf data to it causing it to add weird ascii characters in the middle. This caused an issue while reading the data using protobuf-net library. The issue is resolved here. Shouldn't have taken so long to resolve this.
Related
I've been trying to take a .txt document with three number entries, read those entries as strings and convert those entries in ints, then put them into an int array, but had no success in doing so and i have no clue as to why. Note that the entries as well as some variable names are pre determined by the assignment, additionally we have to use the std::stoi("string") command, which i am not familiar with nor has any syntax been provided to us (which is especially strange since we are usually not allowed to stray to far from the lecture material)
What I excpected to happen is that the numbers from the .txt file were converted into an array, however what actually happened is that an "unhandled exception" (my apologies if that term does not make sanes we have to programm in our native language) occured and the string library opened itself, marking the error on line 107. The problematic line in my code seems to be "auftraegearray[i++] = std::stoi(MengeanAuftraegen);"
int main()
{
std::fstream Auftraege;
Auftraege.open("Auftraege37.txt", std::ios::out);
Auftraege << "10" << std::endl;
Auftraege << "1" << std::endl;
Auftraege << "20" << std::endl;
Auftraege.close();
int i = 0;
int auftraegearray[4];
std::string MengeanAuftraegen;
Auftraege.open("Auftraege37.txt", std::ios::in);
while (!Auftraege.eof())
{
getline(Auftraege, MengeanAuftraegen);
std::cout << MengeanAuftraegen << std::endl;
auftraegearray[i++] = std::stoi(MengeanAuftraegen);
}
Auftraege.close();
void main(){
char *p;
p = new char[3];
strcpy_s(p, sizeof(p), "AB");
cout << p << endl << "input : ";
cin.get(p, 3);
delete []p;
}
Why does an error occurs in the 'delete'??
The errors do not occur elsewhere..
enter image description here
Based on my Igor's and Han's comments, it appears that using sizeof(p) in the strcpy_s function is actually your issue. p is a char *, doing sizeof(p) returns the size of the pointer (usually 4 or 8 depending on the architecture), not the size of the allocated array. In debug builds, the documentation for strcpy_s states:
The debug versions of these functions first fill the buffer with 0xFE. To disable this behavior, use _CrtSetDebugFillThreshold.
So, the runtime will fill 4 (or 8) bytes, which is larger than your allocated array into p, thus corrupting the heap.
I'm quite new to C++, but I'm used to some coding with R language. I started, a few weeks ago, to put together a small application that should copy and rename file pairs (.seq/.ab1). Result from a DNA sequencer analysis (renaming hundreds of them manually would be a real time waste, specially because we have lists with their new names).
Everything seemed to be fine, but the new files (those copied) appear with a "special character" in their names (right before the file type), it seeems like a space, but its not (I've replaced it with a space, and the file opened correctly). After deleting it the file can be oppened by its associated application, but with it, the aplication acusses the file to be corrupted.
The issue seems to come from the code related to ostringstream::str member function, but I honestly don't know how to fix it. I wonder if its not inserting a null character there, before I append the file type...
Here is the part of the code responsible. It gets the old and new names from a 2 column csv file, data separated by ";". Original data, and new (renamed files) data are kept in diferent directories, thats the reason I need to create a string with each file path inside a for loop. I intend to check old and new files content later, probably with memcmp. But first I need them to be correctly renamed.
I'm on a Ubuntu 14.04 (64 bit) machine with gcc 4.8.4 as compiler. I already excuse myself for the probably poor coding and bad english, I'm not a native speaker (writer, actually).
fNew.open(filename);
std::ostringstream oldSeqName (std::ostringstream::ate);
std::ostringstream newSeqName (std::ostringstream::ate);
std::ostringstream oldAb1Name (std::ostringstream::ate);
std::ostringstream newAb1Name (std::ostringstream::ate);
std::fstream log;
time_t now = time(0);
for (std::string nOld, nNew; getline(fNew, nOld, ';') && getline(fNew, nNew); )
{
std::cout << "Old Name: " << nOld << " -> New Name: " << nNew << std::endl;
// Keep a log of the name changes
log.open("NameChangesLog.txt", std::fstream::out | std::fstream::app);
log << ctime(&now) << " - " << "Old Name: " << nOld << " -> New Name: " << nNew << std::endl;
log.close();
// Create old seq files paths string
oldSeqName.str(nOld);
oldSeqName << ".seq";
std::string osn = "./Seq/" + oldSeqName.str();
// Create new seq files paths string
newSeqName.str(nNew);
newSeqName << ".seq";
std::string nsn = "./renamed/" + newSeqName.str();
std::ifstream ifseq(osn, std::ios::binary);
std::ofstream ofseq(nsn, std::ios::binary);
ofseq << ifseq.rdbuf();
ifseq.close();
ofseq.close();
// Create old ab1 files paths string
oldAb1Name.str(nOld);
oldAb1Name << ".ab1";
std::string oan = "./Seq/" + oldAb1Name.str();
// Create new abq files paths string
newAb1Name.str(nNew);
newAb1Name << ".ab1";
std::string nan = "./renamed/" + newAb1Name.str();
std::ifstream ifab1(oan, std::ios::binary);
std::ofstream ofab1(nan, std::ios::binary);
ofab1 << ifab1.rdbuf();
ifab1.close();
ofab1.close();
}
fNew.close();
Is the list file prepared on Windows machine? In that case it would have DOS line ending (\r\n) and is not well suited for getline on Unix. The character you see is likely \r. Make sure you use dos2unix utility before feeding the list file to your program
You probably forget to trim the values returned from getline, so they may still contain whitespace. Whitespace may be tricky to pick up by the application.
let me first thank you for taking the time to read this.
I'm trying to read a file in c++. Currently I have a method that allows the user to select a file in explorer and returns this as an 'std::string'. I then have to open this file, but the method I have for this uses const char*. Therefore I need to convert from one to the other.
If there is an easy method in windows for reading a file using a string instead then let me know as it would solve my entire problem.
When I convert from string to const char*, using str.c_str(), I get a lot of weird characters at the end. I've researched other topics with the same problem, but the answers all seem very specific for those projects, or say just stick to sting/vector instead. Obviously I would happily do this, but I don't have a method that opens the file using a string/vector.
Any help is appreciated :) The code and output of where this occurs is pasted below.
*SOURCE
std::string f;
if (LOWORD(wParam) == 1) {
f = openFile();
char *fchar = new char[f.size()+1]; // +1 to account for \0 byte
//char *fchar = std::vector[1];
std::strncpy(fchar, f.c_str(), f.size());
file1 = fchar;
std::cout<<"string size: " << f.size() << std::endl;
std::cout<<"string: " << f << std::endl;
std::cout<<"fchar: " << fchar << std::endl;
std::cout<<"file1: " << file1 << std::endl;
}
OUTPUT
string size: 33
string: C:\Users\Joseph\Pictures\back_raw
fchar: C:\Users\Joseph\Pictures\back_raw═²²²²½½½½½½½½¯■
file1: C:\Users\Joseph\Pictures\back_raw═²²²²½½½½½½½½¯■**
std::strncpy() does not place a `\0' character at the end of the string. See http://www.cplusplus.com/reference/clibrary/cstring/strncpy/. You need to copy that as well:
std::strncpy(fchar, f.c_str(), f.size() + 1);
Where is file1 declared ?
What about openFile ? (would like to know its return type)
Could you try to manually put that '\0' ? IMHO, your char* is simply lacking the \0 at the end...
Make sure you put a \0 at the end, everywhere you need to.
I have a function in my program that outputs a data structure that consists of three doubles in two formats, one text and one binary.
When I run the program in debug and release modes, I end up with different binary outputs but identical text outputs. What is going on?
Here is the binary output code:
void outputPoints(xyz* points, string description, int length, param parameters)
{
stringstream index;
index.str("");
index << setw( 3 ) << setfill( '0' ) << parameters.stage;
string outputName = parameters.baseFileName + " " + index.str() + " " + description + ".bin"; // create file name
ofstream output; // create output object
cout << "Output " << outputName.c_str() << "...";
output.open(outputName.c_str(), std::ios::binary | std::ios::out); // open or create file for output
output.write(reinterpret_cast<char*>(points), (sizeof(xyz) * length));
output.close(); // close output object
cout << "done" << endl;
}
The debug build usually initializes variables with some patterns. Usually data allocated has the content CDCD, deleted objects are overwritten with FEEE. The CDCD pattern is overwritten when you initialize your variables. The release build doesn't initiliaze with these patterns.
It's worth to check your program for uninitialized variables. You can define a Dump function that just prints the (fist few bytes of) the suspected variables.
I don't know whether you got a solution for your issue and I did not look at your code.
I had the same issue because I was adding unsigned char and unsigned short and saving into unsigned short. I changed all variables to unsigned short and the issue was solved.