Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Read a binary file 1

Status
Not open for further replies.

balajee

Programmer
Jun 29, 2000
134
NZ
Hi

I am having a binary file produced by Lahey Fortran95. It has Strings, integers and non integer values. I know the format of the file. How do I read the strings, integer and non integer values and display them in messagebox to confirm if I am reading it OK. I would like to store the numerical values in arrays.

Could someone give me the code outline using Cfile preferably.

Thanks,
 
would need to know a little about the format...i.e. are the strings, numbers etc... on seperate lines or are they "," seperated...or something else?
 
The data has an integer value at the front and at the end.
 
Would it be possible to see some lines of that file you want to read?
[infinity]


Greetings Andreas
 
The file has a structure similar to this. If I can get a code to read this that will be good. Example is given below:

"9 My string 220 50 20 30 25 2.34 15 10 2.3E5 25"

When Lahey Fortran95 writes this file, the numbers (can be an integer, long integer, single or double) have an integer value at the begining and at end. The strings have an integer at the begining which specifies the length of the string. In the above example the first integer represnts the length of the string, then we have integers for actual values at the start and end. There are no spaces in between. The spaces shown in the above sample line are for your understanding only.

hope this is clear,

Thanks
 
Sorry, but I do not understand exactly. How do you know, whan a number stops, if there are no spaces or anything else between? Explain a bit more...

My first tip is:
...
#include "stdafx.h"
#include <iostream.h>
...
enum {IsReal, IsInt, IsString} TypeOfString;
...
TypeOfString GetType(CString StringToTest){
TypeOfString ReturnValue;
//any code you need to decide between the possibilities
return ReturnValue;
};

CString ToString(CString StringToConvert){
int i=0;
while (('0'<=StringToConvert) && (StringToConvert<='9')) i++;
return StringToConvert.Right(StringToConvert.GetLength()-i);
//Pay attention a String with numbers in the beginning is reduced to the same without numbers, that means
//&quot;61st Try&quot; will be &quot;st Try&quot;
};

...
ifstream in(&quot;FortranFile.txt&quot;,ios::nocreate);
if (in.is_open() == 0){
//File not opened
}else{
char *pBuffer = (char *) malloc (1000);
CString Line, Paragraph;
int PgStart,PgFound;
while (! in.eof()){
in.getline(pBuffer, 1000, '\n');
Line= pBuffer;

PgStart=0;PgFound=0;
while (PgFound>-1){
PgFound=Line.Find(' ',PgStart);
Paragraph=Line.Mid(PgStart, PgFound-PgStart);
PgStart=PgFound+1;
switch (GetType(Paragraph)){
case IsString: AnyStringYouLike=ToString(Paragraph);
break;
case IsReal: AnyRealYouLike = atof(Paragraph);
break;
case IsInt: AnyIntYouLike = atoi(Paragraph);
break;
default:
SendAnyErrorMessageYouLike();
};
};
};
};
in.close()
...

Hope it will help, tell me more ...
[pacman]


Greetings Andreas
 
I have read this file using VB6. Fortran uses 4 bytes for integer/double. I know the exact format of this file. So I know after the a string there is an integer or double.
Now let us take the example string I gave you. I would read first 4 bytes. Then next 9 bytes as I know that the string is 9 characters long. Next I read 4 bytes for an integer(220) which is at the end of the string. So I have finished reading the string now. I am keeping the track of the bytes read.

Next I want to read the value 20 in the sample string which has integer 50 at the start and 30 at the end. So
I read 4 bytes for the integer at the start. Then read next 4 bytes for our value to be read .i.e 20. Next read 4 bytes for the end value ie. 30. So you have finished reading the value 20. and it goes on like this. So to read a data value from the file you read 3 integers each time and leave the first and last values.

