fs.readFileSync()のファイルをキャプチャする方法は?


135

node.js内のreadFile()はエラーをキャプチャする方法を示していますが、エラー処理に関するreadFileSync()関数のコメントはありません。そのため、ファイルがないときにreadFileSync()を使用しようとすると、エラーが発生しますError: ENOENT, no such file or directory

スローされている例外をキャプチャするにはどうすればよいですか?docoにはどの例外がスローされるかが記載されていないため、どの例外をキャッチする必要があるのか​​わかりません。汎用的な「可能なすべての例外をキャッチする」スタイルのtry / catchステートメントは好きではないことに注意してください。この場合、ファイルが存在しないときに発生する特定の例外をキャッチし、readFileSyncを実行しようとします。

接続の試行を処理する前の起動時にのみ同期機能を実行しているため、同期機能を使用してはならないというコメントは不要です:-)


1
私の新しい回答でfs.existsSync()見ることができるように使用することもできます
Francisco Presencia '27 / 09/27

回答:


206

基本的fs.readFileSyncに、ファイルが見つからない場合はエラーをスローします。このエラーはErrorプロトタイプに由来し、を使用してスローされるthrowため、キャッチする唯一の方法はtry / catchブロックを使用することです。

var fileContents;
try {
  fileContents = fs.readFileSync('foo.bar');
} catch (err) {
  // Here you get the error when the file was not found,
  // but you also get any other error
}

残念ながら、プロトタイプチェーンを見ただけでは、どのエラーがスローされたかを検出できません。

if (err instanceof Error)

あなたができる最善であり、これはほとんどの(すべてではないにしても)エラーに当てはまります。したがって、私はあなたが一緒に行くお勧めしたいcodeプロパティとその値をチェックします。

if (err.code === 'ENOENT') {
  console.log('File not found!');
} else {
  throw err;
}

このようにして、この特定のエラーのみを処理し、他のすべてのエラーを再スローします。

または、エラーのmessageプロパティにアクセスして、詳細なエラーメッセージを確認することもできます。この場合は次のようになります。

ENOENT, no such file or directory 'foo.bar'

お役に立てれば。


1
ありがとう、それは私が探していた情報です。私はそれが特定のタイプのエラーであると推定しました。私は、try / catchがどのように機能するかを誤解していることに気付いたばかりで、特定のエラータイプ(Javaの一種)をキャッチできると思っていました。情報Goloをありがとう。:-)
メタルスキン、2013年

2
またEACCES、ファイルは存在するが、権限がないために読み取ることができない場合のifステートメントでコードをチェックする必要があります
Gergely Toth

21

私はこれを処理するこの方法を好みます。ファイルが同期して存在するかどうかを確認できます。

var file = 'info.json';
var content = '';

// Check that the file exists locally
if(!fs.existsSync(file)) {
  console.log("File not found");
}

// The file *does* exist
else {
  // Read the file and do anything you want
  content = fs.readFileSync(file, 'utf-8');
}

注:プログラムがファイルも削除する場合、コメントに記載されているように、これには競合状態があります。ただし、ファイルを削除せずに書き込みまたは上書きのみを行う場合は、これで問題ありません。


2
現在、fs.existsSyncは非推奨でありません。「fs.exists()は非推奨ですが、fs.existsSync()は非推奨です。」
falkodev 2017

17
まったく良くない。existsSyncとreadFileSyncの呼び出しの間にファイルがディスクから削除された場合はどうなりますか?これで、コードには発生を待機する競合状態が組み込まれています...
tkarls '30

2
@tkarlsはい、それは完全に正しいです。それは、Node.jsをまだ学習していて、競合状態にある2015年に書かれました。ただし、注意すべき点が2つあります。この競合状態の可能性は非常に低いため、基本的に無視できます。2つ目と最初のスーパーシードは、最近のコードでasync / awaitを使用してtry / catchをより柔軟にすることです。 「その他」の例外(Nodeは例外に対応しているため)。
フランシスコプレセンシア2017

1
彼らがそうするまで、競争状態は重要ではありません。このような回答は、ソフトウェアにバグが多い理由、コンピューターを頻繁に再起動する必要がある理由、セキュリティの脆弱性が非常に多い理由などです。スタックオーバーフローには、潜在的に有害な回答のフラグが必要です。
Jonathan Tran

