web-dev-qa-db-ja.com

JavaScript文字列のバイト数は?

UTF-8でサーバーから送信される場合、約500Kのjavascript文字列があります。 JavaScriptでそのサイズを確認するにはどうすればよいですか?

JavaScriptはUCS-2を使用することを知っているので、文字あたり2バイトを意味します。ただし、JavaScriptの実装に依存していますか?または、ページのエンコーディングまたはコンテンツタイプですか?

75
Paul Biggar

String値は実装依存ではありません。 ECMA-262 3rd Edition Specification に従って、各文字はUTF-16の単一16ビット単位を表しますテキスト

4.3.16文字列値

文字列値は、String型のメンバーであり、ゼロ以上の16ビット符号なし整数値の有限順序シーケンスです。

注通常、各値はUTF-16テキストの単一の16ビット単位を表しますが、16ビットの符号なし整数であることを除いて、言語は値に制限や要件を設けません。

28
CMS

この関数は、渡されたUTF-8文字列のバイトサイズを返します。

function byteCount(s) {
    return encodeURI(s).split(/%..|./).length - 1;
}

ソース

JavaScriptエンジンは、内部でUCS-2またはUTF-16を自由に使用できます。私が知っているほとんどのエンジンはUTF-16を使用しますが、どのような選択をしたとしても、それは実装の詳細に過ぎず、言語の特性に影響を与えません。

ただし、ECMAScript/JavaScript言語自体は、UTF-16ではなくUCS-2に従って文字を公開します。

ソース

63
Lauri Oherd

Node.jsを使用している場合、 buffers を使用したより簡単なソリューションがあります。

function getBinarySize(string) {
    return Buffer.byteLength(string, 'utf8');
}

そのためのnpm libがあります: https://www.npmjs.org/package/utf8-binary-cutter (忠実にあなたから)

41
Offirmo

unescape js関数を使用してこの組み合わせを試してください:

const byteAmount = unescape(encodeURIComponent(yourString)).length

完全エンコード処理の例:

const s  = "1 a ф № @ ®"; //length is 11
const s2 = encodeURIComponent(s); //length is 41
const s3 = unescape(s2); //length is 15 [1-1,a-1,ф-2,№-3,@-1,®-2]
const s4 = escape(s3); //length is 39
const s5 = decodeURIComponent(s4); //length is 11
19
Kinjeiro

Blob を使用して、文字列サイズをバイト単位で取得できます。

例:

console.info(
  new Blob(['????']).size,                             // 4
  new Blob(['????']).size,                             // 4
  new Blob(['????????']).size,                           // 8
  new Blob(['????????']).size,                           // 8
  new Blob(['I\'m a string']).size,                  // 12

  // from Premasagar correction of Lauri's answer for
  // strings containing lone characters in the surrogate pair range:
  // https://stackoverflow.com/a/39488643/6225838
  new Blob([String.fromCharCode(55555)]).size,       // 3
  new Blob([String.fromCharCode(55555, 57000)]).size // 4 (not 6)
);
19
P Roitto

Node.jsをターゲットにしている場合は、 Buffer.from(string).length を使用できることに注意してください。

var str = "\u2620"; // => "☠"
str.length; // => 1 (character)
Buffer.from(str).length // => 3 (bytes)
9
maerics

UTF-8は、コードポイントごとに1〜4バイトを使用して文字をエンコードします。 CMSが受け入れられた回答で指摘したように、JavaScriptは各文字を16ビット(2バイト)を使用して内部的に保存します。

ループを介して文字列の各文字を解析し、コードポイントごとに使用されるバイト数をカウントし、合計カウントに2を掛けると、そのUTF-8エンコード文字列のJavaScriptのメモリ使用量がバイト単位になります。おそらくこのようなもの:

      getStringMemorySize = function( _string ) {
        "use strict";

        var codePoint
            , accum = 0
        ;

        for( var stringIndex = 0, endOfString = _string.length; stringIndex < endOfString; stringIndex++ ) {
            codePoint = _string.charCodeAt( stringIndex );

            if( codePoint < 0x100 ) {
                accum += 1;
                continue;
            }

            if( codePoint < 0x10000 ) {
                accum += 2;
                continue;
            }

            if( codePoint < 0x1000000 ) {
                accum += 3;
            } else {
                accum += 4;
            }
        }

        return accum * 2;
    }

例:

getStringMemorySize( 'I'    );     //  2
getStringMemorySize( '❤'    );     //  4
getStringMemorySize( '????'   );     //  8
getStringMemorySize( 'I❤????' );     // 14
6
Mac

JavaScript文字列のサイズは

  • ES6以前:1文字につき2バイト
  • ES6以降:文字ごとに2バイト、または文字ごとに5バイト以上

ES6以前
文字ごとに常に2バイト。 UTF-16は、「値は16ビットの符号なし整数でなければならない」という仕様であるため許可されていません。 UTF-16文字列は3または4バイト文字を使用できるため、2バイトの要件に違反します。重要なことは、UTF-16を完全にサポートすることはできませんが、標準では使用される2バイト文字が有効なUTF-16文字であることを要求しています。つまり、ES6より前のJavaScript文字列はUTF-16文字のサブセットをサポートします。

