ค้นหาเว็บไซต์

สตริงใน JavaScript มีไบต์เท่าไหร่?


ฉันมีสตริง JavaScript ที่มีขนาดประมาณ 500K เมื่อถูกส่งมาจากเซิร์ฟเวอร์ในรูปแบบ UTF-8 ฉันจะบอกขนาดของมันใน JavaScript ได้อย่างไร?

ฉันรู้ว่า JavaScript ใช้ UCS-2 ดังนั้นนั่นหมายถึง 2 ไบต์ต่ออักขระหรือไม่ อย่างไรก็ตาม มันขึ้นอยู่กับการใช้งาน JavaScript หรือไม่? หรือขึ้นอยู่กับการเข้ารหัสหน้าเว็บ หรือบางทีอาจขึ้นอยู่กับประเภทเนื้อหา?

คำตอบ #1

คุณสามารถใช้ 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)
);

คำตอบ #2

ฟังก์ชันนี้จะคืนขนาดไบต์ของสตริง UTF-8 ใด ๆ ที่คุณส่งให้มัน

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

แหล่งที่มา

เอนจิ้น JavaScript สามารถใช้ UCS-2 หรือ UTF-16 ภายในได้อย่างอิสระ เอนจิ้นส่วนใหญ่ที่ฉันรู้จักใช้ UTF-16 แต่ไม่ว่าจะเลือกแบบใด มันก็เป็นเพียงรายละเอียดของการใช้งานที่ไม่กระทบต่อลักษณะของภาษา

อย่างไรก็ตาม ภาษา ECMAScript/JavaScript เอง จะแสดงตัวอักษรตาม UCS-2 ไม่ใช่ UTF-16

แหล่งที่มา

คำตอบ #3

หากคุณกำลังใช้ node.js มีวิธีง่ายกว่าโดยการใช้บัฟเฟอร์:

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

มีไลบรารี npm สำหรับสิ่งนั้น: https://www.npmjs.org/package/utf8-binary-cutter (จากของคุณอย่างซื่อสัตย์)

คำตอบ #4

ค่าของ String ไม่ขึ้นกับการใช้งาน ตามข้อกำหนด ECMA-262 ฉบับที่ 3 แต่ละตัวอักษรแทน หน่วยข้อความ UTF-16 ขนาด 16 บิตเดียว:

4.3.16 ค่าตัวอักษร

ค่าสตริงเป็นสมาชิกของประเภท String และเป็นลำดับที่มีจำนวนจำกัดและมีการจัดเรียงของค่าจำนวนเต็มบวก 16 บิตที่มีจำนวนตั้งแต่ศูนย์ขึ้นไป

หมายเหตุ แม้ว่าค่าทุกค่ามักจะแทนหน่วยข้อความ UTF-16 ขนาด 16 บิตเพียงหน่วยเดียว แต่ภาษานี้ไม่กำหนดข้อจำกัดหรือข้อกำหนดใด ๆ เกี่ยวกับค่าดังกล่าว นอกจากว่าต้องเป็นจำนวนเต็มไม่ติดลบขนาด 16 บิต

คำตอบ #5

นี่คือ 3 วิธีที่ฉันใช้:

  1. TextEncoder
new TextEncoder().encode("myString").length
  1. Blob
new Blob(["myString"]).size
  1. Buffer
Buffer.byteLength("myString", 'utf8')

คำตอบ #6

ลองใช้การผสมนี้โดยใช้ฟังก์ชัน 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

คำตอบ #7

โปรดทราบว่าหากคุณกำลังมุ่งเป้าไปที่ node.js คุณสามารถใช้ Buffer.from(string).length:

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

คำตอบ #8

ขนาดของสตริงใน JavaScript คือ

  • ก่อน ES6: 2 ไบต์ต่ออักษร
  • ES6 และต่อมา: 2 ไบต์ต่ออักขระ หรือ 5 ไบต์ขึ้นไปต่ออักขระ

ก่อน ES6
เสมอ 2 ไบต์ต่ออักขระ UTF-16 ไม่อนุญาตเพราะสเปคบอกว่า "ค่าต้องเป็นจำนวนเต็มบวก 16 บิต" เนื่องจากสตริง UTF-16 อาจใช้ตัวอักขระ 3 หรือ 4 ไบต์ จึงจะละเมิดข้อกำหนด 2 ไบต์ อย่างสำคัญ แม้ว่า UTF-16 จะไม่สามารถสนับสนุนได้อย่างสมบูรณ์ มาตรฐานยังต้องการว่าตัวอักขระ 2 ไบต์ที่ใช้นั้นต้องเป็นตัวอักขระ UTF-16 ที่ถูกต้อง กล่าวอีกนัยหนึ่ง สตริง JavaScript ในยุคก่อน ES6 สนับสนุนชุดย่อยของตัวอักขระ UTF-16

ES6 และหลังจากนั้น
2 ไบต์ต่ออักขระ หรือ 5 ไบต์ขึ้นไปต่ออักขระ ขนาดเพิ่มเติมมีบทบาทเพราะ ES6 (ECMAScript 6) เพิ่มการสนับสนุนการละเว้นจุดโค้ดยูนิโค้ด การใช้ยูนิโค้ด escape ดูได้ดังนี้: \u{1D306}

บันทึกปฏิบัติ

  • เรื่องนี้ไม่เกี่ยวข้องกับการใช้งานภายในของเครื่องยนต์เฉพาะ ตัวอย่างเช่น เครื่องยนต์บางตัวใช้โครงสร้างข้อมูลและไลบรารีที่รองรับ UTF-16 อย่างเต็มที่ แต่สิ่งที่พวกเขาให้ภายนอกไม่จำเป็นต้องรองรับ UTF-16 อย่างเต็มที่ นอกจากนี้ เครื่องยนต์อาจรองรับ UTF-16 ภายนอกด้วย แต่ไม่ได้บังคับให้ทำ

  • สำหรับ ES6 กล่าวได้จริง ๆ แล้ว ตัวอักษรจะไม่มีวันยาวเกิน 5 ไบต์ (2 ไบต์สำหรับจุดหนี + 3 ไบต์สำหรับจุดรหัส Unicode) เพราะเวอร์ชันล่าสุดของ Unicode มีตัวอักษรที่เป็นไปได้เพียง 136,755 ตัว ซึ่งใส่เข้าไปใน 3 ไบต์ได้อย่างง่ายดาย อย่างไรก็ตาม เรื่องนี้ไม่ถูกจำกัดโดยมาตรฐานอย่างเคร่งครัด ดังนั้นตามหลักการแล้ว ตัวอักษรเดียวอาจใช้ 4 ไบต์สำหรับจุดรหัสและรวมทั้งหมด 6 ไบต์

  • ส่วนใหญ่ของตัวอย่างโค้ดที่นี่สำหรับการคำนวณขนาดไบต์ดูเหมือนไม่ได้นำการหนีรหัสจุดโค้ด Unicode ของ ES6 มาคิด ดังนั้นผลลัพธ์อาจไม่ถูกต้องในบางกรณี

บทความที่เกี่ยวข้อง