replica nfl jerseysreplica nfl jerseyssoccer jerseyreplica nfl jerseys forums.silverfrost.com :: View topic - Binary file in FORTRAN
forums.silverfrost.com Forum Index forums.silverfrost.com
Welcome to the Silverfrost forums
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Binary file in FORTRAN
Goto page Previous  1, 2
 
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> General
View previous topic :: View next topic  
Author Message
LitusSaxonicum



Joined: 23 Aug 2005
Posts: 2419
Location: Yateley, Hants, UK

PostPosted: Tue Aug 02, 2011 2:12 pm    Post subject: Reply with quote

Christy,

The "header" is the set of bytes at the beginning of something (in your case, the array), and the "trailer" is a set of bytes after it. What these header and trailer sections consist of is system dependent, and they could consist of nothing at all. The header, trailer and the data in between make up one record. A file then consists of a set of records.

Imagine a Fortran program source code. Each line is a record. There isn't any header to each line, but the trailer consists of a CR, LF sequence. The Fortran program is made up of a number of these statements (records).

As to binary values, the computer doesn't record bytes with readable characters, it just keeps a whole list of 1 and 0 (on or off) values. That's binary. These are maddening to contemplate. Therefore people interpret them in different ways. One way is to take half a byte (4 bits) and represent it as:

0, 1, 2, .... 9, A, B, C, D, E or F. (there are 16 possible combinations).

Then, you can see what is in a byte as maybe 0E or CF (FF=255 or 11111111, 00 is 00000000). That is called hexadecimal. But binary is how the computer works.

As there are 256 possible combinations in a whole byte, we could also take each byte as representing a single character. This can cover the whole alphabet in both upper and lower case, and lots of symbols and control codes (like CR and LF). Deep down, however, it's all binary 0 and 1 ...

Eddie
Back to top
View user's profile Send private message
christyleomin



Joined: 08 Apr 2011
Posts: 155

PostPosted: Wed Aug 03, 2011 1:04 pm    Post subject: Reply with quote

That means the binary file that is generated is not readable, right? IT comprises of just 0's and 1's.Correct?

Basically, I have a l FE (finite element analysis) software (say software 'A') and want to write a binary file through my own program (say 'MY FE program') so that software A understands it.

I have the docuemntation of binary file contents of software A . I have some binary files which the software A has written whilst I worked on it.

Are the binary files of software A readable?
Back to top
View user's profile Send private message
IanLambley



Joined: 17 Dec 2006
Posts: 506
Location: Sunderland

PostPosted: Wed Aug 03, 2011 1:32 pm    Post subject: Reply with quote

If the unformatted/binary files do have a header and trailer for each record which conforms to the FTN95 standard then yes, they can be read directly.

If they conform to the other standard, then it is harder to read them. The code that I posted above converts between the two unformatted methods. You could run the file from the non-FTN95 through the conversion routine and then open it in FTN95 to read it. If you write a file from FTN95, run it through the other converter for reading by your FE program.

Alternatively if they are fixed length records then the file will be readable with "direct" access methods and the code I gave above is not useful as there is no header or trailer.

The beauty of binary files is that nothing is lost when writing and reading. the data. The internal representation of the data is directly stored in the file and can reduce file size compared to formatted. For example for a real*8 value which gives say 17 decimal digits precision, it takes 8 bytes to store in unformatte/binary, but you might need a format as ridiculous as F35.17 to store it to the full precision in formatted mode, i.e 35 bytes. Anything less can result in loss of precision.
Ian
Back to top
View user's profile Send private message Send e-mail
LitusSaxonicum



Joined: 23 Aug 2005
Posts: 2419
Location: Yateley, Hants, UK

PostPosted: Wed Aug 03, 2011 1:38 pm    Post subject: Reply with quote

Christy,

Not readable by you or I, just using something like Notepad. Correct.
Notepad takes each byte, and interprets the 0 and 1 pattern as a character. Some of the resulting characters are invisible, which makes it even harder.

I'll start by considering that you want to READ a file written by the pre-existing program, and then go on to the difficulties in writing a file for it to read.

Your pre-existing Fortran program probably wrote a bunch of INTEGER values each time as 4 bytes, and a bunch of REAL values as 8 bytes at a time. Unlike a text file, there are no "blank" characters between the values, you just have a sequence of bytes, which means a sequence of 0 and 1 values.

The first problem you have in reading a file is to know which bytes are an INTEGER, and which bytes are a REAL . OK, you get that from the FE program documentation.

The next problem is sorting out any header and trailer for each record. This may vary not only computer system to system (if you are using a mainframe) or compiler to compiler - e.g. it is different for Intel Fortran from FTN95. OK, you get the answer to that from help by John, for example.

