一時ディレクトリの取得一時ファイルの作成について。 また、一時ディレクトリを設定する環境変数について。

一時ディレクトリの取得 (Path.GetTempPath)

Path.GetTempPathメソッドを呼び出すと、一時ディレクトリのパスを取得することができる。 このメソッドが返す一時ディレクトリは、環境変数の設定によって変わる。 (§.環境変数とPath.GetTempPathメソッドが返すパス)

一時ディレクトリ配下かつ任意のファイル名でのパスを直接生成するメソッドはないので、Path.Combineメソッドと組み合わせてパスを連結・生成する必要がある。

一時ディレクトリを取得する・一時ファイルのパスを生成する
using System;
using System.IO;

class Sample {
  static void Main()
  {
    // 一時ディレクトリへのパスを取得する (パスは環境変数によって変わる)
    Console.WriteLine(Path.GetTempPath());

    // 一時ディレクトリ配下かつファイル名がtemp.txtのフルパスを生成する
    Console.WriteLine(Path.Combine(Path.GetTempPath(), "temp.txt"));
  }
}
一時ディレクトリを取得する・一時ファイルのパスを生成する
Imports System
Imports System.IO

Class Sample
  Shared Sub Main()
    ' 一時ディレクトリへのパスを取得する (パスは環境変数によって変わる)
    Console.WriteLine(Path.GetTempPath())

    ' 一時ディレクトリ配下かつファイル名がtemp.txtのフルパスを生成する
    Console.WriteLine(Path.Combine(Path.GetTempPath(), "temp.txt"))
  End Sub
End Class
実行結果例
>dotnet run
C:\Users\user\AppData\Local\Temp\
C:\Users\user\AppData\Local\Temp\temp.txt

>set TMP=E:\Temp\
>dotnet run
E:\Temp\
E:\Temp\temp.txt
実行結果例
>csc test.cs
>test.exe
C:\Users\user\AppData\Local\Temp\
C:\Users\user\AppData\Local\Temp\temp.txt

>set TMP=E:\Temp\
>test.exe
E:\Temp\
E:\Temp\temp.txt
実行結果例
$dotnet run
/tmp/
/tmp/temp.txt

$mkdir ~/.tmp/
$env TMPDIR=~/.tmp/ dotnet run
/home/user/.tmp/
/home/user/.tmp/temp.txt

$env TMPDIR=~/nonexistent/ dotnet run
Failed to create CoreCLR, HRESULT: 0x80004005
実行結果例
$mono test.exe
/tmp/
/tmp/temp.txt

$env TMP=~/.tmp/ mono test.exe
/home/user/.tmp/
/home/user/.tmp/temp.txt

Path.GetTempFileNameメソッドを使えば、一時ディレクトリ配下かつランダムなファイル名でファイルを作成することができる。

環境変数とPath.GetTempPathメソッドが返すパス

Path.GetTempPathメソッドは、OSやランタイムの種類によってそれぞれ異なる環境変数を参照し、設定されているパスを返す。 Path.GetTempPathメソッドが参照する環境変数と、優先順位は次のようになる。

Windows上の.NET/.NET Core/.NET Frameworkの場合
  1. 環境変数TMP
  2. 環境変数TEMP
  3. レジストリキーHKEY_CURRENT_USER\EnvironmentTMP
  4. レジストリキーHKEY_CURRENT_USER\EnvironmentTEMP
  5. Windowsディレクトリ
Linux上の.NET/.NET Coreの場合
  1. 環境変数TMPDIR
  2. /tmpディレクトリ
Monoの場合
  1. 環境変数TMP
  2. 環境変数TEMP
  3. /tmpディレクトリ

これに従いPath.GetTempPathメソッドの動作は次のようになる。

参照される環境変数
Windows上の.NET/.NET Core/.NET Framework、およびMono
TMPまたはTEMP
Linux上の.NET/.NET Core
TMPDIR
環境変数で設定されているパスが存在しない場合
Windows上の.NET/.NET Core/.NET Framework、およびMono
特に例外等は発生しない
Linux上の.NET/.NET Core
起動時にFailed to create CoreCLR, HRESULT: 0x80004005となる模様
環境変数が設定/変更されていない場合のデフォルト
Windows
%USERPROFILE%\AppData\Local\Temp (C:\Users\user\AppData\Local\Temp)
Linux
/tmp

