Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29243 Discussions

How does one create a uniquely named Windows file via FORTRAN?

John6
Beginner
2,426 Views
Does anyone know a good way to create a new Windows file (via FORTRAN) which is uniquely named?
In C++ we can call GetTempFileNameW to get new uniquely named files. How can this be done via a FORTRAN call? What I would like is for a blank file to be created so that I can write to it, but it must be uniquely named. Seems like a call to a Windows-OS function should be doable. Is there a FORTRAN equivalent, so that an OS call is not needed?
0 Kudos
14 Replies
Steven_L_Intel1
Employee
2,426 Views
GetTempFileName is an Win32 API routine, not part of C++. You can call it in Fortran too. For example:

[fortran]use kernel32
integer(UINT) retval
character(MAX_PATH) filename
integer ipos

retval = GetTempFileName ('.'C,'XYZ'C,0,filename)
if (retval /= 0) then
  ipos = index(filename, CHAR(0))
  print *, "File name is ", filename(1:ipos-1)
else
  print *, "Call failed"
end if

end
[/fortran]
What GetTempFileName does is start out with a name based on the system time, and then it keeps incrementing the name until it finds one that is unused. You can write standard Fortran code to do this based on SYSTEM_CLOCK, an internal WRITE and an OPEN with STATUS='NEW'.
0 Kudos
John6
Beginner
2,426 Views
Thanks, that is exactly what I was looking for (an example ofthe GetTempFileName Win32 API call from FORTRAN). Is there a Linux-OS equivalent? (The app I am working on is compiled on both Win32 and 64- bit OS) and Linux, using IVF).
0 Kudos
Steven_L_Intel1
Employee
2,426 Views
Not that I know of. Linux lacks a system library like Win32.

Try this.

[fortran]character(255) filename

call generate_temp_name('TMP', filename)
print *, trim(filename)


contains

subroutine generate_temp_name (prefix, outname)
implicit none
character(*), intent(in) :: prefix
character(*), intent(out) :: outname

real mrand
integer irand
logical ex
logical, save :: init = .false.
! Initialize random number generator
if (.not. init) then
  call random_seed
  init = .true.
  end if

do
! Get a random number
call random_number(mrand)
! Get the low 24 bits
irand = transfer(mrand, irand)
irand = iand(irand,Z'FFFFFF')
write (outname,101) trim(prefix),irand
101 format (A,Z6.6,'.tmp')
inquire (file=trim(outname),exist=ex)
if (.not.ex) exit
end do

! We have a name that does not exist (at least right now)
return

end subroutine generate_temp_name

end
[/fortran]
0 Kudos
John6
Beginner
2,426 Views
Excellent. They both work great. I will use the latter because it is more portable. Interestingly enough, I had slightly modified the first example to not use a constant string for the prefix (I passed it in as a variable), and when (debug) stepping into the subroutine, the IDE crashed (VS 2005). The subroutine looked something like this:


Subroutine foooo (PrefixString, filename)

use kernel32

Implicit None

integer(UINT) retval

character(*) filename, PrefixString

!character(MAX_PATH) filename

integer ipos, LastNoNULL

retval = GetTempFileName ('.'C,PrefixString,0,filename)

End Subroutine foooo

called as: Call foooo ('text1_', tmp_file)

0 Kudos
Steven_L_Intel1
Employee
2,426 Views
The API routine wants a null-terminated string, but you left off the null.
0 Kudos
John6
Beginner
2,426 Views
That is enough to cause the VS 2005 IDE to crash completely?
0 Kudos
Steven_L_Intel1
Employee
2,426 Views
Hard to say - depends on what the API code does with it. I'll try this later.
0 Kudos
John6
Beginner
2,426 Views
Thanks, I appreciate the help. I did try with and without the trailing null, and the IDE crashed both times.
This occurred on the call into the subroutine, not when the IDE function was called, if that helps.
0 Kudos
Steven_L_Intel1
Employee
2,426 Views
I can't reproduce the crash.
0 Kudos
John6
Beginner
2,426 Views
Huh... Well, not too surprising, these crashes are hard to reproduce... thanks for trying. I don't know whether it matters, but the caller was in one FORTRAN static library project and the callee was in a different static FORTRAN library. I thinkthe problem maylie somewhere in the passing of the string args, especially string constants. I wish I knew what I did that was so wrong, because I hate it when the IDE goes down.
0 Kudos
jimdempseyatthecove
Honored Contributor III
2,426 Views
A minor variation in Steve's "try this" is to use his technique to create a new random named folder (directory) then within that directory, create sequentially numbered temp file names. In this manner you should never have a name conflict and as an additional benefit, should you decide to keep the temp files from a known good run, then latershould a production run ab-end (or during debugging), you now have a list of files that may be useful in running a post mortem of the ab-end.

Also, the temp files from program X are isolated from the temp files from program Y

Jim Dempsey
0 Kudos
mecej4
Honored Contributor III
2,426 Views
Read the output of

man 3 mktemp
man 3 mkstemp
0 Kudos
Steven_L_Intel1
Employee
2,426 Views
That probably won't work well on Windows.
0 Kudos
mecej4
Honored Contributor III
2,426 Views
True, but I was responding to #2, which was about Linux.
0 Kudos
Reply