Finally, you have the problem with which order the bytes are written in. This is the "big-endian" and "little-endian" stuff. It's difficult in binary, so suppose we take a 4-digit decimal integer, such as 8632. Big-endian is just this way round, 8 - 6 - 3 - 2. Little endian stores it (in effect) 2 - 3 - 6 - 8. If your file was written by a code compiled with a different compiler, you will only know if you read the relevant documentation. It would be so much easier if both codes were compiled with FTN95 on a PC! The PC cpu has a native way of doing it, but any compiler can do it however it sees fit.

The problem you have in writing a file for reading by the other programme contains the same difficulties, but in reverse.

Transferring data as unformatted files always has this difficulty. Formatted files are bad enough, as the trailer to each line could be CR LF or just CR, but that is minor compared to unformatted.

Eddie

PS. I simplified the 8632 case. It is more like 86 - 32 versus 32 - 86 !

PPS. Big and little endian refer to whether the most significant bytes come first or last. The name derives from"Gulliver's Travels" where the hero travelled to various foreign lands, in one he witnessed a war between factions over whether to eat a boiled egg from the wide (big end) or narrow (little end) end! Whoever named this had a literary background, clearly. There used to be big arguments about which version of endian should be used.

The binary files that were written are readable, once you know the 3 tricks above to read them.

E
Back to top
View user's profile Send private message
christyleomin



Joined: 08 Apr 2011
Posts: 155

PostPosted: Thu Aug 04, 2011 12:52 am    Post subject: Reply with quote

I have downlaoded hexeditor which reads a binary file, it comes like this;

4c 53 2d 44 59 4e 41 20 75 73 65 72 20 69 6e 70
75 74 20 20 20 20 20 20 20 20 20 20 20 20 20 20
20 20 cb 03 00 00 10 95 2f 03 00 00 70 44 04 00
00 00 2d 24 00 00 06 00 00 00 09 00 00 00 01 00
00 00 00 00 00 00 01 00 00 00 00 00 00 00 40 1f
00 00 09 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 92

However, as Eddie said, this is in 0's and 1's.

I'm really clueless how to start, anything suggested?[/list]
Back to top
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 2621
Location: Sydney

PostPosted: Thu Aug 04, 2011 1:13 am    Post subject: Reply with quote

Quote:
Are the binary files of software A readable?

Yes they are. You must know the OPEN and the WRITE statements that generated them and probably the compiler that generated the fortran code. It is then simply a matter of providing the OPEN and READ statements that suit what was written. You need to provide the READ statement that suits the WRITE. This should always be documented for other users. I would expect there should be a defined data structure to be used.

Binary and text files are very similar. You just need the appropriate OPEN, READ and WRITE to use them.
Binary files are preferred as they retain maximum precision of the numbers being stored. They are more typically used.
Text files can be simpler, as you can more easily look at the file (with NOTEPAD) and see what is in the file. I prefer text files, especially if I want to review what information is being transferred, or there will be a time lag between usage.

To open a binary sequential file use:
OPEN ( UNIT=11, FILE='temporary_file', STATUS='UNKNOWN', &
ACCESS='SEQUENTIAL', FORM='UNFORMATTED', &
ACTION='READWRITE', IOSTAT=iostat)
To open a sequential text file use:
OPEN ( UNIT=11, FILE='temporary_file', STATUS='UNKNOWN', &
ACCESS='SEQUENTIAL', FORM='FORMATTED', &
ACTION='READWRITE', IOSTAT=iostat)
To open a binary direct access file use:
OPEN ( UNIT=11, FILE='temporary_file', STATUS='UNKNOWN', &
ACCESS='DIRECT', FORM='UNFORMATTED', RECL=1000, &
ACTION='READWRITE', IOSTAT=iostat)

The only problem is that files opened as sequential unformatted files also store extra information to identify the amount of information written by each WRITE statement, and this extra information differs between compilers. Direct access unformatted files do not have this problem.
All comments about this problem assume that different fortran compilers have been used for program A and program B.
Depending on which program you have access to ( A or B ) determines the approach you should take.
If I was to approach this problem, I would use ACCESS='TRANSPARENT' and read or write the header and footer in the way the other program expected.

The style of your questions implies you are new to using binary files, although you have implied you have/had access to program A and have written the binary files. The proof of your work is how program B reads what you have written. If you don't have access to program B, you may need to use an approach Ian has recommended and convert the files to a "record" structure that program B's compiler expects.
Test it out !

John
Back to top
View user's profile Send private message
christyleomin