環境変数がデフォルトの状態の場合、Windowsではユーザー別のディレクトリ、Linux等では全ユーザーが共用するディレクトリが一時ディレクトリとして返される点に注意する必要がある。

一時ファイルの作成 (Path.GetTempFileName)

Path.GetTempFileNameメソッドを使うと、一時ディレクトリに一時ファイルを作成することができる。 GetTempFileNameメソッドを呼び出すと、拡張子が.tmpでサイズが0のファイルが作成される。 そのため、一時ファイルを使用し終えたら必要に応じて削除する。 このメソッドでは常にファイルが作成されるため、一時ファイルのファイル名のみを取得することはできない。

Path.GetTempFileNameメソッドで作成される一時ファイルは、GetTempPathメソッドと同じ一時ディレクトリに作成される。

一時ファイルを作成してファイルにテキストを書き込む
using System;
using System.IO;

class Sample {
  static void Main()
  {
    string tempfile = null;

    try {
      // 一時ディレクトリ下に一時ファイルを作成し、そのファイルパスを取得する
      tempfile = Path.GetTempFileName();

      // 一時ファイルにテキストを書き込む
      File.WriteAllText(tempfile, "Hello, world!");
    }
    finally {
      // 一時ファイルが作成された場合、一時ファイルを使った処理が終了した時点で削除する
      if (tempfile != null && File.Exists(tempfile))
        File.Delete(tempfile);
    }
  }
}
一時ファイルを作成してファイルにテキストを書き込む
Imports System
Imports System.IO

Class Sample
  Shared Sub Main()
    Dim tempfile As String = Nothing

    Try
      ' 一時ディレクトリ下に一時ファイルを作成し、そのファイルパスを取得する
      tempfile = Path.GetTempFileName()

      ' 一時ファイルにテキストを書き込む
      File.WriteAllText(tempfile, "Hello, world!")
    Finally
      ' 一時ファイルが作成された場合、一時ファイルを使った処理が終了した時点で削除する
      If tempfile IsNot Nothing AndAlso File.Exists(tempfile) Then
        File.Delete(tempfile)
      End If
    End Try
  End Sub
End Class

GetTempFileNameメソッドは呼び出す度に異なるファイル名で一時ファイルを作成する。 作成されるファイル名は拡張子が.tmpとなる以外、どのようなファイル名となるか具体的には定められていない点に注意。

複数の一時ファイルを作成する
using System;
using System.IO;

class Sample {
  static void Main()
  {
    // 一時ファイルを5個作成する
    for (var i = 0; i < 5; i++) {
      Console.WriteLine(Path.GetTempFileName());
    }
  }
}
複数の一時ファイルを作成する
Imports System
Imports System.IO

Class Sample
  Shared Sub Main()
    ' 一時ファイルを5個作成する
    For i As Integer = 1 To 5
      Console.WriteLine(Path.GetTempFileName())
    Next
  End Sub
End Class
実行結果例
C:\Users\user\AppData\Local\Temp\tmp7381.tmp
C:\Users\user\AppData\Local\Temp\tmp7382.tmp
C:\Users\user\AppData\Local\Temp\tmp7383.tmp
C:\Users\user\AppData\Local\Temp\tmp7384.tmp
C:\Users\user\AppData\Local\Temp\tmp7385.tmp
実行結果例
C:\Users\user\AppData\Local\Temp\tmp193D.tmp
C:\Users\user\AppData\Local\Temp\tmp193E.tmp
C:\Users\user\AppData\Local\Temp\tmp193F.tmp
C:\Users\user\AppData\Local\Temp\tmp1940.tmp
C:\Users\user\AppData\Local\Temp\tmp1941.tmp
実行結果例
/tmp/tmpwLasva.tmp
/tmp/tmpAsoGU7.tmp
/tmp/tmpifmkYa.tmp
/tmp/tmpCLRPLa.tmp
/tmp/tmpdnMEyb.tmp
実行結果例
/tmp/tmp4982ccd0.tmp
/tmp/tmp7ac9d034.tmp
/tmp/tmp6e4f291b.tmp
/tmp/tmp175d37cc.tmp
/tmp/tmp6ce3ebfe.tmp

ランダムなファイル名の生成

