- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am under the impression I can make a binary file that allows random access to a set of fixed size records.
Its allowing me to write records sequentially, but if I pick a record number, I cant do that.
for example if I have 100 records of 20 integer words each, I should be able to pick and replace record number 48, right?
Maybe I dont have the right set of keywords to open the file. But you dont give us any examples that I can find.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
subroutine screwup
integer(4) pr(6000)
open(2,file='screwup2.dat',form='binary',recl=6000)
do 10 irec=1,100
10 write(2,rec=irec)pr
rewind 2
do 20 irec=1,100
read(2,rec=irec)pr
20 print *,"rec ",irec," read"
pause
end
As long as I write the files and read them sequentially, it works.
But I cannot pick a record randomly. So that rec=irec option illegal ?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
If your application is able to forego portability to any opsys but Windows, then you can easily replace the standard (antiquated) Fortran file i/o routines with WinAPI routines. Concepts such as "records", as well as even more obsolete notions (BACKSPACE, REWIND) no longer constrain the i/o functions.
The WinAPI routines allow you to specify an exact byte count to be transferred to/from any memory location, from/to any position in the file at a specified byte-count offset. That's about as atomic and powerful as it gets, and there is nothing, including all the OP asked for, that cannot be easily and directly accomplished.
The Fortran routines below (extracted from a module in a much larger program) illustrate how this is done. Note that file and path namestrings need to be null-terminated for Windows.
Here is a sample calling sequence to load a program variable with nbytes of data read starting at offset_value in the file:
ihandl = Open_the_file ('c:\mydir\fname'c, 'R')
CALL rw_file ('R', ihandl, nbytes, LOC(mydata), offset_value)
CALL close_file (ihandl)
Simple, powerful, and also much much faster than using the built-in Fortran file i/o.
MODULE filesubs
USE ifwin
USE ifwinty
SAVE
CONTAINS
RECURSIVE FUNCTION file_exists (fname) RESULT (size)
IMPLICIT NONE
TYPE(T_WIN32_FIND_DATA) :: fdata
CHARACTER(LEN=*),INTENT(IN) :: fname ! full pathname to file
INTEGER(HANDLE) :: ihandl
INTEGER :: size, rval, nc
size = -1
nc = chcnt(fname, LEN(fname))
IF (nc > 5) THEN
ihandl = FindFirstFile (fname, fdata)
IF (ihandl /= INVALID_HANDLE_VALUE) THEN
size = fdata%nFileSizeLow
! must have this, else memory leak
rval = FindClose (ihandl)
ELSE
! error
ENDIF
END IF
END FUNCTION file_exists
RECURSIVE FUNCTION open_the_file (fullpath, rwmode) RESULT (ihandl)
IMPLICIT NONE
SAVE
INTEGER(HANDLE) :: ihandl
INTEGER :: access, nc
INTEGER :: ntry
INTEGER, PARAMETER :: max_try = 10
CHARACTER(LEN=*),INTENT(IN) :: fullpath, rwmode
CHARACTER(LEN=200) :: msg
IF (rwmode == 'R') THEN
access = GENERIC_READ
ELSE
access = IOR(GENERIC_READ,GENERIC_WRITE)
END IF
ntry = 0
10 ihandl = CreateFile (fullpath, & ! null-terminated
access, &
IOR(FILE_SHARE_READ,FILE_SHARE_WRITE), &
NULL_SECURITY_ATTRIBUTES, &
OPEN_ALWAYS, &
FILE_ATTRIBUTE_NORMAL, &
NULL )
IF (ihandl == INVALID_HANDLE_VALUE) THEN
IF (GetLastError() == ERROR_SHARING_VIOLATION) THEN
ntry = ntry + 1
IF (ntry > max_try) RETURN
CALL delay_ms (5)
GO TO 10
END IF
END IF
END FUNCTION open_the_file
! TYPE T_WIN32_FIND_DATA
! SEQUENCE
! integer(DWORD) dwFileAttributes ! knowns DWORD
! TYPE (T_FILETIME) ftCreationTime ! typedefs FILETIME
! TYPE (T_FILETIME) ftLastAccessTime ! typedefs FILETIME
! TYPE (T_FILETIME) ftLastWriteTime ! typedefs FILETIME
! integer(DWORD) nFileSizeHigh ! knowns DWORD
! integer(DWORD) nFileSizeLow ! knowns DWORD
! integer(DWORD) dwReserved0 ! knowns DWORD
! integer(DWORD) dwReserved1 ! knowns DWORD
! character(260) cFileName
! character(14) cAlternateFileName
! END TYPE
RECURSIVE SUBROUTINE rw_file (rwmode, ihandl, nbytes, loc_pointer, offset)
IMPLICIT NONE
SAVE
CHARACTER(LEN=1), INTENT(IN) :: rwmode
INTEGER(HANDLE), INTENT(IN) :: ihandl
INTEGER, INTENT(IN) :: nbytes, loc_pointer
INTEGER, INTENT(IN), OPTIONAL :: offset
INTEGER :: rval
INTEGER :: nact
! position pointer if offset is provided
IF (PRESENT(offset)) rval = SetFilePointer (ihandl, offset, NULL, FILE_BEGIN)
IF (rwmode == 'R') THEN
IF (ReadFile (ihandl, & ! file handle
loc_pointer, & ! address of data
nbytes, & ! byte count to read
LOC(nact), & ! actual bytes read
NULL_OVERLAPPED) == 0) THEN
! Error reading file
END IF
ELSE
IF (WriteFile (ihandl, & ! file handle
loc_pointer, & ! address of data
nbytes, & ! byte count to write
LOC(nact), & ! actual bytes written
NULL_OVERLAPPED) == 0) THEN
! Error writing file
END IF
END IF
END SUBROUTINE rw_file
RECURSIVE SUBROUTINE Set_File_Pointer (ihandl, offset, truncate)
IMPLICIT NONE
INTEGER(HANDLE), INTENT(IN) :: ihandl
INTEGER, INTENT(IN) :: offset
LOGICAL, INTENT(IN), OPTIONAL :: truncate
INTEGER :: rslt
rslt = SetFilePointer (ihandl, MAX0(offset,0), NULL, FILE_BEGIN)
IF (PRESENT(truncate)) rslt = SetEndOfFile (ihandl)
END SUBROUTINE Set_File_Pointer
RECURSIVE SUBROUTINE close_file (ihandl)
IMPLICIT NONE
INTEGER(HANDLE), INTENT(INOUT) :: ihandl
LOGICAL :: rslt
!IF (ihandl > 0) rslt = CloseHandle (ihandl)
rslt = CloseHandle (ihandl)
ihandl = 0
filehandles = MAX0(0, filehandles - 1)
END SUBROUTINE close_file
END MODULE filesubs
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Read about the ACCESS='DIRECT' specifier in the file OPEN statement. Related to this is he specifier FORM='...'
Do not use the nonstandard FORM='BINARY' unless you understand the implications.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have to say Form="binary" since I am working with Midi files,
generated by music software.
Anyway thanks for the helpful tips.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
form='binary' is an extension. Instead you should be using form="unformatted", access="stream".
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Well, I still cant get it to access that file, when I use your suggestion.
It says "file not found" even when the file is where it can easily find it.
So should I be able to attach the file, regardless of what kind it is ?
subroutine getmid()
character*20 FN/"LAFA.mid"/
integer(4) midirec(60)
!
110 format(A20)
12 open(2,file="LAFA.MID", &
form="unformatted", access="stream", action="READ")
do irec=1,100
read(2)midirec
print *,"record ",irec," read"
enddo
end
Didnt someone write about this matter recently ?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
>>It says "file not found" even when the file is where it can easily find it.
Then most likely the (your) current directory is not where you expect it to be.
The current directory can be located anywhere.
When launched from an IDE, the current directory is usually specified on some property page (e.g. Debug or Release configuration). Default for MS Visual Studio is the Project Folder, but you can set it anywhere else. Your executable is likely located elsewhere.
You could add an OPEN file for output such as "WhereAmI" write something to it (e.g. "Here I am"), close the file. Then find the file.
There is also a Current Drive.
Using "LAFA.MID" specifies the file is located in the "current directory" on the "current drive.
Function GETDRIVEQQ and GETDRIVEDIRQQ can also be used to query the system.
Jim Dempsey
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I made sure the executable is where where Its supposed to be,
By opening a scratch file and seeing where it gets put. I can verify that it is always put in the same location as the data I want to look at.
And I can always attach the file on an OPEN statement, but every time I try to read one record it gives me an EOF return, rather than reading in the data.
Is there someone at INTEL that has actually had to deal with a similar problem, so we dont do this endless guesswork ? I will pay for their time.
The file I am working with was probably generated on a MAC machine, which is why I have to treat it as a "strange" format, with a raw set of data bytes.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It doesn't give give me a way to do that.
Not obvious, anyway. It is sitting in my user file directory,
but how do I transfer the whole file ?
This was imported from outside, but I find it hard to understand why there is no way to examine the contents of it, even as a "raw binary"
Would access="STREAM" be the correct way ?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Here is the file I am trying to read.
I am trying to use "drag and drop." or Browse files.
But nothing happens when I click on that.
Dont they bother to check this stuff ?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You can put the file in a ZIP archive and attach that. I am going to test that here. (It worked. Be sure to drag it onto the "attach" box and not the message box.)
Would you please show the actual and complete error message you get for "file not found" and also a directory listing of the directory you think the file should be found in? That you sometimes get EOF tells me that it is being created empty because the intended file is not there.
I do recommend using ACCESS='STREAM', FORM='UNFORMATTED' (and unformatted READs) to read binary data.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
input file name:
lafa.mid
Access method:
stream
LGU 2 file opened OK
forrtl: severe (24): end-of-file during read, unit 2, file C:\Users\Administrator\documents\visual studio 2010\Projects\Console8\Console8\lafa.mid
Image PC Routine Line Source
libifcoremdd.dll 510B19D2 Unknown Unknown Unknown
libifcoremdd.dll 510EED7F Unknown Unknown Unknown
Console8.exe 00C612A6 _GETMIDI 29 CONSOLE8.F90
Console8.exe 00C63F37 _MAIN__ 7 CONSOLE8.F90
Console8.exe 00C65CAF Unknown Unknown Unknown
Console8.exe 00C6466F Unknown Unknown Unknown
Console8.exe 00C6449F Unknown Unknown Unknown
KERNEL32.DLL 76B16359 Unknown Unknown Unknown
ntdll.dll 77467B74 Unknown Unknown Unknown
ntdll.dll 77467B44 Unknown Unknown Unknown
You can see that it attaches the file, but I get the ERROR QUIT when it tries to do any reading from it. I did use the Stream input method, as you recommended.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
We'd need to see a small test program that demonstrates the problem. It could be that your program is reading past the end of the file. Please attach ZIP of the file and a program we can look at. Ideally this would be a small program that just tries to read some data from the file, but if you can't make that work the whole program is ok.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
OK, here is the source code. I am trying to read a standard MIDI file from a music program.
subroutine getmidi()
character*20 FN
character*20 AM
integer(4) midirec(60)
!
110 format(A20)
12 print *,"input file name:"
READ(*,110)FN
print *,"Access method:"
READ(*,110)AM
open(2,file=FN,access=AM, form="UNFORMATTED")
35 print *,"LGU 2 file opened OK"
do irec=1,100
! this is where it falls apart
! It gives me an EOF, rather than reading in any data.
! I am trying to use STREAM input
read(2)midirec
print *,"record ",irec," read"
print *,"contents:",midirec
enddo
end
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
BTW, the file I was reading has more than 230K bytes of data, so I dont think I would be getting an End-of-File right at the beginning of the 1st read operation. I had trouble attaching the actual file, but I can make a more concerted effort if needed.
It keeps telling me the file type is "not supported." Its a standard file used every where, so I dont see why.
You would probably get the same problem, no matter what type it is ?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Well, this MIDI file is just one example of the problem, namely reading in files where you want to examine their contents, but you dont know their origins ahead of time.
Of course, once you DO know that, then there might be a better way to manipulate their contents. But the first step is to find out WHAT they ARE first.
The problem is, if it gives you an EOF ERROR without any info, then you have learned nothing whatsoever.
I was wondering is: INTEL if had a tool where you can examine a file byte by byte without knowing its format ahead of time.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Sorry, there should have been a space between the link and the comma after it. That is, the correct link is
instead of
I tried to fix my previous post, which you read, by adding a space between the URL and the comma, and this *@~%! forum software marked the post as spam and deleted it! Just because I added a space!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
WSinc, you wrote: "Of course, once you DO know that, then there might be a better way to manipulate their contents. But the first step is to find out WHAT they ARE first."
Sorry, in general inferring the structure of a file format from a small number of example files is extremely difficult and rarely worth the effort. Reverse engineers and hackers have special skills and tools for that, and they would probably not use Fortran.
Most people, after looking at a binary file without knowing something about its contents, would think that they are seeing random bytes. Try looking at EXE or Zip files using HXD.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page