Fortran プログラムで、日本語フォルダーに保存されたファイルを開く

概要

インテル Visual Fortran コンパイラー(インテル社が提供する、Microsoft Windows OS 用の Fortran コンパイラー)の最近のバージョンにより作成された実行ファイルでは、入出力のために開こうとするファイルの絶対パスに日本語(全角文字)が含まれる場合、ファイルパスが正しく認識されずにファイルが開けない問題があります。この記事は、問題の確認方法と対応プログラムの例を示します。

注意

本記事の内容はエクセルソフトメンバーの独自研究に基づいており、開発元による正式なアナウンスではありません。あらゆる条件の下で適用可能であると確認された情報ではなく、開発元が将来リリースするバージョンにおける情報提供を保証するものでもありません。適用は、ご自身の責任において行ってください。

本記事の内容は、執筆時点での例として、以下のバージョン (参考) について適用されることを確認しています。

2019 update 3 (コンパイラーバージョン 19.0.3.203) および以降のバージョンにおいて、本記事の例によるエラーは確認されていません。ただし、引き続き類似した問題が発生する場合は、本記事における対応例をお試しください。

  • 2019 update 2 (コンパイラーバージョン 19.0.2.190) [2019年03月13日 追記]
  • 2018 update 1 (コンパイラーバージョン 18.0.1.156) [2017年12月22日 追記]
  • 2017 update 5 (コンパイラーバージョン 17.0.5.267) [2017年12月22日 追記]
  • 2017 update 4 (コンパイラーバージョン 17.0.4.210)
  • 2017 Initial release (コンパイラーバージョン 17.0.0.109)
  • 2016 update 4 (コンパイラーバージョン 16.0.4.246)
  • 2015 update 7 (コンパイラーバージョン 15.0.7.287)
  • 2015 update 6 (コンパイラーバージョン 15.0.6.285)
  • 2015 update 5 (コンパイラーバージョン 15.0.5.280)

本記事で説明する問題は、最新バージョン (執筆時点:2017 update 4) においても発生することが開発元へ報告されました。

インテル oneAPI ツールキットの公開 (2020年12月) 以降、開発元の方針によりコンパイラーの「日本語版」対応は終了しました。一般に日本語環境でも同様に動作しますが、言語環境ごとに特有の事象について検証は実施されていません。

ページの先頭へ戻る

説明

通常、Fortran プログラムから単純にファイル(例として output.txt )を開く場合には、作業フォルダー(例として C:\fileopen\研究\ )と同じ場所にある C:\fileopen\研究\output.txt ファイルが開かれます。
しかし、インテル Visual Fortran コンパイラー の最近のバージョンにより作成された実行ファイルでは、ファイルパスに全角文字を含む場合に正しく認識されず、 C:\fileopen\ v\output.txt を開く、と処理されます。これは実際のパスとは異なるため、実行時にエラーが発生します。

この動作を回避し、日本語(全角文字)を含むパスにあるファイルを扱うには、ファイルを開く手続きにおいて、明示的に絶対パス(フルパス)を用います。

コード例

! 問題が生じる例
    open(10, name='output.txt')
    ! output.txt を開く
    ! NG: C:\fileopen\研究\ から実行
    ! OK: C:\fileopen\research\ から実行

    write(20, *) 'Hello Fortran'
    ! 事前に OPEN していなければ、自動的に fort.20 を開く
    ! NG: C:\fileopen\研究\ から実行
    ! OK: C:\fileopen\research\ から実行

! 対応例 (1)
    use ifport
    integer pathlen
    character(len=$MAXPATH) abspath

    pathlen = fullpathqq('output.txt', abspath)
    open(10, name=abspath(:pathlen))
    ! FULLPATHQQ は正確に C:\fileopen\研究\output.txt と展開する

