UTF-8でサーバーから送信される場合、約500Kのjavascript文字列があります。 JavaScriptでそのサイズを確認するにはどうすればよいですか?
JavaScriptはUCS-2を使用することを知っているので、文字あたり2バイトを意味します。ただし、JavaScriptの実装に依存していますか?または、ページのエンコーディングまたはコンテンツタイプですか?
String
値は実装依存ではありません。 ECMA-262 3rd Edition Specification に従って、各文字はUTF-16の単一16ビット単位を表しますテキスト:
4.3.16文字列値
文字列値は、String型のメンバーであり、ゼロ以上の16ビット符号なし整数値の有限順序シーケンスです。
注通常、各値はUTF-16テキストの単一の16ビット単位を表しますが、16ビットの符号なし整数であることを除いて、言語は値に制限や要件を設けません。
Node.jsを使用している場合、 buffers を使用したより簡単なソリューションがあります。
function getBinarySize(string) {
return Buffer.byteLength(string, 'utf8');
}
そのためのnpm libがあります: https://www.npmjs.org/package/utf8-binary-cutter (忠実にあなたから)
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
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)
);
Node.jsをターゲットにしている場合は、 Buffer.from(string).length
を使用できることに注意してください。
var str = "\u2620"; // => "☠"
str.length; // => 1 (character)
Buffer.from(str).length // => 3 (bytes)
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
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コードポイントエスケープを考慮していないようです。そのため、場合によっては結果が不正確になる可能性があります。
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)
私は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エンジンは単純に制限されません。もっと複雑です。
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 を参照してください。
これを試すことができます:
var b = str.match(/[^\x00-\xff]/g);
return (str.length + (!b ? 0: b.length));
それは私のために働いた。