LoginSignup
1
1

More than 3 years have passed since last update.

【Node.js入門】ファイル&jsonファイルI/Oをやってみた♬

Last updated at Posted at 2020-06-28

常識だからだと思うけど、Node.js始めたのでファイル入出力やろうとすると、割と動かないし、記事がもう一息なので、自分で整理しておこうと思う。
今回は、テキストファイル書き出し/読込とJsonファイルの書き出し/読込をやろうと思う。
参考は以下のとおり
【参考】
Node.jsを使ったやっつけのファイル操作
[Node.js]ファイルの作成、書き込み、追記をする
JSのObjectをforEachで処理する方法

やったこと

・テキストファイル書き出し/読込
・Jsonファイル書き出し/読込

・テキストファイル書き出し/読込

これは、参考①で取り上げているので、まんま動くかなと思ったが、少し違うような気もしたので、参考②を見つつ、実際動かして以下のコードで動くことを確認した。

コード解説

まず、参考①と②を比較するとvarなのかconstなのか。。以下の参考④から、スコープが以下のとおりだということです。
なので、今回はconstで足りているようです。
【参考】
var/let/constの使い分けのメモ

  • var;
    • 関数内のどこでもvarの宣言を書ける
    • 関数のどこで宣言しても、先頭で定義したものとしてみなされる
    • 関数スコープである
    • 使いたい変数は先頭部分で全て定義するのが定石
  • let;
    • ブロックスコープ
    • スコープを狭く出来るため影響範囲を狭められる
  • const;
    • 再代入不可能な変数を作る (つまり定数にできる)
    • letと同じブロックスコープ

したがって、流動性に関しては、var>let>constの順に融通性があるようです。因みに以下の関数内のletはconstにするとisExistを変更している部分でエラーが出ます。

const fs = require('fs');

Node.jsの予約語を注意しつつ、以下のような関数名(参考⑥から関数の命名規則;関数名は先頭小文字のキャメルケース。例:sendMessage)にしました。
【参考】
予約語
JavaScriptの命名規則を現役エンジニアが解説【初心者向け】
以下がファイルの存在確認の関数です。

function checkFile(filePath) {
  let isExist = false;
  try {
    fs.statSync(filePath);
    isExist = true;
  } catch(err) {
    isExist = false;
  }
  return isExist;
}

以下は、ファイルにstreamを書き込む関数です。streamは文字列です。

function writeFile(filePath, stream) {
  let result = false;
  try {
    fs.writeFileSync(filePath, stream);
    return true;
  } catch(err) {
    return false;
  }
}

以下がファイルの読み込み関数です。読み込まれた文字列がcontentに格納されリターンされます。

function readFile(filePath) {
  let content = new String();
  if(checkFile(filePath)) {;
    content = fs.readFileSync(filePath, 'utf8');
  }
  return content;
};

以下がファイルを削除する関数です。

function delFile(filePath){
  let result = false;
  try {
    fs.unlinkSync(filePath);
    return true;
  } catch(err) {
    return false;
  }
}

以下は既存ファイルにアペンドする関数です。


function addFile(filePath, stream) {
  let result = false;
  try {
    fs.appendFileSync(filePath, stream);
    return true;
  } catch(err) {
    return false;
  }
}

ということで、以下で一連の関数を実行しています。

const check_result = checkFile("file_");
console.log("check_result", check_result)
const write_result = writeFile("file_", "aaa")
console.log("write_result", write_result)
const add_result = addFile("file_", "\n"+"bbb")
console.log("add_result", add_result)
const read_result = readFile("file_")
console.log("read_result",typeof(read_result))
console.log(read_result)

結果は以下のとおり、あんまりおもしろくはないけど、正しく実行できています。
ちなみに、read_resultはstr型です。

check_result true
write_result true
add_result true
read_result string
aaa
bbb

・Jsonファイル書き出し/読込

