Node.js で ファイル / ディレクトリ の 存在を確認する 方法

0 件のコメント

ファイル / ディレクトリ の 存在確認

ファイル / フォルダの存在確認を行うには fs.stat() または fs.access() を利用します。 詳細は後に記載しますが、フォルダを確認した後にファイル読み書きを行うのであれば fs.access() でアクセス権含めて確認するのが良さそうです。

ということで、ここでは fs.access() でのフォルダ存在確認のサンプルコードを載せます。

サンプルコード

var fs = require("fs");
var path = require("path");

var filepath = "./data/message.txt";

var dirname = path.dirname(filepath);

fs.access(dirname, fs.constants.R_OK | fs.constants.W_OK, (error) => {
  if (error) {
    if (error.code === "ENOENT") {
      fs.mkdirSync(dirname);
    } else {
      return;
    }
  }

  fs.writeFile(filepath, "Hello World !", "utf8", (error) => { });
});

解説

第1引数にアクセス可能か確認したいフォルダまたはファイルへのパスを指定し、 第2引数に確認したいアクセス権を指定します。 確認が終わると第3引数で指定されたコールバックが呼ばれます。 第3引数のコールバックはエラーオブジェクト error のみを引数とするメソッドです。 指定したファイルまたはフォルダに対して指定されたアクセス権がある場合はエラーオブジェクトが設定されず、それ以外の場合にエラーオブジェクトが設定されます。

第2引数で指定できるアクセス権種別は以下の通りです。

種別 説明
fs.constants.F_OK ファイルが存在しているかどうかを判定します。 ファイルに対するアクセス権は考慮しません。 第2引数のアクセス権に関する設定を省略した場合のデフォルトは fs.constants.F_OK になります。
fs.constants.R_OK 実行プロセスから読み取り権限があるかどうか。
fs.constants.W_OK 実行プロセスから書き込み権限があるかどうか。
fs.constants.X_OK 実行プロセスから実行権限があるかどうか。

ファイルまたはフォルダへアクセスした際に想定される代表的なエラーは以下の通りです。

error.code 説明
"ENOENT" 該当するファイルまたはフォルダがありません。
"EPERM" 操作する権限がありません。
"EBUSY" リソースが処理中またはロックされています。

fs.stat() vs fs.access()

Node.js の APIドキュメント を読んでいると、フォルダの存在確認を行うには fs.stat() または fs.access() を利用するよう書かれています。 それぞれのメソッドでできることは次の通りです。

fs.stat()
指定されたファイルやフォルダの情報(ステータス)を取得するメソッド
fs.access()
指定されたファイルやフォルダへ実行ユーザーがアクセス可能かどうかを確認するメソッド

このことから考えると、一般的にファイルやフォルダの存在チェックは fs.access() を使うのが良さそうです。

ファイル読み書き前の存在確認

Node.js APIドキュメント では次のようなことも記述されています(原文は英語ですが、以下は原文の英語を日本語訳したもの)。

fs.open()fs.readFile()fs.writeFile() を呼び出す前に fs.access() を使ってファイルへのアクセス権を確認することは推奨されません。 2つの処理の間(「アクセス権の確認」と「ファイル実処理」の間)で他のプロセスがファイルの状態を変更する可能性があるため、前述のような実装を行うとレースコンディションを引き起こします。 代わりに、ファイルの open / read / write を直接行い、ファイルアクセスできなかった場合に発生する例外を処理する必要があります。

つまり「アクセスできるか確認してからアクセスする」ではなく「とりあえずアクセスしてダメだったら例外処理する」という考え方で実装を行うことが推奨されているようです。 これを具体的に実装してみると以下のようになります。

サンプルコード (ファイル読み込み)

var fs = require("fs");

fs.readFile("./data/test.json", "utf8", (error, data) => {
  if (error) {
    console.log(error.message);
    throw error;
  }
  console.log(data);
});

サンプルコード (ファイル書き込み)

var fs = require("fs");

fs.mkdir("./data/", (error) => {
  if (error && error.code !== "EEXIST") {
    console.log(error.message);
    throw error;
  }
  fs.writeFile("./data/message.json", data, "utf8", (error) => {
    if (error) {
      console.log(error.message);
      throw error;
    }
  });
});

今回の記事は参考になったでしょうか? ファイル / フォルダの存在確認のポイントは以下のようになります。

  • 基本的にはいきなり open / read / write を行う実装が推奨
  • どうしてもチェックしたいなら fs.access() を使う

参考記事