ノードjsストリームで*同じファイル*を読み書きするよりエレガントな方法はありますか?

ロイ

ファイルを読み取り、それを変更してthrough2、同じファイルに書き込みたい、次のようなコード。

const rm = require('rimraf')
const through2 = require('through2')
const fs = require('graceful-fs')
// source file path
const replacementPath = `./static/projects/${destPath}/index.html`
// temp file path
const tempfilePath = `./static/projects/${destPath}/tempfile.html`
// read source file then write into temp file
await promiseReplace(replacementPath, tempfilePath)    
// del the source file
rm.sync(replacementPath)
// rename the temp file name to source file name
fs.renameSync(tempfilePath, replacementPath)
// del the temp file
rm.sync(tempfilePath)

// promiseify readStream and writeStream
function promiseReplace (readfile, writefile) {
  return new Promise((res, rej) => {
    fs.createReadStream(readfile)
      .pipe(through2.obj(function (chunk, encoding, done) {
        const replaced = chunk.toString().replace(/id="wrap"/g, 'dududud')
        done(null, replaced)
      }))
      .pipe(fs.createWriteStream(writefile))
      .on('finish', () => {
        console.log('replace done')
        res()
      })
      .on('error', (err) => {
        console.log(err)
        rej(err)
      })
  })
}

上記のコードは機能しますが、もっとエレガントにできるか知りたいですか?

また、node-tempのような一時ライブラリも試します

残念ながら、同じファイルにreadStreamとwriteStreamを書き込むことはできず、これに関する問題が発生します。

ですから、これを行うためのより良い方法を知っている人は誰でも教えてください、どうもありがとうございました。

セスホラデイ

不要な依存関係を取り除き、ストリーム用の新しい簡略化されたコンストラクターを使用することで、コードをよりエレガントにすることができます。

const fs = require('fs');
const util = require('util');
const stream = require('stream');
const tempWrite = require('temp-write');

const rename = util.promisify(fs.rename);

const goat2llama = async (filePath) => {
    const str = fs.createReadStream(filePath, 'utf8')
        .pipe(new stream.Transform({
            decodeStrings : false,
            transform(chunk, encoding, done) {
                done(null, chunk.replace(/goat/g, 'llama'));
            }
        }));
    const tempPath = await tempWrite(str);
    await rename(tempPath, filePath);
};

テスト

AVAは、それが機能することを証明するためにテストします。

import fs from 'fs';
import path from 'path';
import util from 'util';
import test from 'ava';
import mkdirtemp from 'mkdirtemp';
import goat2llama from '.';

const writeFile = util.promisify(fs.writeFile);
const readFile = util.promisify(fs.readFile);

const fixture = async (content) => {
    const dir = await mkdirtemp();
    const fixturePath = path.join(dir, 'fixture.txt');
    await writeFile(fixturePath, content);
    return fixturePath;
};

test('goat2llama()', async (t) => {
    const filePath = await fixture('I like goats and frogs, but goats the best');
    await goat2llama(filePath);
    t.is(await readFile(filePath, 'utf8'), 'I like llamas and frogs, but llamas the best');
});

変更に関するいくつかのこと:

  • Through2はもう実際には必要ありません。パススルーを設定したり、ストリームを適切に変換したりするのは以前は面倒でしたが、簡略化された構築APIのおかげで、今ではそうではありません
  • おそらく、graceful-fsも必要ありません。多くの同時ディスクI / Oを実行している場合を除いて、EMFILE通常は問題になりません。特に最近では、ノードがファイル記述子についてよりスマートになっているためです。しかし、それがあなたにとって問題であるならば、そのライブラリはWindows上のウイルス対策ソフトウェアによって引き起こされる一時的なエラーを助けます。
  • あなたは間違いなくこれのためにrimrafを必要としません。必要なのはfs.rename()これはmvコマンドラインと似ていますが、いくつかの微妙な違いがありますが、ここでは違いはそれほど重要ではありません。重要なのは、そこにあったファイルの名前を変更した後、一時パスには何も存在しないということです。
  • temp-writeを使用したのは、安全なランダムファイルパスを生成してOSの一時ディレクトリに配置するためです(これは時々自動的にクリーンアップされます)。さらに、ストリームの変換を処理し、Promiseいくつかのエッジケースを処理します。エラーの周り。開示:私はストリームの実装をで書きましたtemp-write:)