Joined: 08 Apr 2011
Posts: 155

PostPosted: Thu Aug 04, 2011 1:29 am    Post subject: Reply with quote

In addition to above;

Let me start with something simple;

(1) Let us say I have a "MY FE PROGRAM"

I have;

subroutine ReadMyFEProgramData

call GetNodes !!I get number of nodes
call GetNumberOFElements !!I get number of elements

end

(2) Now, I want to begin writing my binary file which ANOTHER (say program ''A'') program can read. I know that; the variables for number of nodes and number of elements in program 'A' are named as NNODES And NELMENTS respectively.

Number of words of NNODES And NELMENTS is 1 (each) and disk address is 10 and 11 respectively.

The word size id 4 bytes for single precision and 8 bytes for double precision.

The databases (i.e.binary file) are written as word addressable fixed length binary files. The actual length depends on the amount of data saved, but will always be a multiple of 512 words (4 or 8 bytes each). Since it is likely that the database cannot be contained in a single file of length, FEMLEN,the data will spread over several files known as a family of files. Having a set of files enables them to be handled more easily than a single very large file. The root name for a family is the name of the first file member.

With this information, can anyone please guide me how to write NNODES and NELMNTS to a binary file?

After writing, PROGRAM A understands the binary file I wrote and can do what it wants with the data in binary file.
Back to top
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 2621
Location: Sydney

PostPosted: Thu Aug 04, 2011 3:47 am    Post subject: Reply with quote

I've recommended you read the fortran documentation about Input/Output, as your grasp of the subject appears poor.
A simple example of what you may need : ( you could improve much of it depending on other requirements)
Code:
      subroutine write_FE_info (num_nodes, XYZ, num_elem, elem_type, elem_connect)
!
!  Routine to dump Model to binary file
!
      integer*4 num_nodes, num_elem, elem_type(*), elem_connect(10,*)
      real*8    XYZ(3,*)
!
      character file_name*40
      integer*4 iostat, i, j, node_count(6), nn
      data node_count / 2, 2, 4, 4, 8, 4 /
!
      file_name = 'transfer_file.bin'
      open (unit=21, file=file_name, form='UNFORMATTED', iostat=iostat)
        write (*,*) ' File ',trim(file_name),' Opened for writing: iostat=', iostat
!
      write (21) num_nodes
      write (21) ((xyz(i,j),i=1,3),j=1,num_nodes)
!
      write (21) num_elem
      write (21) (elem_type(i),i=1,num_elem)
      do j = 1,num_elem
         if (elem_type(j) < 1) cycle
         nn = node_count(elem_type(j))
         write (21) j, (elem_connect(i,j),i=1,nn)
      end do
!
      close (unit=21)
!
      end subroutine write_FE_info

      subroutine read_FE_info (num_nodes, XYZ, num_elem, elem_type, elem_connect)
!
!  Routine to read Model from binary file
!
      integer*4 num_nodes, num_elem, elem_type(*), elem_connect(10,*)
      real*8    XYZ(3,*)
!
      character file_name*40
      integer*4 iostat, i, j, k, node_count(6), nn
      data node_count / 2, 2, 4, 4, 8, 4 /
!
      file_name = 'transfer_file.bin'
      open (unit=21, file=file_name, form='UNFORMATTED', status='OLD', iostat=iostat)
        write (*,*) ' File ',trim(file_name),' Opened for reading: iostat=', iostat
!
      read (21, iostat=iostat) num_nodes
        write (*,*) num_nodes, ' nodes in model', iostat
      read (21, iostat=iostat) ((xyz(i,j),i=1,3),j=1,num_nodes)
        write (*,*) ' nodes read', iostat
!
      read (21, iostat=iostat) num_elem
        write (*,*) num_elem, ' elements in model', iostat
      read (21, iostat=iostat) (elem_type(i),i=1,num_elem)
        write (*,*) ' element type read', iostat
!
      do j = 1,num_elem
         elem_connect(:,j) = 0
         if (elem_type(j) < 1) cycle
         nn = node_count(elem_type(j))
         read (21, iostat=iostat) k, (elem_connect(i,j),i=1,nn)
         if (iostat /= 0 .or. j/=k) write (*,*) 'ERROR reading element',j,k
      end do
       write (*,*) 'elements read'
!
      close (unit=21)
!
      end subroutine read_FE_info

compiles but not tested !!
Back to top
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 2621
Location: Sydney

PostPosted: Thu Aug 04, 2011 6:49 am    Post subject: Reply with quote

