ホームページ  >  記事  >  ウェブフロントエンド  >  Node.js を使用して圧縮および解凍関数を実装する

Node.js を使用して圧縮および解凍関数を実装する

亚连
亚连オリジナル
2018-06-06 09:27:073737ブラウズ

この記事では主に Node.js をベースにした圧縮と解凍の方法を紹介しますので、参考にしてください。

圧縮形式

zip と gzip は、私たちが目にする 2 つの最も一般的な圧縮形式です。もちろん、Windows では gzip が使用されることはほとんどありません。

tar は、デフォルトでは圧縮されないアーカイブ形式で、最終的な tar ファイルを gzip 形式の tar.gz ファイルに圧縮するには、gzip と組み合わせる必要があります。通常、これは tgz と省略されます。

なぜ rar について言及されていないのですか?これは特許で保護されたアルゴリズムであるため、解凍ツールは無料で入手できますが、圧縮ツールは有料です。したがって、一般的なアプリケーション シナリオでは、rar 圧縮ファイルが提供されることはほとんどありません。

この記事では、Node.jsでgzip、tar、tgz、zipを圧縮・解凍する方法をそれぞれ紹介します。

非圧縮ファイル ライブラリ

この記事で使用されている非圧縮ファイル ライブラリは urllib から取得したもので、最初にそれを複製し、指定されたディレクトリに移動する必要があります。

git clone https://github.com/node-modules/urllib.git nodejs-compressing-demo

gzip

Linux の世界では、各ツールの責任は非常に純粋で単一になります。 gzip として使用すると、ファイルが圧縮されるだけです。フォルダーがどのようにパッケージ化され、圧縮されるかについては、tar が担当するものではありません。

ファイルを圧縮する gzip コマンドライン

たとえば、nodejs-compressing-demo/lib/urllib.js ファイルを gzip 圧縮する場合は、urllib.js.gz ファイルとソース ファイルを取得します。削除されます。

$ ls -l nodejs-compressing-demo/lib/urllib.js
-rw-r--r-- 1 a a 31318 Feb 12 11:27 nodejs-compressing-demo/lib/urllib.js

$ gzip nodejs-compressing-demo/lib/urllib.js

$ ls -l nodejs-compressing-demo/lib/urllib.js.gz
-rw-r--r-- 1 a a 8909 Feb 12 11:27 nodejs-compressing-demo/lib/urllib.js.gz

# 还原压缩文件
$ gunzip nodejs-compressing-demo/lib/urllib.js.gz

ファイル サイズが 31318 バイトから 8909 バイトに減少し、3.5 倍以上の圧縮効果が得られました。

cat コマンドと組み合わせたパイプメソッドを使用して、ファイルを任意のファイルとして圧縮して保存することもできます:

$ ls -l nodejs-compressing-demo/README.md
-rw-r--r-- 1 a a 13747 Feb 12 11:27 nodejs-compressing-demo/README.md

$ cat nodejs-compressing-demo/README.md | gzip > README.md.gz

$ ls -l README.md.gz
-rw-r--r-- 1 a a 4903 Feb 12 11:50 README.md.gz

Node.js は gzip を実装します

もちろん、gzip アルゴリズムとツールを実際に実装するわけではありません。 Node.js の世界では、これらの基本ライブラリがすでに用意されているので、そのまま使用するだけです。

この記事では、圧縮モジュールを使用してすべての圧縮コードと解凍コードを実装します。

なぜ圧縮を選択するのですか?十分なコード品質と単体テストが保証されており、アクティブなメンテナンス状態にあり、非常に使いやすい API を備え、ストリーミング インターフェイスもサポートしているためです。

Promise インターフェイス

const compressing = require('compressing');

// 选择 gzip 格式,然后调用 compressFile 方法
compressing.gzip.compressFile('nodejs-compressing-demo/lib/urllib.js', 'nodejs-compressing-demo/lib/urllib.js.gz')
 .then(() => {
  console.log('success');
 })
 .catch(err => {
  console.error(err);
 });

// 解压缩是反响过程,接口都统一为 uncompress
compressing.gzip.uncompress('nodejs-compressing-demo/lib/urllib.js.gz', 'nodejs-compressing-demo/lib/urllib.js2')
 .then(() => {
  console.log('success');
 })
 .catch(err => {
  console.error(err);
 });

async/await プログラミング モデルと組み合わせると、コードは通常の非同期 IO 操作として記述できます。

const compressing = require('compressing');