I have done some coding I am giving here: The file I am reading here has first 80 char string and then integer or double values. This code displays first letter &quot;P&quot; insteasd of an integer 80. Next it displays the string coorectly. Further coding I have not done as I am not able to get the integer values. May be you can modify this code so that I can read the integer/double values as well. Here C++ uses 2 bytes for integer values so I am reading 2 bytes for an integer.

The code is like this:

CFile file(&quot;3dd.out&quot;, CFile::modeRead);
// Read data from the file.
char s[80];

int bytesRead = file.Read(s, 2);
s[bytesRead] = 0;
CString message = s;
AfxMessageBox(message);

file.Seek (2, CFile::current);
bytesRead = file.Read(s, 80);
s[bytesRead] = 0;
message = s;
AfxMessageBox(message);

Sorry this has gone very long. Hope this makes sense.

Thanks,
 
that means you don't read a string but

0x00 0x09 'M' 'y' ' ' 'S' 't' 'r' 'i' 'n' 'g'
0x00 220
0x00 50
0x00 20
0x00 30
0x00 25
0x?? 0x?? 0x?? 0x??
0x00 15
0x00 10
0x?? 0x?? 0x?? 0x??
0x00 25

???

So I would read linear, that means I suppuse, that with every sector you read you know the length of the next one, so you can do it like you did, but you had to keep in memory some things:

CFile file(&quot;3dd.out&quot;, CFile::modeRead);
// Read data from the file.
int *MyInt; //AM Pointer to int
float *MyReal; //AM Pointer to float
//float 4byte 3.4E +/- 38 (7 digits)
char s[80];

MyInt = &s[0];
MyReal = &s[0];
int bytesRead = file.Read(s, 2);//AM 2 bytes 0x00 0x09 in example
//AM s[bytesRead] = 0;
CString message;
message.Format(&quot;My integer %i&quot;,*MyInt);
AfxMessageBox(message);

//AM You read 2 bytes ... file.Seek (2, CFile::current);
bytesRead = file.Read(s, *MyInt); //AM if you know, that it is a string with length you read before...
s[bytesRead] = 0;
message = s;
AfxMessageBox(message);

//AM to read real:
bytesRead = file.Read(s, 4); //AM if you know, that it is a real
message.Format(&quot;My Real: %f&quot;,*MyReal);
AfxMessageBox(message);


Does it help you?
[worm]

Greetings Andreas
 
I have modified the code as per your suggestions above but
It gives me an error:

error C2440: '=' : cannot convert from 'char *' to 'int *'

at

MyInt = &s[0];
MyReal = &s[0];

Do you know what's haapening? I am yet understand these pointers.

Thanks,
 
sorry, i forgot to do this :

MyInt = (int *)&s[0];
MyReal = (float *)&s[0];

The compiler doesn't know that you really read an int or float, so you hev to inforce that by explicit typecasting...

Does it work now?
[elephant2]


Greetings Andreas
 
In General should it be better to implement functions like

float ReadFloat(CFile f){
float buffer;
f.read(buffer,4);
return buffer;
};

int ReadInt(CFile f){
int buffer;
f.read(buffer,2);
return buffer;
};

CString ReadString(CFile f){
int length;
char *buffer,*last;
length = ReadInt(f);
buffer = (char*)malloc(length+1);
f.read(*buffer,length);
last=buffer+length;
*last=0;
return CString(buffer);
};

and to do things like

...
CFile file(&quot;3dd.out&quot;, CFile::modeRead);
AnyInt=ReadInt(f);
AnotherInt=ReadInt(f);
AnyString=ReadString(f);
...

try it and tell me
[roll2]



Greetings Andreas
 
The error is not there but The first integer is expected to be &quot;80&quot; however its showing &quot;-872415152&quot;.
 
the sense of the code is to set the pointer to the buffer.
try

MyInt = (int *)s[0];
MyReal = (float *)s[0];

or

MyInt = (int *)&s;
MyReal = (float *)&s;

or

MyInt = (int *)s;
MyReal = (float *)s;

