Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Beginner

Fortran OPEN isostat 29

Hi,

I come across this situation when I am trying to open a binary file by fortran open function. The open function returns isostat value of 29. I figured that the reason is my file folder has special characters (å) from Nordic areas. If I get rid of these special characters, the open function works fine. Any idea how I can fully support this in my code?

Thank you,

Yang 

0 Kudos
5 Replies
Highlighted
Black Belt

Although Windows itself

Although Windows itself supports Unicode file names, support in programming languages for such names may be missing or incomplete. Here is a workaround, which you may not find to be sufficiently convenient.

Create a symbolic link to the file, giving an ASCII name to the link (you may need to do this in a command window with admin-privilege):

     mklink Malmo.bin Malmö.bin

In your Fortran program, use the name of the link instead of the name of the target file itself.

0 Kudos
Highlighted
Black Belt

Intel Fortran does not yet

Intel Fortran does not yet support UNICODE in file specifications. I have seen examples where the programmer wrote a USEROPEN routine that called the Windows API CreateFileW to open the file with the "wide character" filespec, and then returned the handle to the Fortran run-time library.

Steve (aka "Doctor Fortran") - https://stevelionel.com/drfortran
0 Kudos
Highlighted
Beginner

Hi Steve,

Hi Steve,

I have similar issue with my application. It is not start if directory has unicode character. My application write log file to this directory.

I read this blog and trying to implement the useropen routine that called Windows API CreateFileW but i am getting linking error. If i use Windows API CreateFile then no linking error found.

////Here is my code 

EXTERNAL uopen_
INTEGER(INT_PTR_KIND()) uopen_

....

open  (12, file=filename,iostat=istat,STATUS='NEW',USEROPEN=uopen_)

...

      INTEGER (INT_PTR_KIND()) FUNCTION uopen_( FILENAME,DESIRED_ACCESS,SHARE_MODE,A_NULL,CREATE_DISP,FLAGS_ATTR,B_NULL,UNIT)
              USE KERNEL32
          !IMPLICIT NONE
          INTEGER(4) DESIRED_ACCESS
          INTEGER(4) SHARE_MODE
          INTEGER(4) A_NULL
          INTEGER(4) CREATE_DISP
          INTEGER(4) FLAGS_ATTR
          INTEGER(4) B_NULL
          INTEGER(4) UNIT
          !INTEGER(4) FLEN
          CHARACTER*(512) FILENAME
          INTEGER(4) ISTAT
          TYPE(T_SECURITY_ATTRIBUTES), POINTER :: NULL_SEC_ATTR
140       FORMAT( X, "ERROR: USEROPEN Passed Wrong Unit Number",I)
!         Sanity check
          IF (UNIT .NE. 10) THEN
             WRITE(*,140) UNIT
          END IF
      !! WRITE(*,*) "FILENAME=",FILENAME !! prints the full path of the filename
! Set the FILE_FLAG_WRITE_THROUGH bit in the flag attributes to CreateFile( )
! (for whatever reason)
!     FLAGS_ATTR = FLAGS_ATTR + FILE_FLAG_WRITE_THROUGH
! Do the CreateFile( ) call and return the status to the Fortran rtl
      ISTAT = CreateFileW( FILENAME,DESIRED_ACCESS,SHARE_MODE,NULL_SEC_ATTR,CREATE_DISP,FLAGS_ATTR,0 )
         if (ISTAT == INVALID_HANDLE_VALUE) then
          write(*,*) "Could not open file (error ", GetLastError(),")",FILENAME
         endif
         uopen_ = ISTAT
         RETURN
        END FUNCTION uopen_

/////////////////////

I am new for fortran programming. Could you please help me to resolve this linking error.

Thanks

 

 

 

 

0 Kudos
Highlighted
Black Belt

The Intel module does not

The Intel module does not declare CreateFileW, so you have to declare it yourself. Is the filename you are specifying one that contains UTF-16 characters?

A declaration for CreateFileW could be:

INTERFACE 
FUNCTION CreateFileW( &
        lpFileName, &
        dwDesiredAccess, &
        dwShareMode, &
        lpSecurityAttributes, &
        dwCreationDisposition, &
        dwFlagsAndAttributes, &
        hTemplateFile)
import
  integer(HANDLE) :: CreateFileW ! HANDLE
    !DEC$ ATTRIBUTES DEFAULT, STDCALL, DECORATE, ALIAS:'CreateFileW' :: CreateFileW
!DEC$ ATTRIBUTES REFERENCE, ALLOW_NULL :: lpFileName
  character*(*) lpFileName ! LPCSTR lpFileName
  integer(DWORD) dwDesiredAccess ! DWORD dwDesiredAccess
  integer(DWORD) dwShareMode ! DWORD dwShareMode
!DEC$ ATTRIBUTES REFERENCE, ALLOW_NULL :: lpSecurityAttributes
  TYPE (T_SECURITY_ATTRIBUTES) lpSecurityAttributes ! LPSECURITY_ATTRIBUTES lpSecurityAttributes
  integer(DWORD) dwCreationDisposition ! DWORD dwCreationDisposition
  integer(DWORD) dwFlagsAndAttributes ! DWORD dwFlagsAndAttributes
  integer(HANDLE) hTemplateFile ! HANDLE hTemplateFile
 END FUNCTION CreateFileW
END INTERFACE

You would insert this in your _uopen routine after IMPLICIT NONE. I can't promise that this will do what you want, but it should at least link.

As an alternative you could perhaps call SetCurrentDirectoryW (which you would also have to declare) to change to the Unicode-named directory, and then use normal Fortran I/O to write files there. If you're already in a directory that has a Unicode name, I would think that normal Fortran I/O should work, but I am not certain.

Steve (aka "Doctor Fortran") - https://stevelionel.com/drfortran
0 Kudos
Highlighted
Employee

Note that CreateFileW()

Note that CreateFileW() expects "wide" character string for the file name, where each char is 2 bytes, each byte in little endian format (UCS-2 encoding).

Eugene Epshteyn
0 Kudos