src/NTFile.js
/**
* NTFile.js
* Copyright 2013-2023 natade < https://github.com/natade-jp >
*
* The MIT license.
* https://opensource.org/licenses/MIT
*/
//@ts-check
import fs from "fs";
import child_process from "child_process";
/**
* ファイルクラス
*/
export default class NTFile {
/**
* UTF-8 でテキストを書き込む
* @param {string} path
* @param {string} text
*/
static saveTextFile(path, text) {
fs.writeFileSync(path, text, "utf-8");
}
/**
* UTF-8 with BOM でテキストを書き込む
* @param {string} path
* @param {string} text
*/
static saveTextFileWithBOM(path, text) {
if (text.length > 0 && text.charAt(0) !== "\uFEFF") {
fs.writeFileSync(path, "\uFEFF" + text, "utf-8");
} else {
fs.writeFileSync(path, text, "utf-8");
}
}
/**
* BOMあり/なしに関わらず、UTF-8のテキストを読み込む
* @param {string} path
* @returns {string} テキストデータ
*/
static loadTextFile(path) {
const text = fs.readFileSync(path, "utf-8");
if (text.length > 0 && text.charAt(0) === "\uFEFF") {
return text.substring(1);
} else {
return text;
}
}
/**
* バイナリデータを書き込む
* @param {string} path
* @param {number[]} binary
*/
static saveBinaryFile(path, binary) {
const buffer = new Uint8Array(binary.length);
for (let i = 0; i < buffer.length; i++) {
buffer[i] = binary[i];
}
fs.writeFileSync(path, buffer);
}
/**
* バイナリデータを読み込む
* @param {string} path
* @returns {number[]} バイナリデータ
*/
static loadBinaryFile(path) {
const buffer = fs.readFileSync(path);
const binary = new Array(buffer.length);
for (let i = 0; i < buffer.length; i++) {
binary[i] = buffer.readUInt8(i);
}
return binary;
}
/**
* 実行する
* @param {string} command
*/
static exec(command) {
const execSync = child_process.execSync;
execSync(command);
}
/**
* ファイルが存在するか調べる
* @param {string} path
* @return {boolean}
*/
static isExist(path) {
try {
fs.statSync(path);
return true;
} catch (error) {
if (error.code === "ENOENT") {
return false;
} else {
console.log(error);
}
}
return false;
}
/**
* ディレクトリかどうか判定する
* @param {string} path
* @return {boolean}
*/
static isFile(path) {
if (!NTFile.isExist(path)) {
return false;
}
return fs.statSync(path).isFile();
}
/**
* ディレクトリかどうか判定する
* @param {string} path
* @return {boolean}
*/
static isDirectory(path) {
if (!NTFile.isExist(path)) {
return false;
}
return fs.statSync(path).isDirectory();
}
/**
* ファイルをコピーする
* @param {string} from
* @param {string} to
*/
static copy(from, to) {
const bin = fs.readFileSync(from);
fs.writeFileSync(to, bin);
}
/**
* ファイルを削除する
* @param {string} path
*/
static deleteFile(path) {
if (!NTFile.isExist(path)) {
return;
}
fs.unlinkSync(path);
}
/**
* フォルダを作成する
* @param {string} path
*/
static makeDirectory(path) {
if (NTFile.isExist(path)) {
return;
}
fs.mkdirSync(path);
}
/**
* 追加条件
* @typedef {Object} NTFilterObject
* @property {Array<RegExp|string>} [includes]
* @property {Array<RegExp|string>} [excludes]
*/
/**
* 指定したディレクトリ及び条件下のファイルのリストを作成
* @param {string} target_directory
* @param {NTFilterObject} [filter]
* @return {Array<string>}
*/
static createList(target_directory, filter) {
const dir_path = target_directory.replace(/[\\/]+$/, "");
const load_list = fs.readdirSync(dir_path);
const list = [];
for (let i = 0; i < load_list.length; i++) {
list[i] = dir_path + "/" + load_list[i];
}
for (let i = 0; i < list.length; i++) {
if (NTFile.isDirectory(list[i])) {
const new_list = fs.readdirSync(list[i]);
for (let j = 0; j < new_list.length; j++) {
/**
* @type {string}
*/
const add_file = list[i] + "/" + new_list[j];
list.push(add_file);
}
}
}
if (filter == undefined) {
return list;
}
/**
* @type {Array<string>}
*/
const filtered_list = [];
for (const i in list) {
const name = list[i];
let is_target = false;
if (filter.includes) {
for (const j in filter.includes) {
const fi = filter.includes[j];
if (typeof fi === "string") {
if (name.indexOf(fi) === -1) {
is_target = true;
break;
}
} else if (fi.test(name)) {
is_target = true;
break;
}
}
}
if (!is_target) {
continue;
}
if (filter.excludes) {
for (const j in filter.excludes) {
const fi = filter.excludes[j];
if (typeof fi === "string") {
if (name.indexOf(fi) === -1) {
is_target = false;
break;
}
} else if (fi.test(name)) {
is_target = false;
break;
}
}
}
if (!is_target) {
continue;
}
filtered_list.push(name);
}
return filtered_list;
}
/**
* フォルダを削除する
* @param {string} path
*/
static deleteDirectory(path) {
if (!NTFile.isDirectory(path)) {
return;
}
{
// まずはファイルのみを全消去
const list = NTFile.createList(path);
for (let i = 0; i < list.length; i++) {
if (NTFile.isFile(list[i])) {
NTFile.deleteFile(list[i]);
}
}
}
// フォルダの中身が0のフォルダを繰り返し削除
for (let i = 0; i < 10; i++) {
const list = NTFile.createList(path);
for (let j = 0; j < list.length; j++) {
if (NTFile.createList(list[j]).length === 0) {
fs.rmdirSync(list[j]);
}
}
}
// 最後に目的のフォルダを削除
fs.rmdirSync(path);
}
/**
* 環境ファイルの定義値をJSONで取得する
* - XX = YY といったデータが記載された文章を読み込む
* @param {String} path
* @return {Object<string, string>}
*/
static getEnvironmentFile(path) {
const text = NTFile.loadTextFile(path).split(/\r?\n/g);
/**
* @type Object<string, string>
*/
const output = {};
for (let i = 0; i < text.length; i++) {
let line = text[i];
line = line.replace(/#.*/, "").trim();
if (line.length === 0) {
continue;
}
if (!/=/.test(line)) {
continue;
}
const name = line.replace(/=.*/, "").trim();
let data = line.replace(/[^=]+=/, "").trim();
if (/^".*"$/.test(data)) {
data = data.replace(/^"(.*)"$/, "$1");
}
output[name] = data;
}
return output;
}
}