async function main() {
 try {
  await compressing.gzip.compressFile('nodejs-compressing-demo/lib/urllib.js',
   'nodejs-compressing-demo/lib/urllib.js.gz');
  console.log('success');
 } catch (err) {
  console.error(err);
 }

 // 解压缩
 try {
  await compressing.gzip.uncompress('nodejs-compressing-demo/lib/urllib.js.gz',
   'nodejs-compressing-demo/lib/urllib.js2');
  console.log('success');
 } catch (err) {
  console.error(err);
 }
}

main();

ストリームインターフェース

ストリームモードでプログラミングする場合、各ストリームのエラーイベントを処理し、すべてのストリームを手動で破棄する必要があることに特別な注意が必要です。

fs.createReadStream('nodejs-compressing-demo/lib/urllib.js')
 .on('error', handleError)
 .pipe(new compressing.gzip.FileStream()) // It's a transform stream
 .on('error', handleError)
 .pipe(fs.createWriteStream('nodejs-compressing-demo/lib/urllib.js.gz2'))
 .on('error', handleError);

// 解压缩,就是 pipe 的方向倒转过来
fs.createReadStream('nodejs-compressing-demo/lib/urllib.js.gz2')
 .on('error', handleError)
 .pipe(new compressing.gzip.UncompressStream()) // It's a transform stream
 .on('error', handleError)
 .pipe(fs.createWriteStream('nodejs-compressing-demo/lib/urllib.js3'))
 .on('error', handleError);

公式のストリームでのバックプレッシャリングの推奨事項によると、ポンプ モジュールを使用してストリーム モード プログラミングと連携し、ポンプにこれらのストリームのクリーニング作業を完了させる必要があります。

const pump = require('pump');

const source = fs.createReadStream('nodejs-compressing-demo/lib/urllib.js');
const target = fs.createWriteStream('nodejs-compressing-demo/lib/urllib.js.gz2');

pump(source, new compressing.gzip.FileStream(), target, err => {
 if (err) {
  console.error(err);
 } else {
  console.log('success');
 }
});

// 解压缩
pump(fs.createReadStream('nodejs-compressing-demo/lib/urllib.js.gz2'),
  new compressing.gzip.FileStream(),
  fs.createWriteStream('nodejs-compressing-demo/lib/urllib.js3'),
  err => {
 if (err) {
  console.error(err);
 } else {
  console.log('success');
 }
});

Stream インターフェースの利点

Stream インターフェースは Promise インターフェースよりもはるかに複雑に見えますが、なぜこのようなアプリケーション シナリオがあるのでしょうか。

実際、HTTP サービスの分野では、HTTP リクエスト自体がリクエスト ストリームであるため、ストリーム モデルの方が大きな利点があります。アップロードされたファイルを gzip 圧縮して返したい場合、アップロードされたファイルを保存する必要はありません。代わりに、このファイル ストリームを直接使用して、Stream インターフェイスを使用してファイルをローカル ディスクに保存します。

egg ファイルのアップロード用のサンプル コードを使用して、gzip 圧縮を実装し、わずかな変更を加えて返すことができます。

const pump = require('pump');

class UploadFormController extends Controller {
 // ... other codes

 async upload() {
  const stream = await this.ctx.getFileStream();
  // 直接将压缩流赋值给 ctx.body,实现边压缩边返回的流式响应
  this.ctx.body = pump(stream, new compressing.gzip.FileStream());
 }
}

tar | gzip > tgz

gzip Chapter tar がフォルダーのパッケージ化を担当することを事前に知ることができます。

たとえば、nodejs-compressing-dem o フォルダー全体をファイルにパッケージ化して他の人に送信したい場合は、tar コマンドを使用できます。

$ tar -c -f nodejs-compressing-demo.tar nodejs-compressing-demo/

$ ls -l nodejs-compressing-demo.tar
-rw-r--r-- 1 a a 206336 Feb 12 14:01 nodejs-compressing-demo.tar

ご覧のとおり、tar でパッケージ化されたファイルは非圧縮であり、そのサイズが実際のフォルダーの合計サイズに近いため、通常はさらに大きくなります。そこで、梱包と同時に全員で圧縮していきます。

$ tar -c -z -f nodejs-compressing-demo.tgz nodejs-compressing-demo/

$ ls -l nodejs-compressing-demo.tgz
-rw-r--r-- 1 a a 39808 Feb 12 14:07 nodejs-compressing-demo.tgz

tar と tgz のサイズの差は 5 倍以上あり、ネットワーク伝送帯域幅が大幅に減少する可能性があります。

Node.js は tgz