全体として、これはまともな改善です。ただし、コメントで説明されている境界の問題が残っています。幸いなことに、この問題に遭遇したのはあなたが最初ではありません。実際のソリューションを特にエレガントとは言いませんが、自分で実装した場合は確かです。しかし、replacestreamはあなたを助けるためにここにあります。

const fs = require('fs');
const util = require('util');
const tempWrite = require('temp-write');
const replaceStream = require('replacestream');

const rename = util.promisify(fs.rename);

const goat2llama = async (filePath) => {
    const str = fs.createReadStream(filePath, 'utf8')
        .pipe(replaceStream('goat', 'llama'));
    const tempPath = await tempWrite(str);
    await rename(tempPath, filePath);
};

また...

一時ファイルは好きではありません

確かに、一時ファイルはしばしば悪いです。ただし、この場合、一時ファイルは適切に設計されたライブラリによって管理され、安全で邪魔にならない場所に保存されます。他のプロセスと競合する可能性はほとんどありません。また、rename()何らかの理由で失敗し場合でも、ファイルはOSによってクリーンアップされます。

それはあなたが使用して完全に一時ファイルを避けることができると述べたfs.readFile()fs.writeFile()の代わりにストリーミング。前者は、チャンクの境界について心配する必要がないため、テキストの置換もはるかに簡単になります。どちらかのアプローチを選択する必要がありますが、非常に大きなファイルの場合、ファイルを手動でチャンク化する以外に、ストリーミングが唯一のオプションである可能性があります

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

Node.jsは、ストリームの読み取りと書き込みを同じファイルに同時に行います

分類Dev

Python(おそらくパンダ)でファイルから配列を読み取るときに、最初の行(メタデータを含む)を処理してスキップするエレガントな方法はありますか?

分類Dev

iOS:関連するアプリだけが読み取り/書き込みできるようにファイルをエクスポートする方法はありますか?

分類Dev

Pythonでのテキストファイルへのリストの書き込みと読み取り:より効率的な方法はありますか?

分類Dev

S3バケットから画像(ファイル)をレンダリングする方法は、フロントエンドですべてのパブリックアクセスをブロックしました(プライベート書き込み、プライベート読み取り)

分類Dev

Node.jsはファイルストリームを変換し、同じファイルに書き込むと空のファイルになります

分類Dev

この「if」リストをよりエレガントな方法で書く方法はありますか?

分類Dev

ストリームからCSVファイルを読み取り、書き込まれたとおりに各行を処理する方法は?

分類Dev

Pythonでは、明示的なループなしでカスタム形式でリストを印刷するエレガントな方法はありますか?

分類Dev

RailsでWordpressのエクスポートファイルを読み取る方法はありますか?

分類Dev

Swiftでこの遅延読み込みパターンを作成するためのよりエレガントな方法はありますか?

分類Dev

Pythonで辞書ループ例外を処理するためのより良いまたはよりエレガントな方法はありますか?

分類Dev

c#-バッファリングされたストリームを使用することは、ソースストリームでreadメソッドを使用して同じバイト数を読み取ることとどのように異なりますか?

分類Dev

graphvizのfdpレイアウトを使用して、同じクラスター内のノード間と異なるクラスター内のノード間で異なるエッジスプラインを使用する方法はありますか?

分類Dev

エラーを無視する方法lsコマンドでそのようなファイルディレクトリはありませんか?

分類Dev

コードを読みやすくするためにJavaブール値の名前を変更するエレガントな方法はありますか?

分類Dev

スペースで区切られたテキスト値を整数として読み取り、配列にフロートするよりエレガントな方法はありますか?

分類Dev

ノードは、sshを使用してリモートコンピューターからファイルを読み取りストリームします

分類Dev

ディスクからのファイルの読み取りエラー:エラー:ENOENT:そのようなファイルまたはディレクトリはありません。 '。/ database.jsonを開きます

分類Dev

ノード:データを読み取り、変換し、ストリームとパイプを使用してファイルに書き込みます

分類Dev

Excelテンプレートからデータを読み取り、同じファイルに書き込みます

分類Dev

Chaquopy:Pythonコードからテキストファイルを読み取るときにエラーが発生しました「そのようなファイルまたはディレクトリはありません」

分類Dev

配列サイズがわからないRubyでwhileループを書くよりエレガントな方法はありますか?

分類Dev

