2021/09/11

TypeScript 第7回 ファイル読み込み

第5回で, コマンドライン引数から式を与えられるようにしました. 次は, ファイルからの読み込みに対応したくなります. この記事では, ファイルを読み込むために調べた結果を書きます. 

1)fs.readFileSync関数

Node.jsのfsモジュールに定義してある関数を使えば, ファイルを読み込めます. package.jsonファイルを読み込んで, コンソールに出力するコードは次のようになります.

import * as fs from 'fs'
let text = fs.readFileSync('./package.json')
console.log(text.toString())

1行目でfsモジュールをインポートし, 2行目でreadFileSync関数を使ってpackage.jsonファイルを読み込み, 結果をtextに設定しています. 3行目でコンソールに出力していますが, toString()を使って文字列に変換しています. 

この結果を使えば, ファイルから逆ポーランド記法で記述した式を読み込み, 計算できます. 

2)非同期処理

readFileSync関数を使えば, 目的を達成できますが, TypeScriptを使いこなすためには, fsモジュールのreadFile関数を避けて通れません. readFile関数の使い方をもう少し調べます.

readFile関数には, ファイルから読み込んだ結果を処理するためのコールバック関数を与えます. コードを書くと次のようになりました. 

import * as fs from 'fs'

fs.readFile('./package.json', (errorresult=> {
    if (error) {
        console.log('エラー'error)
    } else {
        console.log(result.toString())
    }
})

console.log('プログラム終了')

実行した結果は次のようになりました.

PS C:\TSWork\ReadFile> .\node_modules\.bin\tsc
PS C:\TSWork\ReadFile> node .\dist\index.js
プログラム終了
{
  "name": "readfile",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@types/node": "^16.6.1",
    "typescript": "^4.3.5"
  }
}

PS C:\TSWork\ReadFile>

ファイルの読み込みを非同期に実行するため, プログラムの最後に書いてある「プログラム終了」をコンソールに出力する処理が終わってから, ファイルを読み込んだ結果を表示しています. また, readFile関数の戻り値はvoidであるため, readFileSync関数のようにファイルから読み込んだ結果を返しません. このままでは, コールバック関数の中に処理を書き始めてしまい, 所謂, コールバック地獄に陥ってしまいます. 

3)Promise

コールバック地獄から逃れるためにPromiseを使います. コードは次のようになりました. 

import * as fs from 'fs'

function readTextFile(filepathstring): Promise<string> {
    return new Promise((resolvereject=> {
        fs.readFile(filepath, (errorresult=> {
            if (error) {
                reject(error)
            } else {
                resolve(result.toString())
            }
        })
    })
}

async function readExec() {
    console.log('ファイル読み込み開始')
    let text = await readTextFile('./package.json')
    console.log(text)
}

readExec()

console.log('プログラム終了')

readTextFile関数では, fs.readFile関数の実行をPromiseで包んで返すようにしています. 

readTextFile関数は非同期に実行するので, 実行結果を待つためにawaitを指定します. awaitを使うためには, asyncで囲まなくてはなりませんので, readExec関数を定義しています. 実行結果は次のようになりました.

PS C:\TSWork\ReadFile> .\node_modules\.bin\tsc
PS C:\TSWork\ReadFile> node .\dist\index.js
ファイル読み込み開始
プログラム終了
{
  "name": "readfile",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@types/node": "^16.6.1",
    "typescript": "^4.3.5"
  }
}

PS C:\TSWork\ReadFile>

相変わらず, 「プログラム終了」をコンソールに出力してから, ファイルから読み込んだ結果を出力していますが, readTextFile関数の結果を変数に代入できるので, 扱いやすくなりました. 

4)まとめ

この記事では, ファイルから読み込む方法を調べました. ファイルの読み込みは非同期で実行するため, 慣れるまで時間がかかりそうです. 最後に, この記事で使用したNode.jsとTypeScriptのバージョンは次の通りです.

PS C:\TSWork\ReadFile> node --version
v14.17.4
PS C:\TSWork\ReadFile> .\node_modules\.bin\tsc --version
Version 4.3.5
PS C:\TSWork\ReadFile>

0 件のコメント:

コメントを投稿

ヒューマン・リソース・マシーン 入社41年目−並べ替えよ

目次 1)課題 0を終端とした文字列がいくつか流れてきます。各文字列に対してソート(並べ替え)を行い、小さい順(昇順)に右側へ運んでください。 2)状況の確認 この問題では, 予めコードが入っています. このコードを実行して, 何をするコードなのか確かめます.  左のコンベアから...