the problem for me is, that I up to now dont know exactly in what cases c++ is working with pointers automaticly, especially with structs, arrays, strings...

so I have to try this every time with the compiler ...

(Sorry, I work in c++ for 2 month...)

X-)


Greetings Andreas
 
Sorry did not work any of these options. The result is same &quot;-872415152&quot;.
 
sorry...

I think I got it...

try short int instead of int... (int has maybe 4 byte in the version of c++ you work in. read the help about that)
can you read the float correctly?

(-::)

Greetings Andreas
 
With short int its showing &quot;-13108&quot;.
Is it possible for you to give me code which writes one line of an integer, a string and again an integer and then a float. And then read this line. I can then simulate the code to read my file.

Thanks,
 
I tried this, it worked.
First write file, then read file

content: 5, 5, &quot;Hallo&quot;, 5, 3.1415...

read: 5, &quot;Hallo&quot;, 5, 3.14...

//////////////////////////////////////////////////////////////////////
// Konstruktion/Destruktion
//////////////////////////////////////////////////////////////////////

ReadFortran::ReadFortran()
{
/* CFile file(&quot;test.file&quot;, CFile::modeRead);
AnyInt=ReadInt(f);
AnotherInt=ReadInt(f);
AnyString=ReadString(f);
file.Close();*/
}

ReadFortran::~ReadFortran()
{

}

float ReadFloat(CFile &f){
float buffer;
f.Read(&buffer,4);
return buffer;
};

int ReadInt(CFile &f){
short int buffer;
f.Read(&buffer,2);
return buffer;
};

CString ReadString(CFile &f){
short int length;
char *buffer,*last;
length = ReadInt(f);
buffer = (char*)new char[length+1];
f.Read((void*)buffer,length);
last=buffer+length;
*last=0;
CString x=buffer;
delete [] buffer;
return x;
};

void ReadFortran::WriteFile(CString FileName)
{
short int a=5;char b[]=&quot;Hallo&quot;;float c=3.14159265;
CFile f(FileName, CFile::modeWrite|CFile::modeCreate);
f.Write(&a,sizeof(a));
f.Write(&a,sizeof(a));
f.Write(&b[0],sizeof(b)-1);
f.Write(&a,sizeof(a));
f.Write(&c,sizeof(c));
f.Close();
}

void ReadFortran::ReadFile(CString FileName)
{
short int a=5;char b[]=&quot;Hallo&quot;;float c;
CString s,help;
CFile f(FileName, CFile::modeRead);
Line=&quot;This is the read line: &quot;;
a=ReadInt(f);
help.Format(&quot;%s1: int #%3i# &quot;,Line,a);
Line=help;

s=ReadString(f);
help.Format(&quot;%s2: string #%s# &quot;,Line,s);
Line=help;

a=ReadInt(f);
help.Format(&quot;%s3: int #%3i#&quot;,Line,a);
Line=help;

c=ReadFloat(f);
help.Format(&quot;%s4: float #%10.5f#&quot;,Line,c);
Line=help;

}

Good luck
:cool:

Greetings Andreas
 
Sorry just one question. What is that &quot;Line&quot;. What is it supposed to do? When I used it it gave me an error: Undeclared identifier. I just removed it. Used message box.
 
sorry, should have said:

I wrote 3 global functions: ReadInt, ReadFloat, ReadString

These are to be used by you.

Besides I wrote a small testclass i called ReadFortran (better should have been anything with C at the beginning :) )
This Class consists of 2 member-functions
(ReadFile, WriteFile) and 1 member value (CString Line)
This class gives a simple function that writes a small count of bytes into a file and another that can read exact this configuration of bytes from a file.

Your task is to implement other functions, that depend on the real file format you heve to know, using the 3 global functions ReadInt, ReadFloat, ReadString.

Everything clear?

(and thx for the STAR [smurf])



Greetings Andreas
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top