! 対応例 (2)
    use ifport
    integer pathlen, result
    character(len=$MAXPATH) abspath

    pathlen = fullpathqq('output.txt', abspath)
    result = setenvqq('FORT20=' // abspath(:pathlen))
    write(20, *) 'Hello Fortran'
    ! 装置番号 20 に対応する環境変数 FORT20 に、絶対パスでファイル名を指定

インテル Visual Fortran コンパイラーに含まれる移植ルーチン(ifport)より FULLPATHQQ 関数を用いると、ファイル名と現在の作業フォルダーから正確な絶対パスを取得できます。
暗黙的に装置番号と紐づけられたファイル(fort.N)を利用している場合には、明示的に OPEN 文により開くようにするか、実際に入出力を行う前に、環境変数 FORTN をプログラム内から指定します。環境変数をプログラム内から指定するには、同様に移植ルーチン(ifport)より SETENVQQ 関数を用います。

ページの先頭へ戻る

事例1:OPEN 文で明示的にファイルを開く

以下に、この記事で取り扱う問題の確認と対応例として、インテル Visual Fortran コンパイラーがインストールされている Windows OS 上の、コマンドプロンプトでの操作を示します。

ディレクトリ構成(コマンドプロンプト)

C:\fileopen>dir
 ドライブ C のボリューム ラベルがありません。
 ボリューム シリアル番号は XXXX-XXXX です

 C:\fileopen のディレクトリ

2017/06/14  17:54              .
2017/06/14  17:54              ..
2017/06/14  16:03               290 open-fullpath.f90
2017/06/14  16:02               161 open.f90
2017/06/14  17:50              research
2017/06/14  17:54              研究
               2 個のファイル                 451 バイト
               4 個のディレクトリ  101,022,728,192 バイトの空き領域

テスト用ソースコードおよびプログラムのコンパイル

このプログラムは、作業フォルダーにある output.txt ファイルを開き、文字列 Hello Fortran を書き込みます。

C:\fileopen>type open.f90

    implicit none
    character(len=30) relpath

    relpath = 'output.txt'

    open(10, name=trim(relpath))

    write(10, *) 'Hello Fortran'
end

C:\fileopen>ifort /Od open.f90
インテル(R) 64 対応インテル(R) Visual Fortran コンパイラー (インテル(R) 64 対応 アプリケーション用) バージョン 17.0.4.210 ビルド 20170411
(C) 1985-2017 Intel Corporation.  無断での引用、転載を禁じます。

Microsoft (R) Incremental Linker Version 14.00.24210.0
Copyright (C) Microsoft Corporation.  All rights reserved.

-out:open.exe
-subsystem:console
open.obj

半角英数字のみのフォルダー内で実行

C:\fileopen>cd research

C:\fileopen\research>dir /B


C:\fileopen\research>..\open.exe

C:\fileopen\research>dir /B
output.txt

C:\fileopen\research>type output.txt
 Hello Fortran

全角文字を含むフォルダー内で実行(エラーが発生する)

C:\fileopen>cd 研究

C:\fileopen\研究>..\open.exe
forrtl: 致命的なエラー (43): ファイル名仕様エラーです。ユニット 10、ファイル C:\fileopen\ v\output.txt
Image              PC                Routine            Line        Source      
open.exe           00007FF7CA8C44BD  Unknown               Unknown  Unknown
...

対処後のソースコード(FULLPATHQQ 関数により取得した絶対パスでファイルを開く)

! open-fullpath.f90
    use ifport
    implicit none
    integer pathlen
    character(len=$MAXPATH) abspath

    character(len=30) relpath

    relpath = 'output.txt'
    pathlen = fullpathqq(trim(relpath), abspath)

    open(10, name=abspath(:pathlen))

    write(10, *) 'Hello Fortran'
end

コンパイルおよび実行

C:\fileopen>ifort /Od open-fullpath.f90
インテル(R) 64 対応インテル(R) Visual Fortran コンパイラー (インテル(R) 64 対応 アプリケーション用) バージョン 17.0.4.210 ビルド 20170411
(C) 1985-2017 Intel Corporation.  無断での引用、転載を禁じます。

Microsoft (R) Incremental Linker Version 14.00.24210.0
Copyright (C) Microsoft Corporation.  All rights reserved.

-out:open-fullpath.exe
-subsystem:console
open-fullpath.obj

C:\fileopen>cd 研究

C:\fileopen\研究>dir /B


C:\fileopen\研究>..\open-fullpath.exe

C:\fileopen\研究>dir /B
output.txt

C:\fileopen\研究>type output.txt
 Hello Fortran

ページの先頭へ戻る

事例2:装置番号に紐づけられたファイルを用いる

以下に、この記事で取り扱う問題の確認と対応例として、インテル Visual Fortran コンパイラーがインストールされている Windows OS 上の、コマンドプロンプトでの操作を示します。

ディレクトリ構成(コマンドプロンプト)

C:\readdata>dir
 ドライブ C のボリューム ラベルがありません。
 ボリューム シリアル番号は XXXX-XXXX です

 C:\readdata のディレクトリ

2017/06/15  15:39              .
2017/06/15  15:39              ..
2017/06/14  21:22              nodata
2017/06/14  17:11               915 read-fullpath.f90
2017/06/15  14:04               206 read.f90
2017/06/14  21:22              trial
2017/06/14  21:22              試用
               2 個のファイル               1,121 バイト
               5 個のディレクトリ  99,969,908,736 バイトの空き領域

テスト用ソースコードおよびプログラムのコンパイル

このプログラムは、作業フォルダーにある fort.20 ファイル( OPEN 文でファイル名を指定しない場合の規定値)から数値を読み取り表示します。

C:\readdata>type read.f90
    implicit none
    integer j
    real(8) :: array(4,4)
    do j=1, 4
        read(20, '(4F8.3)') array(:,j)
    end do

    do j=1, 4
        write(*, '(4F8.3)') array(:,j)
    end do
end

C:\readdata>ifort /Od read.f90
インテル(R) 64 対応インテル(R) Visual Fortran コンパイラー (インテル(R) 64 対応 アプリケーション用) バージョン 17.0.4.210 ビルド 20170411
(C) 1985-2017 Intel Corporation.  無断での引用、転載を禁じます。

Microsoft (R) Incremental Linker Version 14.00.24210.0
Copyright (C) Microsoft Corporation.  All rights reserved.

-out:read.exe
-subsystem:console
read.obj

実行(実際にファイルが無いためエラー)

C:\readdata>cd nodata

C:\readdata\nodata>dir /B


C:\readdata\nodata>..\read.exe
forrtl: 致命的なエラー (29): ファイルが見つかりません。ユニット 20、ファイル C:\readdata\nodata\fort.20
Image              PC                Routine            Line        Source      
read.exe           00007FF60B5C43FD  Unknown               Unknown  Unknown
...

半角英数字のみのフォルダー内で実行

C:\readdata>cd trial

C:\readdata\trial>dir /B
fort.20

C:\readdata\trial>..\read.exe
   1.000   2.000   3.000   4.000
   2.000   4.000   6.000   8.000
  -3.000  -6.000   3.000   6.000
   4.000  -3.000   2.000  -1.000

全角文字を含むフォルダー内で実行(エラーが発生する)

C:\readdata>cd 試用

C:\readdata\試用>dir /B
fort.20

C:\readdata\試用>..\read.exe
forrtl: 致命的なエラー (29): ファイルが見つかりません。ユニット 20、ファイル C:\readdata\f(\fort.20
Image              PC                Routine            Line        Source      
read.exe           00007FF60B5C43FD  Unknown               Unknown  Unknown
...

対処後のソースコード( SETENVQQ 関数で環境変数 FORT20 を設定)

インテル Visual Fortran コンパイラーに依存する処理は、CONTAINS 文以降に定義されているサブルーチン jppath_workaround() の中に集約されています。

! read-fullpath.f90
    implicit none
    integer j
    real(8) :: array(4,4)

    ! 入出力に利用する各装置番号について、事前に呼び出す
    call jppath_workaround(20)

    do j=1, 4
        read(20, '(4F8.3)') array(:,j)
    end do

    do j=1, 4
        write(*, '(4F8.3)') array(:,j)
    end do
    stop

contains
    subroutine jppath_workaround(unit)
        use ifport
        implicit none
        integer,intent(in) :: unit

        integer pathlen, result
        character(len=16)  envname
        character(len=$MAXPATH) tmpval, abspath
        character(len=16+$MAXPATH) envval

        envname = ''; tmpval = ''

        ! 環境変数 FORT の値を取得
        write(envname, '("FORT", I0)') unit
        result = getenvqq(trim(envname), tmpval)

        ! 環境変数が設定されていなければ、デフォルトのファイル名を設定
        if(result == 0) then
            write(tmpval, '("fort.", I0)') unit
        end if

        ! 絶対パスを取得
        pathlen = fullpathqq(trim(tmpval), abspath)

        ! 環境変数 FORT に値を設定する
        envval = trim(envname) // '=' // abspath(:pathlen)
        result = setenvqq(trim(envval))
    end subroutine
end

コンパイルおよび実行

C:\readdata>ifort /Od read-fullpath.f90
インテル(R) 64 対応インテル(R) Visual Fortran コンパイラー (インテル(R) 64 対応 アプリケーション用) バージョン 17.0.4.210 ビルド 20170411
(C) 1985-2017 Intel Corporation.  無断での引用、転載を禁じます。

Microsoft (R) Incremental Linker Version 14.00.24210.0
Copyright (C) Microsoft Corporation.  All rights reserved.

-out:read-fullpath.exe
-subsystem:console
read-fullpath.obj

C:\readdata>cd 試用

C:\readdata\試用>..\read-fullpath.exe
   1.000   2.000   3.000   4.000
   2.000   4.000   6.000   8.000
  -3.000  -6.000   3.000   6.000
   4.000  -3.000   2.000  -1.000

上述したソースコード read-fullpath.f90 での対処は、事前に環境変数 FORT20 を設定することで指定のパスにあるファイルを開く場合にも対応しています。

C:\readdata\試用>dir /B
fort.20
ソート済み.txt

C:\readdata\試用>set FORT20=ソート済み.txt

C:\readdata\試用>..\read-fullpath.exe
  -6.000  -3.000  -3.000  -1.000
   1.000   2.000   2.000   2.000
   3.000   3.000   4.000   4.000
   4.000   6.000   6.000   8.000

コマンドプロンプト上で設定した環境変数は、コマンドプロンプトを閉じるか、以下のように設定値無しとすることで解除されます。

C:\readdata\試用>set FORT20=

ページの先頭へ戻る

まとめ

本記事では、インテル Visual Fortran コンパイラーを使用した Fortran プログラムで、日本語フォルダーに保存されたファイルを開く際に起こる問題と、対応方法について説明しました。Windows OS において Fortran プログラム中でファイルを開く場合には、絶対パス(フルパス)でファイル名を指定すると、期待通り動作しました。

ページの先頭へ戻る