ES6以降
1文字あたり2バイト、または1文字あたり5バイト以上。 ES6(ECMAScript 6)が nicodeコードポイントエスケープ のサポートを追加するため、追加のサイズが作用します。 Unicodeエスケープの使用は次のようになります。\ u {1D306}

実用メモ

  • これは、特定のエンジンの内部実装とは関係ありません。たとえば、一部のエンジンは完全なUTF-16サポートを備えたデータ構造とライブラリを使用しますが、外部で提供されるものは完全なUTF-16サポートである必要はありません。また、エンジンは外部UTF-16サポートも提供する場合がありますが、必須ではありません。

  • ES6の場合、最新バージョンのUnicodeには136,755文字しかなく、3バイトに簡単に収まるため、実際の文字は5バイト(エスケープポイントに2バイト+ Unicodeコードポイントに3バイト)を超えることはありません。ただし、これは技術的には規格によって制限されていないため、原則として単一の文字でコードポイントに4バイト、合計で6バイトを使用できます。

  • ここでのバイトサイズを計算するためのコード例のほとんどは、ES6 Unicodeコードポイントエスケープを考慮していないようです。そのため、場合によっては結果が不正確になる可能性があります。

3
whitneyland

Lauri Oherdからの回答は、野生で見られるほとんどの文字列でうまく機能しますが、文字列にサロゲートペアの範囲(0xD800から0xDFFF)の孤立文字が含まれていると失敗します。例えば。

byteCount(String.fromCharCode(55555))
// URIError: URI malformed

この長い関数は、すべての文字列を処理する必要があります。

function bytes (str) {
  var bytes=0, len=str.length, codePoint, next, i;

  for (i=0; i < len; i++) {
    codePoint = str.charCodeAt(i);

    // Lone surrogates cannot be passed to encodeURI
    if (codePoint >= 0xD800 && codePoint < 0xE000) {
      if (codePoint < 0xDC00 && i + 1 < len) {
        next = str.charCodeAt(i + 1);

        if (next >= 0xDC00 && next < 0xE000) {
          bytes += 4;
          i++;
          continue;
        }
      }
    }

    bytes += (codePoint < 0x80 ? 1 : (codePoint < 0x800 ? 2 : 3));
  }

  return bytes;
}

例えば。

bytes(String.fromCharCode(55555))
// 3

サロゲートペアを含む文字列のサイズを正しく計算します。

bytes(String.fromCharCode(55555, 57000))
// 4 (not 6)

結果はNodeの組み込み関数Buffer.byteLengthと比較できます:

Buffer.byteLength(String.fromCharCode(55555), 'utf8')
// 3

Buffer.byteLength(String.fromCharCode(55555, 57000), 'utf8')
// 4 (not 6)
2
Premasagar

私はV8エンジンの組み込みバージョンを使用しています。単一の文字列をテストしました。各ステップを1000文字押します。 UTF-8。

シングルバイト(8ビット、ANSI)文字 "A"(16進数:41)を使用した最初のテスト。 2バイト文字(16ビット) "Ω"(16進数:CE A9)での2番目のテストと3バイト文字(24ビット) "☺"(16進数:E2 98 BA)での3番目のテスト。

3つすべてのケースで、デバイスは888 000文字でメモリを印刷し、caを使用します。 RAMに26 348 kb。

結果:文字は動的に保存されません。そして、16ビットだけではありません。 -わかりました、おそらく私の場合のみ(埋め込み128 MB RAMデバイス、V8エンジンC++/QT)-文字エンコーディングは、javascriptエンジンのRAMのサイズとは関係ありません。例えばencodingURIなどは、高レベルのデータ送信と保存にのみ役立ちます。

埋め込まれているかどうかにかかわらず、文字は16ビットだけで保存されるわけではありません。残念ながら、Javascriptが低レベルの領域で何をするのか、100%の答えはありません。ところで文字 "A"の配列で同じ(上記の最初のテスト)をテストしました。ステップごとに1000個のアイテムをプッシュしました。 (まったく同じテスト。文字列を配列に置き換えただけです。)システムは、10 416 KBを使用して配列長1 337 000を超えると、メモリを使い果たします(不要)。したがって、javascriptエンジンは単純に制限されません。もっと複雑です。

1
Dominik

JavaScript文字列の単一の要素は、単一のUTF-16コード単位と見なされます。つまり、文字列の文字は16ビット(1コード単位)で格納され、16ビットは2バイト(8ビット= 1バイト)に相当します。

charCodeAt()メソッドを使用して、指定されたインデックスのUTF-16コード単位を表す0〜65535の整数を返すことができます。

codePointAt()を使用して、Unicode文字のコードポイント値全体を返すことができます。 UTF-32。

UTF-16文字を単一の16ビットコードユニットで表現できない場合、サロゲートペアがあるため、2つのコードユニットを使用します(2 x 16ビット= 4バイト)

さまざまなエンコーディングとそのコード範囲については、 nicode encodings を参照してください。

1
holmberd

これを試すことができます:

  var b = str.match(/[^\x00-\xff]/g);
  return (str.length + (!b ? 0: b.length)); 

それは私のために働いた。

0
user3728331