C#.NET-単一のZIPファイル内のXMLファイルのコレクションに対して同じXMLノードをクエリする簡単な方法はありますか?

分類Dev

フォームのデフォルト値をチェックするためのよりエレガントな方法はありますか?

分類Dev

SInatraで永続的なフォームデータを取得する簡単な方法はありますか?または、フォーム変数をファイルに書き込んで手動で読み取る必要がありますか?

分類Dev

ノードjsで複数のテキストファイルを読み書きする方法

分類Dev

Javaでリストを処理するよりエレガントな方法はありますか?(Python VS Java)

分類Dev

ES6-すべての名前付きエクスポートをインポートするエレガントな方法はありますが、デフォルトのエクスポートはありませんか?

Related 関連記事

  1. 1

    Node.jsは、ストリームの読み取りと書き込みを同じファイルに同時に行います

  2. 2

    Python(おそらくパンダ)でファイルから配列を読み取るときに、最初の行(メタデータを含む)を処理してスキップするエレガントな方法はありますか?

  3. 3

    iOS:関連するアプリだけが読み取り/書き込みできるようにファイルをエクスポートする方法はありますか?

  4. 4

    Pythonでのテキストファイルへのリストの書き込みと読み取り:より効率的な方法はありますか?

  5. 5

    S3バケットから画像(ファイル)をレンダリングする方法は、フロントエンドですべてのパブリックアクセスをブロックしました(プライベート書き込み、プライベート読み取り)

  6. 6

    Node.jsはファイルストリームを変換し、同じファイルに書き込むと空のファイルになります

  7. 7

    この「if」リストをよりエレガントな方法で書く方法はありますか?

  8. 8

    ストリームからCSVファイルを読み取り、書き込まれたとおりに各行を処理する方法は?

  9. 9

    Pythonでは、明示的なループなしでカスタム形式でリストを印刷するエレガントな方法はありますか?

  10. 10

    RailsでWordpressのエクスポートファイルを読み取る方法はありますか?

  11. 11

    Swiftでこの遅延読み込みパターンを作成するためのよりエレガントな方法はありますか?

  12. 12

    Pythonで辞書ループ例外を処理するためのより良いまたはよりエレガントな方法はありますか?

  13. 13

    c#-バッファリングされたストリームを使用することは、ソースストリームでreadメソッドを使用して同じバイト数を読み取ることとどのように異なりますか?

  14. 14

    graphvizのfdpレイアウトを使用して、同じクラスター内のノード間と異なるクラスター内のノード間で異なるエッジスプラインを使用する方法はありますか?

  15. 15

    エラーを無視する方法lsコマンドでそのようなファイルディレクトリはありませんか?

  16. 16

    コードを読みやすくするためにJavaブール値の名前を変更するエレガントな方法はありますか?

  17. 17

    スペースで区切られたテキスト値を整数として読み取り、配列にフロートするよりエレガントな方法はありますか?

  18. 18

    ノードは、sshを使用してリモートコンピューターからファイルを読み取りストリームします

  19. 19

    ディスクからのファイルの読み取りエラー:エラー:ENOENT:そのようなファイルまたはディレクトリはありません。 '。/ database.jsonを開きます

  20. 20

    ノード:データを読み取り、変換し、ストリームとパイプを使用してファイルに書き込みます

  21. 21

    Excelテンプレートからデータを読み取り、同じファイルに書き込みます

  22. 22

    Chaquopy:Pythonコードからテキストファイルを読み取るときにエラーが発生しました「そのようなファイルまたはディレクトリはありません」

  23. 23

    配列サイズがわからないRubyでwhileループを書くよりエレガントな方法はありますか?

  24. 24

    C#.NET-単一のZIPファイル内のXMLファイルのコレクションに対して同じXMLノードをクエリする簡単な方法はありますか?

  25. 25

    フォームのデフォルト値をチェックするためのよりエレガントな方法はありますか?

  26. 26

    SInatraで永続的なフォームデータを取得する簡単な方法はありますか?または、フォーム変数をファイルに書き込んで手動で読み取る必要がありますか?

  27. 27

    ノードjsで複数のテキストファイルを読み書きする方法

  28. 28

    Javaでリストを処理するよりエレガントな方法はありますか?(Python VS Java)

  29. 29

    ES6-すべての名前付きエクスポートをインポートするエレガントな方法はありますが、デフォルトのエクスポートはありませんか?

ホットタグ

アーカイブ