Promise インターフェイスを実装します

まず、compressing.tar.compressDir(sourceDir, targetFile) を使用してフォルダーを tar ファイルにパッケージ化し、次に上記の gzip 圧縮方法を使用して、 tar ファイル ファイルは tgz ファイルに圧縮されます。

const compressing = require('compressing');

compressing.tar.compressDir('nodejs-compressing-demo', 'nodejs-compressing-demo.tar')
 .then(() => {
  return compressing.gzip.compressFile('nodejs-compressing-demo.tar',
   'nodejs-compressing-demo.tgz');
 });
 .then(() => {
  console.log('success');
 })
 .catch(err => {
  console.error(err);
 });

// 解压缩
compressing.gzip.uncompress('nodejs-compressing-demo.tgz', 'nodejs-compressing-demo.tar')
 .then(() => {
  return compressing.tar.uncompress('nodejs-compressing-demo.tar',
   'nodejs-compressing-demo2');
 });
 .then(() => {
  console.log('success');
 })
 .catch(err => {
  console.error(err);
 });

async/await プログラミング モデルと組み合わせると、コードが読みやすくなります:

const compressing = require('compressing');

async function main() {
 try {
  await compressing.tar.compressDir('nodejs-compressing-demo',
   'nodejs-compressing-demo.tar');
  await compressing.gzip.compressFile('nodejs-compressing-demo.tar',
   'nodejs-compressing-demo.tgz');
  console.log('success');
 } catch (err) {
  console.error(err);
 }
 
 // 解压缩
 try {
  await compressing.gzip.uncompress('nodejs-compressing-demo.tgz',
   'nodejs-compressing-demo.tar');
  await compressing.tar.uncompress('nodejs-compressing-demo.tar',
   'nodejs-compressing-demo2');
  console.log('success');
 } catch (err) {
  console.error(err);
 }
}

main();

Stream インターフェイス

compressing.tar.Stream クラスを通じて、任意のファイルとフォルダーを tar ストリームに動的に追加できます。オブジェクト、非常に柔軟です。

const tarStream = new compressing.tar.Stream();
// dir
tarStream.addEntry('dir/path/to/compress');
// file
tarStream.addEntry('file/path/to/compress');
// buffer
tarStream.addEntry(buffer);
// stream
tarStream.addEntry(stream);

const destStream = fs.createWriteStream('path/to/destination.tgz');
pump(tarStream, new compressing.gzip.FileStream(), destStream, err => {
 if (err) {
  console.error(err);
 } else {
  console.log('success');
 }
});

zip

zip は、実際には tar + gzip の「商用」の組み合わせと見なすことができ、ユーザーは圧縮ファイルと圧縮フォルダーを区別する必要がなくなります。

zip コマンド ライン ツールを使用してフォルダーを圧縮する例:

$ zip -r nodejs-compressing-demo.zip nodejs-compressing-demo/
 adding: nodejs-compressing-demo/ (stored 0%)
 adding: nodejs-compressing-demo/test/ (stored 0%)
 ...
 adding: nodejs-compressing-demo/.travis.yml (deflated 36%)

$ ls -l nodejs-compressing-demo.*
-rw-r--r-- 1 a a 206336 Feb 12 14:06 nodejs-compressing-demo.tar
-rw-r--r-- 1 a a  39808 Feb 12 14:07 nodejs-compressing-demo.tgz
-rw-r--r-- 1 a a  55484 Feb 12 14:34 nodejs-compressing-demo.zip

tgz と zip のファイル サイズを比較すると、デフォルトの圧縮パラメーターの下では gzip の方が zip よりも優れた効果があることがわかります。

Node.js は zip を実装します

実装コードは tar と似ていますが、デフォルトで圧縮されており、gzip プロセスを追加する必要がない点が異なります。

えー

概要

Node.js に基づく圧縮と解凍は思ったより簡単ですか?巨大な npm のおかげで、コマンド ライン ツールを使用して簡単にプログラミングを体験できます。

Promise インターフェイスでも Stream インターフェイスでも、最適なシナリオがあります。それを選択しますか?

現時点で、圧縮および解凍機能を使用すると、どのようなサービスや機能が実行できるでしょうか?

上記は私があなたのためにまとめたものです。

関連記事:

tween.jsを使用してイージングトゥイーンアニメーションアルゴリズムを実装する

Reactのrefの詳細な説明(詳細なチュートリアル)

JSを介してテキストの断続的なループスクロール効果を実現する方法

以上がNode.js を使用して圧縮および解凍関数を実装するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。