If you want to cope with different record length formats, I've modified the program to demonstrate how you might control the record length header, using ACCESS='TRANSPARENT'. other compilers might use FORM='BINARY'
Code:
      subroutine write_FE_info (num_nodes, XYZ, num_elem, elem_type, elem_connect)
!
!  Routine to dump Model to binary file
!
      integer*4 num_nodes, num_elem, elem_type(*), elem_connect(10,*)
      real*8    XYZ(3,*)
!
      character file_name*40
      integer*4 iostat, j, node_count(6), nn, elist(0:10)
      data node_count / 2, 2, 4, 4, 8, 4 /
!
      file_name = 'transfer_file.bin'
      open (unit=21, file=file_name, form='UNFORMATTED', access='TRANSPARENT', iostat=iostat)
      write (*,*) ' File ',trim(file_name),' Opened for writing: iostat=', iostat
!
      call write_record (num_nodes, 4)
      call write_record (xyz, 3*num_nodes*8)
!
      call write_record (num_elem, 4)
      call write_record (elem_type, num_elem*4)
      do j = 1,num_elem
         if (elem_type(j) < 1) cycle
         nn = node_count(elem_type(j))
         elist(0) = j
         elist(1:10) = elem_connect(:,j)
         call write_record (elist, (nn+1)*4)
      end do
!
      close (unit=21)
!
      end subroutine write_FE_info

      subroutine read_FE_info (num_nodes, XYZ, num_elem, elem_type, elem_connect)
!
!  Routine to read Model from binary file
!
      integer*4 num_nodes, num_elem, elem_type(*), elem_connect(10,*)
      real*8    XYZ(3,*)
!
      character file_name*40
      integer*4 iostat, j, node_count(6), nn, elist(0:10)
      data node_count / 2, 2, 4, 4, 8, 4 /
!
      file_name = 'transfer_file.bin'
      open (unit=21, file=file_name, form='UNFORMATTED', access='TRANSPARENT', status='OLD', iostat=iostat)
      write (*,*) ' File ',trim(file_name),' Opened for reading: iostat=', iostat
!
      call read_record (num_nodes, iostat)
       write (*,*) num_nodes, ' nodes in model', iostat
      call read_record (xyz, iostat)
       write (*,*) ' nodes read', iostat
!
      call read_record (num_elem, iostat)
       write (*,*) num_elem, ' elements in model', iostat
      call read_record (elem_type, iostat)
       write (*,*) ' element type read', iostat
!
      do j = 1,num_elem
         elem_connect(:,j) = 0
         if (elem_type(j) < 1 .or. elem_type(j) > 6) cycle
         nn = node_count(elem_type(j))
         call read_record (elist, iostat)
         if (iostat < 0 .or. elist(0)/=j) write (*,*) 'ERROR reading element',j,elist(0)
         elem_connect(1:nn,j) = elist(1:nn)
      end do
!
      close (unit=21)
!
      end subroutine read_FE_info

      subroutine write_record (list, bytes)       ! write (21) num_nodes
!
!  Write record, assuming access=transparent
!
      integer*4 list(8), bytes, n
      n = bytes/4
      write (21) bytes
      write (21) list(1:n)
      write (21) bytes
      end
Back to top
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 2621
Location: Sydney

PostPosted: Thu Aug 04, 2011 6:51 am    Post subject: Reply with quote

the file I/O routines
Code:
      subroutine write_record (list, bytes)       ! write (21) num_nodes
!
!  Write record, assuming access=transparent
!
      integer*4 list(8), bytes, n
      n = bytes/4
      write (21) bytes
      write (21) list(1:n)
      write (21) bytes
      end

      subroutine read_record (list, bytes)       ! read (21, iostat=iostat) num_nodes
!
!  Read record, assuming access=transparent
!
      integer*4 list(8), bytes, iostat,n,m
!
      read (21, iostat=iostat) bytes
       if (iostat/=0) then
          write (*,*) 'error reading header'
          goto 99
       end if
       if (bytes < 4 .or. mod(bytes,4)/=0) then
          write (*,*) 'invalid header for record'
          goto 99
       end if
!
      n = bytes/4
      read (21, iostat=iostat) list(1:n)
       if (iostat/=0) then
          write (*,*) 'error reading record'
          goto 99
       end if
!
      read (21, iostat=iostat) m
       if (iostat/=0) then
          write (*,*) 'error reading trailer'
          goto 99
       end if
       if (m/=bytes) then
          write (*,*)'inconsistent header and trailer for record'
          goto 99
       end if
!
      return
!
   99 bytes = -1
      end

Again, compiled but not tested !
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> General All times are GMT + 1 Hour
Goto page Previous  1, 2
Page 2 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group