ホームページ  >  記事  >  ウェブフロントエンド  >  Node.js バッファーでのエンコードについて話しましょう

Node.js バッファーでのエンコードについて話しましょう

青灯夜游
青灯夜游転載
2021-08-31 10:28:233452ブラウズ

この記事では、Node.js バッファーのエンコーディングについて説明します。皆さんのお役に立てれば幸いです。

Node.js バッファーでのエンコードについて話しましょう

コンピュータの最小単位はビット、つまり0と1であり、ハードウェア上の高位と低位に対応します。ただし、1 ビットだけでは情報が少なすぎるため、8 ビットを 1 バイトとして指定し、以降はバイト単位で数値や文字列などのさまざまな情報を格納します。 [推奨学習:「nodejs チュートリアル 」]

文字を保存するにはどうすればよいですか?エンコーディングに依存しており、異なる文字は異なるエンコーディングに対応し、レンダリングが必要な場合には、対応するエンコーディングに従ってフォント ライブラリがチェックされ、対応する文字のグラフィックスがレンダリングされます。

文字セット

コンピュータが最初に発明されたのは米国であったため、文字セット (charset) はもともと ASCII コードであり、abc ABC 123 およびその他の 128 文字でした。州。その後、ヨーロッパでも ISO と呼ばれる一連の文字セット標準が開発され、その後中国でも GBK と呼ばれる一連の文字セット標準が開発されました。

国際標準化機構は、各自が同じコードを持つことはできないと考えました。そうしないと、同じコードが異なる文字セットで異なる意味を持つことになるため、世界のほとんどのコードを含める Unicode コーディングを提案しました。文字のみの一意のエンコーディング。

しかし、ASCII コードは保存に 1 バイトだけ必要ですが、GBK は 2 バイト必要で、一部の文字セットは 3 バイト必要です。などです。保存に 1 バイトしか必要ないものもありますが、2 バイト保存することはスペースの無駄です。 。そのため、utf-8、utf-16、utf-24 などのさまざまなエンコード スキームが存在します。

utf-8、utf-16、および utf-24 はすべて Unicode エンコーディングですが、具体的な実装計画は異なります。

UTF-8 スペースを節約するために、1 ~ 6 バイトの可変長記憶方式が設計されています。 UTF-16 は 2 バイト固定、UTF-24 は 4 バイト固定です。

Node.js バッファーでのエンコードについて話しましょう

最後に、UTF-8 は必要なスペースが最も少ないため、広く使用されています。

Node.js バッファ エンコーディング

各言語は文字セットのエンコーディングとデコーディングをサポートしており、Node.js も同様のことを行います。

Node.js では、バッファを使用してバイナリ データを保存できます。バイナリ データを文字列に変換する場合は、文字セットを指定する必要があります。バッファの from、byteLength、lastIndexOf およびその他のメソッドは、エンコーディングの指定をサポートしています。

具体的にサポートされているエンコーディングは次のとおりです:

utf8、ucs2、utf16le、latin1、ascii、base64、hex

一部の学生は次のことに気づくかもしれません:base64 と hex は文字セットではありませんああ、なぜですかあなたはここにいますか?

はい、文字セットに加えて、バイトから文字へのエンコード スキームには、プレーンテキスト文字に変換するための Base64 と 16 進数に変換するための hex も含まれています。

これが、Node.js が文字セットではなくエンコードと呼ぶ理由です。サポートされているエンコードおよびデコード スキームが単なる文字セットではないためです。

エンコーディングが指定されていない場合、デフォルトは utf8 です。

const buf = Buffer.alloc(11, 'aGVsbG8gd29ybGQ=', 'base64');

console.log(buf.toString());// hello world

エンコーディング ソース コード

エンコーディングについて Node.js ソース コードを調べました:

このセクションではエンコーディングを実装します: https://github .com/nodejs/node/blob/master/lib/buffer.js#L587-L726

各エンコーディングが、エンコーディング、encodingVal、byteLength、write、slice、indexOf を実装していることがわかります。 API は異なるエンコーディング スキームを使用すると、異なる結果が得られます。Node.js は、受信したエンコーディングに従って異なるオブジェクトを返します。これは多態性のアイデアです。

