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

Fortran OPEN isostat 29

Yang_F_
Beginner
973 Views

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
mecej4
Honored Contributor III
973 Views

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
Steve_Lionel
Honored Contributor III
973 Views

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.

0 Kudos
Hodage__Yogesh
Beginner
973 Views

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
Steve_Lionel
Honored Contributor III
973 Views

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.

0 Kudos
Eugene_E_Intel
Employee
973 Views

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).

0 Kudos
Reply