功能:

  1. 按索引替换指定字符串
  2. 插入到任意位置
  3. 可重复读取文本
  4. 深层读取文件夹中的文件
    1. 可以指定后缀

代码:

import { open, readdir } from "fs/promises";
import path from "path";
import { OpenPram } from "./type";
  
export class FileEnhance {
    constructor() { }
    static async insert(openPram: OpenPram, txt: string, index: number, encoding: BufferEncoding = 'utf-8') {
        await this.replaceRange(openPram, txt, index, undefined, encoding);
    }
    /**
     * @param start 包括在内
     * @param end 包括在内 */
    static async replaceRange(openPram: OpenPram, txt: string, start: number = 0, end = start, fileEncoding: BufferEncoding = 'utf-8') {
        if (end && start > end) throw new Error("End > Start");
        const file = await open(openPram.path, openPram.flags || 'w+', openPram.mode);
        if (!start && !end) {
            await file.writeFile(txt, { 'encoding': fileEncoding });
        }
        else {
            let beforeTxt = (await file.readFile(fileEncoding))
            let afterTxt = beforeTxt.slice(end + 1);
            beforeTxt = beforeTxt.slice(0, start);
            //console.log(afterTxt);
            await file.write(beforeTxt + txt + afterTxt, 0, fileEncoding);
        }
        await file.close();
    }
    static getRange(openPram: OpenPram, start: number = 0, end?: number, encoding: BufferEncoding = 'utf-8'): Promise<string> {
        if (end && start > end) throw new Error("End > Start");
        return new Promise<string>(async (resolve, reject) => {
            let file: FileHandle;
            try {
                file = await open(openPram.path, openPram.flags, openPram.mode);
            } catch (error) {
                reject(error)
                return;
            }
            /* utf-8编码一个字符最多等于4个字节 */
            let redStream = file.createReadStream({ encoding: encoding, start: 0, end: end ? end * 4 : undefined });
            let str: string = '';
            redStream.on('data', chunk => {
                str += chunk;
            })
            redStream.on('end', async () => {
                redStream.destroy();
                //console.log('destroy!')
                await file.close();
                resolve(str.slice(start, end ? end + 1 : undefined))
            })
        })
    }
    /** @param extend 要带有'.'*/
    static async getFileInDir(dirPath: string, extend?: string, isDeep: boolean = true): Promise<string[]> {
        let filePath: string[] = [];
        for (const item of await readdir(dirPath, { withFileTypes: true })) {
            if (item.isFile()) {
                if (extend && path.extname(item.name).toLowerCase() !== extend.toLowerCase()) continue;
                filePath.push(path.join(dirPath, item.name));
            }
            else if (isDeep) {
                filePath.push(...await this.getFileInDir(path.join(dirPath, item.name), extend));
            }
        }
        return filePath;
    }
}
/* type.d.ts */
import { PathLike, Mode } from "fs";
  
declare interface OpenPram {
    path: PathLike, flags?: string | number, mode?: Mode
}