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.
do 10 irec=1,100
do 20 irec=1,100
20 print *,"rec ",irec," read"
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 ?
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
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.
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 ?
12 open(2,file="LAFA.MID", &
form="unformatted", access="stream", action="READ")
print *,"record ",irec," read"
Didnt someone write about this matter recently ?
>>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.
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.
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 ?
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.
input file name:
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.
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.
OK, here is the source code. I am trying to read a standard MIDI file from a music program.
12 print *,"input file name:"
print *,"Access method:"
35 print *,"LGU 2 file opened OK"
! this is where it falls apart
! It gives me an EOF, rather than reading in any data.
! I am trying to use STREAM input
print *,"record ",irec," read"
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 ?
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.
Sorry, there should have been a space between the link and the comma after it. That is, the correct link is
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!
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.