Quantcast
Channel: Node.jsタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9092

no such file or directory, open に対処する

$
0
0

fsを使用して、上のディレクトリのファイルを取得しようとするとError: ENOENT: no such file or directory, open が出て、喚いていたが解決したので残しておく。

ファイル内容

先に記しておくが、後の説明を読みながら解釈することを勧める。

ディレクトリ構成

test(親ディレクトリ)
   ├── src
   │   └── fileManeger.js
   ├── config ←(ここに出力)
   │     
   └── main.js

main.js

constfs=require('fs');//nodeモジュール読みこみconstfileManegerClass=require('./src/fileManeger.js')//クラスファイル読みこみconstfileManeger=newfileManegerClass(fs);//インスタンス化constcontent={"name":"taro","age":30};fileManeger.write1(content);//fsをメソッド内でインポートする ファイルの相対パスをmain.jsがあるディレクトリからにするfileManeger.write2(content);//fsをメソッド内でインポートする ファイルの相対パスをmain.jsがあるディレクトリからにするfileManeger.write3(content);//fsをコンストラクタから受け取る ファイルの相対パスをfileManeger.jsがあるディレクトリからにするfileManeger.write4(content);//fsをメソッド内でインポートする ファイルの相対パスをfileManeger.jsがあるディレクトリからにする

fileManeger.js

classfileManeger{constructor(fs){this.fs=fs;};//fsをコンストラクタから受け取る ファイルの相対パスをmain.jsがあるディレクトリからにするasyncwrite1(content){constfs=this.fs;try{fs.writeFileSync('./config/write-1.json',JSON.stringify(content,null,"\t"),'utf8');console.log(`write1 complete`)}catch(e){console.log(`write1 fail\n-------------------------------\n${e}\n-------------------------------\n`)}};//fsをメソッド内でインポートする ファイルの相対パスをmain.jsがあるディレクトリからにするasyncwrite2(content){constfs=require('fs');try{fs.writeFileSync('./config/write-2.json',JSON.stringify(content,null,"\t"),'utf8');console.log(`write2 complete`)}catch(e){console.log(`write2 fail\n-------------------------------\n${e}\n-------------------------------\n`)}};//fsをコンストラクタから受け取る ファイルの相対パスをfileManeger.jsがあるディレクトリからにするasyncwrite3(content){constfs=this.fs;try{fs.writeFileSync('../config/write-3.json',JSON.stringify(content,null,"\t"),'utf8');console.log(`write3 complete`)}catch(e){console.log(`write3 fail\n-------------------------------\n${e}\n-------------------------------\n`)}};//fsをメソッド内でインポートする ファイルの相対パスをfileManeger.jsがあるディレクトリからにするasyncwrite4(content){constfs=require('fs');try{fs.writeFileSync('../config/write-4.json',JSON.stringify(content,null,"\t"),'utf8');console.log(`write4 complete`)}catch(e){console.log(`write4 fail\n-------------------------------\n${e}\n-------------------------------\n`)}};};module.exports=fileManeger;//クラス出力

やりたいこと

main.jsから./src/fileManeger.js(クラス)を読み込み、configディレクトリ内にファイルを出力する。

はまった理由

結論から言うと、fsのパスの指定の仕方が悪かった。私は最初、fileManeger.jsでfsは呼び出されるのだからパスはそのファイルからたどるのだろうと勝手に予測して../config/write.jsonと指定していた。
しかしながら、fsはパスを作業ディレクトリからたどる。ここでいう作業ディレクトリとはnodeで実行したファイルがあるディレクトリのこと、つまりtestディレクトリである。
ということは私が指定したディレクトリはtestディレクトリの上層にあることになってしまっていたのだ。

│
├──config(???? 幻のディレクトリ)
│
└──test(ここから ../config/write.json)
      ├── src
      │   └── fileManeger.js
      ├── config ←(ここを指定したはずが...)
      │     
      └── main.js

試してみた

testディレクトリでmain.jsを実行する。
比較のため、fsモジュールの読み込み箇所と出力ファイル名、パスを変えている。
一応、モジュールをインポートする場所は関係ないことを示すために4つのパターンを用意した。

メソッド名パスモジュールの読み込み出力ファイル名
write1./config/write-1.jsonコンストラクタからwrite-1.json
write2./config/write-2.jsonメソッド内でwrite-2.json
write3../config/write-3.jsonコンストラクタからwrite-3.json
write4../config/write-4.jsonメソッド内でwrite-4.json

実行結果

console.png

./config/write-〇.jsonのパスであるwrite1メソッドとwrite2メソッドは成功している。
一方、../config/write-〇.jsonのパスであるwrite3メソッドとwrite4メソッドは読み込めないとエラーが出ている。

結論

以上のことから、fsのファイルパスの起点はnode.jsで実行しているファイルがあるディレクトリであることがわかった

よって、fsを使用したコードのエラーでError: ENOENT: no such file or directory, openが出た際は、ファイルのパスがnode.jsで実行しているファイルがあるディレクトリからの相対パスになっているか確認しよう

参考

公式ドキュメントにファイルパスの話が出ているのでその部分のリンクを記載しておく。
Node.js v14.13.1 Documentation

検証に使用したソースコード
github huda0209/qitta_fs-sample


Viewing all articles
Browse latest Browse all 9092

Latest Images

Trending Articles