一時ファイルの名前に用いる目的でランダムなファイル名を生成するには、Path.GetRandomFileNameメソッドを用いることができる。

このメソッドはPath.GetTempFileNameメソッドとは異なりファイル名のみを生成し、ファイル自体は生成しない。 一方、Path.GetRandomFileNameは拡張子もランダムな文字列となる。 拡張子をランダムにしたくない場合にはPath.ChangeExtensionメソッドを使って拡張子を変更する必要がある。 また生成されるファイル名にはディレクトリ名は含まれないので、一時ファイル名として用いる場合はPath.Combineメソッドでパスを結合する必要がある。

ランダムなファイル名で一時ファイルのパスを生成する
using System;
using System.IO;

class Sample {
  static void Main()
  {
    // ランダムなファイル名を5個生成する
    for (var i = 0; i < 5; i++) {
      Console.WriteLine(Path.GetRandomFileName());
    }
    Console.WriteLine();

    // 一時ディレクトリ下に配置するランダムなファイル名(拡張子.tmp)を5個生成する
    for (var i = 0; i < 5; i++) {
      // ランダムなファイル名を生成し、拡張子を.tmpに変更する
      var filename = Path.ChangeExtension(Path.GetRandomFileName(), ".tmp");

      // 生成したファイル名と一時ディレクトリのパスを結合して表示する
      Console.WriteLine(Path.Combine(Path.GetTempPath(), filename));
    }
  }
}
ランダムなファイル名で一時ファイルのパスを生成する
Imports System
Imports System.IO

Class Sample
  Shared Sub Main()
    ' 一時ファイルを5個作成する
    For i As Integer = 1 To 5
      Console.WriteLine(Path.GetRandomFileName())
    Next
    Console.WriteLine()

    ' 一時ディレクトリ下に配置するランダムなファイル名(拡張子.tmp)を5個生成する
    For i As Integer = 1 To 5
      ' ランダムなファイル名を生成し、拡張子を.tmpに変更する
      Dim filename As String = Path.ChangeExtension(Path.GetRandomFileName(), ".tmp")

      ' 生成したファイル名と一時ディレクトリのパスを結合して表示する
      Console.WriteLine(Path.Combine(Path.GetTempPath(), filename))
    Next
  End Sub
End Class
実行結果例
df3kkr3v.wds
qenz2rxf.z0j
ct3sjsvc.eo3
h3awteth.fsm
4k15rb5t.arn

C:\Users\user\AppData\Local\Temp\nq324ouf.tmp
C:\Users\user\AppData\Local\Temp\vna2k0yi.tmp
C:\Users\user\AppData\Local\Temp\hu421sz1.tmp
C:\Users\user\AppData\Local\Temp\52u4clr2.tmp
C:\Users\user\AppData\Local\Temp\ul4simjx.tmp
実行結果例
ls1xc1gq.nup
r1prcdxe.zgz
hk5f2hnq.mnx
annuxtbh.zxa
eggtatzn.r0m

C:\Users\user\AppData\Local\Temp\4z4auewl.tmp
C:\Users\user\AppData\Local\Temp\rqtbpzil.tmp
C:\Users\user\AppData\Local\Temp\5l0g52sc.tmp
C:\Users\user\AppData\Local\Temp\4o4r2pdh.tmp
C:\Users\user\AppData\Local\Temp\tcw0zr0w.tmp
実行結果例
hhyqkyhx.jis
ex5b14ki.gf4
ndo4d2ej.10p
1xq34d4w.duw
cw0kkquq.xkt

/tmp/dbh1pch3.tmp
/tmp/qawqr02d.tmp
/tmp/uhxjfogo.tmp
/tmp/00f3bgvp.tmp
/tmp/dxnwzupo.tmp
実行結果例
o1fx94ld.dsl
0wkjldn8.pgh
mwsuo979.o24
qyvua564.pbn
vc0721i2.nud

/tmp/fx930rjf.tmp
/tmp/d0ew8uk1.tmp
/tmp/elkyt5r3.tmp
/tmp/w4pd3fhj.tmp
/tmp/bqms56w7.tmp

この例では生成したファイル名が衝突する可能性があるため、実際に一時ファイル名として使用する場合は、すでにファイル名が使用されていないかを調べる必要がある。