次は、利用度の高いと思われるJsonファイルの書き出し/読込をやります。参考③のまんまで、以下のコードで実行できます。
実は、まず以下の参考⑥をやりましたが、jsonObject.list.forEach((obj)が動きませんでした。ということで参考③にたどり着きました。
【参考】
Node.jsでJSONを読み込んで加工して書き出す
早速、動くコードを見てみます。
まず、参考⑥を動かします。以下は無事に読み込みました。

var obj = JSON.parse(fs.readFileSync('package.json', 'utf8'));
console.log("jsonObject",obj)

結果は、以下のとおりで、Jsonファイルです。

package.json
jsonObject {
  name: 'test-linebot',
  version: '1.0.0',
  description: '',
  main: 'index.js',
  scripts: { test: 'echo "Error: no test specified" && exit 1' },
  keywords: [],
  author: '',
  license: 'ISC',
  dependencies: {
    '@line/bot-sdk': '^7.0.0',
    express: '^4.17.1',
    'node-tfidf': '0.0.2',
    'tf-idf.js': '^0.3.2'
  }
}

そして、参考③のコードも以下のように動きます。

// こういうオブジェクトがあったとしてね
var obj = { tanuki:'pon-poko', kitsune:'kon-kon', neko:'nyan-nyan' };

// こうすればOK
Object.keys(obj).forEach(function (key){
  console.log(key + "" + obj[key] + "と鳴いた!");
});

出力もコード(keyとobj[key]の内容)も見やすいです。

tanukiはpon-pokoと鳴いた!
kitsuneはkon-konと鳴いた!
nekoはnyan-nyanと鳴いた!

そして、以下でいよいよjsonファイルに書き出します。

const result = {};
Object.keys(obj).forEach(function(key){
    result[key] = obj[key];
    //console.log(key,obj[key])
});
fs.writeFileSync('output.json', JSON.stringify(result));

output.jsonファイルの中身は以下のとおりです。
{"tanuki":"pon-poko","kitsune":"kon-kon","neko":"nyan-nyan"}
次に、Jsonファイルの読み書きの関数を以下のように定義しました。
まず、読み込み関数は以下のとおりです。

function readJF(filePath) {
  let content = {};
  if(checkFile(filePath)) {;
    content = JSON.parse(fs.readFileSync(filePath, 'utf8'));
  }
  return content;
};

次に、書込み関数は以下のとおりです。
Jsonファイルの追記のコードは、場合によりそうなので、適切なものが思いつきませんでした。一応、参考⑦にいくつかの例があります。
【参考】
How do I add to an existing json file in node.js

function writeJF(filePath,obj) {
    let result_ = false;
    const result = {};
    Object.keys(obj).forEach(function(key){
        result[key] = obj[key];
        //console.log(key,obj[key])
    });
    fs.writeFileSync(filePath, JSON.stringify(result));
    result_ = true;
    return result_;
};

最後に以下のとおり、実行してみました。

const readJ_result = readJF("package.json")
console.log("readJ_result",readJ_result)
console.log("readJ_result.name")
console.log(readJ_result['name'])
var writeJ_result = writeJF("test_.json",readJ_result)

結果は以下のとおりです。

readJ_result {
  name: 'test-linebot',
  version: '1.0.0',
  description: '',
  main: 'index.js',
  scripts: { test: 'echo "Error: no test specified" && exit 1' },
  keywords: [],
  author: '',
  license: 'ISC',
  dependencies: {
    '@line/bot-sdk': '^7.0.0',
    express: '^4.17.1',
    'node-tfidf': '0.0.2',
    'tf-idf.js': '^0.3.2'
  }
}
readJ_result.name
test-linebot

そして、test_.jsonの中身は以下のとおりで、以下に示すようにpackage.jsonと同一内容です。しかし、見た目が構造化されていないことが分かります。

test_.json
{"name":"test-linebot","version":"1.0.0","description":"","main":"index.js","scripts":{"test":"echo \"Error: no test specified\" && exit 1"},"keywords":[],"author":"","license":"ISC","dependencies":{"@line/bot-sdk":"^7.0.0","express":"^4.17.1","node-tfidf":"0.0.2","tf-idf.js":"^0.3.2"}}
package.json
{
  "name": "test-linebot",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@line/bot-sdk": "^7.0.0",
    "express": "^4.17.1",
    "node-tfidf": "0.0.2",
    "tf-idf.js": "^0.3.2"
  }
}

そこで、参考のとおり、fs.writeFileSync(filePath, JSON.stringify(result, null, '\t'));と改行コードを入れると以下のように成形されました。
※indentが少し広いですが、...
【参考】
JSON.stringify()

{
    "name": "test-linebot",
    "version": "1.0.0",
    "description": "",
    "main": "index.js",
    "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
    },
    "keywords": [],
    "author": "",
    "license": "ISC",
    "dependencies": {
        "@line/bot-sdk": "^7.0.0",
        "express": "^4.17.1",
        "node-tfidf": "0.0.2",
        "tf-idf.js": "^0.3.2"
    }
}

というわけで、fs.writeFileSync(filePath, JSON.stringify(result, null, ' '));

{
 "name": "test-linebot",
 "version": "1.0.0",
 "description": "",
 "main": "index.js",
 "scripts": {
  "test": "echo \"Error: no test specified\" && exit 1"
 },
 "keywords": [],
 "author": "",
 "license": "ISC",
 "dependencies": {
  "@line/bot-sdk": "^7.0.0",
  "express": "^4.17.1",
  "node-tfidf": "0.0.2",
  "tf-idf.js": "^0.3.2"
 }
}

fs.writeFileSync(filePath, JSON.stringify(result, null, ' '));
やっと答えにたどり着きました。
※ここは趣味の世界ですね

{
  "name": "test-linebot",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@line/bot-sdk": "^7.0.0",
    "express": "^4.17.1",
    "node-tfidf": "0.0.2",
    "tf-idf.js": "^0.3.2"
  }
}

まとめ

・ファイルとjsonファイルの書込み/読込を整理してみた

・jsonファイルの追記はやれそうだが、まだ適当な関数に昇華できていない
・ファイルを利用してbotを充実したいと思う

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1