N年後、さらに多くを学習した後の別のコメント(回答にメモを追加)。これは書き込み専用のファイルシステムプログラムのコンテキストでは完全に問題ありませんが、ファイルも削除できる場合、これは競合状態にあり、私が最近書いているコードではない(特にそのSync!のため)。またfiles、非同期とtry / catchを簡単にするために学んできたすべてのパッケージを作成しました。
フランシスコプレセンシア

11

エラーをキャッチしてから、エラーの種類を確認する必要があります。

try {
  var data = fs.readFileSync(...)
} catch (err) {
  // If the type is not what you want, then just throw the error again.
  if (err.code !== 'ENOENT') throw err;

  // Handle a file-not-found error
}

...「スローerr」にしてください。
drudru

関数の非同期バージョンで同じエラーをキャッチする方法はありますか?
KiJéy18年

1
@KiJéy非同期コードは、コールバックの最初の引数としてエラーを渡すため、同じ動作が得られることを確認すると、
loganfsmyth

4

これらのシナリオでは、すぐに呼び出されるラムダを使用します。

const config = (() => {
  try {
    return JSON.parse(fs.readFileSync('config.json'));
  } catch (error) {
    return {};
  }
})();

async バージョン:

const config = await (async () => {
  try {
    return JSON.parse(await fs.readFileAsync('config.json'));
  } catch (error) {
    return {};
  }
})();

ECMAScript 6に対するソリューションであることを投稿に追加することをお勧めします。18/ 01/01の時点で、ブラウザーの使用率が約77%のIEからのサポートはありません(caniuse.com/#feat=arrow-functions)。私は好奇心旺盛ですが、IEユーザーにはどのように対応しますか?
メタルスキン、

2
@Metalskin Webpack + Babel。ただし、fsNodeモジュール
sdgfsdh

ああ、私はノードと連絡が取れていないので、質問したところ、ノードはES6をサポートしていないと思われます(間違っている可能性があります)。
ちょっと

これを更新する... fs.readFileAsync()は今fs.readFile() でもあり、非同期機能をnode.jsのtry / catchの中に入れるべきではありません。try / catchは非同期であるため、エラーが発生することはありません。代わりに、コールバックでエラーを渡し、そこにそれを扱う:fs.readFile('/etc/passwd', (err, data) => { if (err) throw err; console.log(data); }); から:nodejs.org/dist/latest-v12.x/​​docs/api/...
KH B

約束が拒否され、あなたが約束を待っている場合、try-catchが呼び出されると思います。
sdgfsdh

0

代わりにAsyncを使用して、NodeJSで持っている唯一のスレッドをブロックしないようにしてください。この例を確認してください:

const util = require('util');
const fs = require('fs');
const path = require('path');
const readFileAsync = util.promisify(fs.readFile);

const readContentFile = async (filePath) => {
  // Eureka, you are using good code practices here!
  const content = await readFileAsync(path.join(__dirname, filePath), {
    encoding: 'utf8'
  })
  return content;
}

後で他の関数からのtry / catchでこの非同期関数を使用できます。

const anyOtherFun = async () => {
  try {
    const fileContent = await readContentFile('my-file.txt');
  } catch (err) {
    // Here you get the error when the file was not found,
    // but you also get any other error
  }
}

ハッピーコーディング!


0

JavaScriptのtry…catchメカニズムを使用して、非同期APIによって生成されたエラーをインターセプトすることはできません。初心者によくある間違いは、エラーファーストコールバック内でスローを使用しようとすることです。

// THIS WILL NOT WORK:
const fs = require('fs');

try {
  fs.readFile('/some/file/that/does-not-exist', (err, data) => {
    // Mistaken assumption: throwing here...
    if (err) {
      throw err;
    }
  });
} catch (err) {
  // This will not catch the throw!
  console.error(err);
}

fs.readFile()に渡されるコールバック関数が非同期で呼び出されるため、これは機能しません。コールバックが呼び出されるまでに、try…catchブロックを含む周囲のコードはすでに終了しています。コールバック内でエラーをスローすると、ほとんどの場合、Node.jsプロセスがクラッシュする可能性があります。ドメインが有効になっている場合、またはハンドラーがprocess.on( 'uncaughtException')に登録されている場合、そのようなエラーはインターセプトされる可能性があります。

リファレンス:https : //nodejs.org/api/errors.html

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.