const encodingOps = {
  utf8: {
    encoding: 'utf8',
    encodingVal: encodingsMap.utf8,
    byteLength: byteLengthUtf8,
    write: (buf, string, offset, len) => buf.utf8Write(string, offset, len),
    slice: (buf, start, end) => buf.utf8Slice(start, end),
    indexOf: (buf, val, byteOffset, dir) =>
      indexOfString(buf, val, byteOffset, encodingsMap.utf8, dir)
  },
  ucs2: {
    encoding: 'ucs2',
    encodingVal: encodingsMap.utf16le,
    byteLength: (string) => string.length * 2,
    write: (buf, string, offset, len) => buf.ucs2Write(string, offset, len),
    slice: (buf, start, end) => buf.ucs2Slice(start, end),
    indexOf: (buf, val, byteOffset, dir) =>
      indexOfString(buf, val, byteOffset, encodingsMap.utf16le, dir)
  },
  utf16le: {
    encoding: 'utf16le',
    encodingVal: encodingsMap.utf16le,
    byteLength: (string) => string.length * 2,
    write: (buf, string, offset, len) => buf.ucs2Write(string, offset, len),
    slice: (buf, start, end) => buf.ucs2Slice(start, end),
    indexOf: (buf, val, byteOffset, dir) =>
      indexOfString(buf, val, byteOffset, encodingsMap.utf16le, dir)
  },
  latin1: {
    encoding: 'latin1',
    encodingVal: encodingsMap.latin1,
    byteLength: (string) => string.length,
    write: (buf, string, offset, len) => buf.latin1Write(string, offset, len),
    slice: (buf, start, end) => buf.latin1Slice(start, end),
    indexOf: (buf, val, byteOffset, dir) =>
      indexOfString(buf, val, byteOffset, encodingsMap.latin1, dir)
  },
  ascii: {
    encoding: 'ascii',
    encodingVal: encodingsMap.ascii,
    byteLength: (string) => string.length,
    write: (buf, string, offset, len) => buf.asciiWrite(string, offset, len),
    slice: (buf, start, end) => buf.asciiSlice(start, end),
    indexOf: (buf, val, byteOffset, dir) =>
      indexOfBuffer(buf,
                    fromStringFast(val, encodingOps.ascii),
                    byteOffset,
                    encodingsMap.ascii,
                    dir)
  },
  base64: {
    encoding: 'base64',
    encodingVal: encodingsMap.base64,
    byteLength: (string) => base64ByteLength(string, string.length),
    write: (buf, string, offset, len) => buf.base64Write(string, offset, len),
    slice: (buf, start, end) => buf.base64Slice(start, end),
    indexOf: (buf, val, byteOffset, dir) =>
      indexOfBuffer(buf,
                    fromStringFast(val, encodingOps.base64),
                    byteOffset,
                    encodingsMap.base64,
                    dir)
  },
  hex: {
    encoding: 'hex',
    encodingVal: encodingsMap.hex,
    byteLength: (string) => string.length >>> 1,
    write: (buf, string, offset, len) => buf.hexWrite(string, offset, len),
    slice: (buf, start, end) => buf.hexSlice(start, end),
    indexOf: (buf, val, byteOffset, dir) =>
      indexOfBuffer(buf,
                    fromStringFast(val, encodingOps.hex),
                    byteOffset,
                    encodingsMap.hex,
                    dir)
  }
};
function getEncodingOps(encoding) {
  encoding += '';
  switch (encoding.length) {
    case 4:
      if (encoding === 'utf8') return encodingOps.utf8;
      if (encoding === 'ucs2') return encodingOps.ucs2;
      encoding = StringPrototypeToLowerCase(encoding);
      if (encoding === 'utf8') return encodingOps.utf8;
      if (encoding === 'ucs2') return encodingOps.ucs2;
      break;
    case 5:
      if (encoding === 'utf-8') return encodingOps.utf8;
      if (encoding === 'ascii') return encodingOps.ascii;
      if (encoding === 'ucs-2') return encodingOps.ucs2;
      encoding = StringPrototypeToLowerCase(encoding);
      if (encoding === 'utf-8') return encodingOps.utf8;
      if (encoding === 'ascii') return encodingOps.ascii;
      if (encoding === 'ucs-2') return encodingOps.ucs2;
      break;
    case 7:
      if (encoding === 'utf16le' ||
          StringPrototypeToLowerCase(encoding) === 'utf16le')
        return encodingOps.utf16le;
      break;
    case 8:
      if (encoding === 'utf-16le' ||
          StringPrototypeToLowerCase(encoding) === 'utf-16le')
        return encodingOps.utf16le;
      break;
    case 6:
      if (encoding === 'latin1' || encoding === 'binary')
        return encodingOps.latin1;
      if (encoding === 'base64') return encodingOps.base64;
      encoding = StringPrototypeToLowerCase(encoding);
      if (encoding === 'latin1' || encoding === 'binary')
        return encodingOps.latin1;
      if (encoding === 'base64') return encodingOps.base64;
      break;
    case 3:
      if (encoding === 'hex' || StringPrototypeToLowerCase(encoding) === 'hex')
        return encodingOps.hex;
      break;
  }
}

まとめ

コンピュータにデータを保存する最小単位はビットですが、情報を保存する最小単位はバイトです。 ascii、iso、gbk などのさまざまな文字セットがあり、国際標準化機構はすべての文字を含めるための unicode を提案しました。いくつかの unicode 実装ソリューションがあります: utf-8、utf-16、utf-文字を格納するセクションの数。その中でもutf-8は可変長であり、記憶容量が最も小さいため広く使われています。

Node.js はバイナリ データを Buffer 経由で保存するため、文字列に変換する際にエンコード スキームを指定する必要があります。このエンコード スキームには文字セット (charset) だけでなく、16 進数スキームと Base64 スキームもサポートされています。

utf8、ucs2、utf16le、latin1、ascii、base64、hex

エンコーディングの Node.js ソース コードを調べたところ、各エンコーディング スキームが実装に使用されることがわかりました。一連の API これはポリモーフィックな思考です。

エンコーディングは Node.js を学習する際に頻繁に遭遇する概念ですが、Node.js のエンコーディングには文字セットだけが含まれるわけではありません。この記事がエンコーディングと文字セットの理解に役立つことを願っています。

プログラミング関連の知識について詳しくは、プログラミング入門をご覧ください。 !

以上がNode.js バッファーでのエンコードについて話しましょうの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はjuejin.cnで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。