?
Solved

Write to binary File,struct with AnsiString.

Posted on 2006-11-06
12
Medium Priority
?
4,765 Views
Last Modified: 2013-11-17
Hello everyone.
I am trying to write to a file a struct of the following type:

typedef struct ResFileStr_
{
 AnsiString ImagePath;
 int RecognitionMethod;
 int Background,ThresholdMethod;
 float Recall,Precission;
}ResFileStr;

So i create the file with fp=fopen("test.res",wb") and then i write a struct with fwrite(&rec,sizeof rec,1,fp).
The rec struct data is something like this:rec.ImagePath="C:\\di1\\dir2\\file.jpg" rec.RecognitionMethod=2 and so on.
Then when i try to open it and read it all fields are the way they should be except the ImagePath field.
I fp=fopen("test.res","rb") and i fread(&rec,sizeof rec,1,fp) and rec.imagePath=@#^saa//566\\\5656^^$%233..."something like this.Any ideas.
Thanks In Advance.
Sotiris Zegiannis,Greece,TUOA,Computer Science Department.

0
Comment
Question by:sotiris_zegiannis
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 3
  • 2
  • +1
12 Comments
 
LVL 16

Expert Comment

by:George Tokas
ID: 17881456
Before i post my oppinion about the way I THINK its better:
Open the file you saved with a hex editor.
Check out if the bytes of the field is valid.
Maybe there is something wrong there.
That's for starters.

Now:
You are using the "c" way...
It will be better to use the C++ Builder way as explained at online help...

But check out first the file and we will discuss again...

George Tokas.
0
 

Author Comment

by:sotiris_zegiannis
ID: 17881822
I have already used the c++ way,if that's what you mean,by using the ifstream/ofstream classes,but the problem remains.Moreover the files are ok as far as validation is concerned.
0
 
LVL 16

Expert Comment

by:George Tokas
ID: 17882553
>>I have already used the c++ way,if that's what you mean,by using the ifstream/ofstream classes
No I don't mean that...
I mean:
void __fastcall TForm1::Button1Click(TObject *Sender)

{
  int iFileHandle;
  int iFileLength;
  int iBytesRead;
  char *pszBuffer;
  if (OpenDialog1->Execute())
  {
    try
    {
      iFileHandle = FileOpen(OpenDialog1->FileName, fmOpenRead);
      iFileLength = FileSeek(iFileHandle,0,2);
      FileSeek(iFileHandle,0,0);
      pszBuffer = newchar[iFileLength+1];
      iBytesRead = FileRead(iFileHandle, pszBuffer, iFileLength);
      FileClose(iFileHandle);

      for (int i=0;i<iBytesRead;i++)
      {
        StringGrid1->RowCount += 1;
        StringGrid1->Cells[1][i+1] = pszBuffer[i];
        StringGrid1->Cells[2][i+1] = IntToStr((int)pszBuffer[i]);
      }
      delete [] pszBuffer;
    }
    catch(...)
    {
      Application->MessageBox("Can't perform one of the following file operations: Open, Seek, Read, Close.", "File Error", IDOK);
    }
  }
}


That came from online help of BCB6 using search for "FileOpen" and the topic is:
"FileOpen, FileSeek, FileRead Example"
It will be better if you post a bit of code to help you.

George.
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
LVL 25

Accepted Solution

by:
kode99 earned 2000 total points
ID: 17883301
You would need to change the structure to use a char array in place of the AnsiString to make this work.

typedef struct ResFileStr_
{
char ImagePath[255];
 int RecognitionMethod;
 int Background,ThresholdMethod;
 float Recall,Precission;
}ResFileStr;

Although it is in a plain structure,  the AnsiString is still not a plain data type.  It is kinda like only part of it is written out so when you try to read it back you don't get all the information you need reconstruct it properly.
 
POD - Plain Old Data,
http://www.parashift.com/c++-faq-lite/intrinsic-types.html#faq-26.7


0
 
LVL 18

Expert Comment

by:Jose Parrot
ID: 17893468
Hi,

Despite its type name, AnsiString is not a sequence of characters as one can think at glance. So you never will see Ansi characters sequence by reflecting the string form, although the content is the same.
So, if you write an AnsiString, must read it as a AnsiString; if you want to "type" the record and see characters as expected, say "C:\\di1\\dir2\\file.jpg", you must save it as char type, as kode99 suggests.

If you don't want to change so much your code, you can convert MyAnsiString to char simply by using MyAnsiString.c_str() conversion.

Also, as matter of consistency, when you write the file, you should open it as "wt" for text, instead of "wb" for binary. And, of course, for reading, open such file as "rt". That way your file will be pure ASCII characters and you can "type" it and read its content without problems.

Jose
0
 
LVL 16

Expert Comment

by:George Tokas
ID: 17894444
>>Despite its type name, AnsiString is not a sequence of characters as one can think at glance
String.c_str() is....
I have used AnsiStrings the way the author describe and didn't have any problem using C++Builder functions...
Check out C++ Builder Developers Guide 5 & 6....

George Tokas.
0
 
LVL 18

Expert Comment

by:Jose Parrot
ID: 17894744
I'm talking about c code to use AnsiString. Not Builder c++.
Example:
     AnsiString ImagePath;
     fopen(ImagePath.c_str(),"rb");

Jose
0
 
LVL 16

Expert Comment

by:George Tokas
ID: 17895079
>>I'm talking about c code to use AnsiString. Not Builder c++.
If I'm not mistaken THIS IS C++ BUILDER TA...
What I wanted to say is that when we have a superset to use (BCB) why use the subset for (c)...
But because of the university the author is, I think that stucked with that...
No offence everybody....
No matter of any superiority over anything...
Just an oppinion...

George Tokas.
0
 
LVL 25

Expert Comment

by:kode99
ID: 17896141
You just have to be careful when mixing c style code with c++.  This is an example of what can happen.  No error indicated it just will not work properly.  By adding the AnsiString you are adding a class to a struct.  A class contains functions and by definition a c struct is a data only form.  So functions like fwrite/fread which work fine for c struct variables just cannot handle the complexity of a c++ class.

For most situations the AnsiString in the struct will work just fine.  If you want to see another malfunction do a 'sizeof' on a AnsiString (without the c_str()),  the result will always be 4 no matter how long the string data is.  Not exactly the result intended and also no error indicated.

Unfortunatly c_str() will do no good for changing how the struct will be written to disk.  It would have to be used to convert AnsiString to a char array when assigning the ImagePath variable in the structure.  The downside is that you have to used a fixed length array for the name,  AnsiString is very convienient.

It would also be possible to write the ImagePath with 2 write operations in addition to writing the structure.  So write a integer length of the string first,  followed by the actual string and then write the structure and then the read back would have to be similar.  I think this is a hack though and could come back to haunt you later.

I would say the c++ way would be to use a class instead of a struct and then build the file io into the class properly.  In the end this approach leads to cleaner code and is much easier to manage in the long run.
0
 
LVL 18

Expert Comment

by:Jose Parrot
ID: 17897757
Hello, Sotiris Zegiannis,

Seems all comments posted confirm not mixing c and c++ as a good practice.
The c++ approach by using a class instead of a struct is the suggestion we would agree on, as pointed by kode99.

As you are using Builder C++, it is prefferable to take advantage of its features besides that of C++. And, if yours is an application to image processing, TImage is a perfect class to work with. You can draw primitives, load images directly, save and print its contents easely.

So, even if you'll need work a bit more, let me suggest to remake your application entirely by using C++. You can start by using the code provided by George Tokas. As you can see it uses a dialog to chose the image file you want, which is far superior to console style interactivity.

Please accept my appologies, extensive to the experts around, if I made more confusion than clarifying the subject in my previous comment, although the objective was to contribute.

Jose
0
 

Author Comment

by:sotiris_zegiannis
ID: 17901204
I really appreciate everybone's help.At the end you where right code99,you can't mix c && c++.I put an array of chars in the struct and it worked fine.Thank you all very much.
Take Care.
Sotos.
0
 
LVL 16

Expert Comment

by:George Tokas
ID: 17911212
I have something to add here.
I waited some time before posting this just to prove the point that I don't feel any kind of anger.
So dear Sotiri,
First of all:
>>At the end you where right code99,you can't mix c && c++
Yes you can. You can mix whatever you like even CPU register status. The problem is the right way to do it.

I can understand your "C" obsession of some kind because I know what you learn at the University. Many years OUTDATED.
My recomendation was to use BCB functions. And the reason is a bit simple.
If you are using BCB to write and compile a c listing it's like having a Ferrari on the road and drive it like a VW Beatle and the OLDEST of the models. That vehicle belongs to the museum along with c. Of course the same apply for VS and some other compilers.
Since we are almost all working in Windows what we are doing is to use the API one way or the other. Lower level functions at the most cases don't do any good.

There is a realy long talk about the above and I hope you Sotiri and the rest of the experts that you can see my point here.

George Tokas.
0

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Programmer's Notepad is, one of the best free text editing tools available, simply because the developers appear to have second-guessed every weird problem or issue a programmer is likely to run into. One of these problems is selecting and deleti…
Here is a helpful source code for C++ Builder programmers that allows you to manage and manipulate HTML content from C++ code, while also handling HTML events like onclick, onmouseover, ... Some objects defined and used in this source include: …
THe viewer will learn how to use NetBeans IDE 8.0 for Windows to perform CRUD operations on a MySql database.
The viewer will learn how to use and create keystrokes in Netbeans IDE 8.0 for Windows.

801 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question