javascript编码和二进制

573 阅读3分钟

本文是团队技术分享大纲。实际分享结合代码演示,细节较多

PPT

Base64

目的:使用文本(ASCII)表示二进制。相当于64进制,使用64个可打印字符[A-Za-z+/]编码,当最后一块不够24bits时=用作填充

atob, btoa

可直接看polyfill来理解算法

developer.mozilla.org/zh-CN/docs/…

Unicode问题

developer.mozilla.org/zh-CN/docs/…javascripts_utf-16>_base64

应用

Data Urls

data:text/plain;base64,SGVsbG8sIFdvcmxkIQ
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAADAklEQVRYhe2WQWgUZxiGn/ffuFlrLkoIMbOsWQxWikcvPRVFqKaKyQhejKcipfRUPPQUiAcpHrx5kSL1IK0HXQ2SKqXUSo/VHkREZFNjM7OVZSkeQtls43wesqmandmMzUYP7Xub/3/ne56BYf6B/3qUtpi/lh+yhu1GtgtsyKAX1Le4a1VBDVTGdFNZ/RgcCMqrFhj6bihbn/9rLDI7jvFeWtnm5PtOOp3rfudCebjceG0B74o3Zhadxuh7LXAroSq54+FoeCGVwLZrA71zf/MVZiOrAreQdLVnHcceHqjUEgUGpwb7G/XGTbDtHYW/wD3I5rK7Zj6aedIiUJws9s0vzN9aO/gLie6u7g8eHXxUBXBLy41n81+3g0t6CkQpCFGzmxDbvshajIOlF86GY8Go4ZTZF/qVjcJtkXS3jeRd4baEfmWjU2afUOzbb2bD3hVvDMBN2IQjslOJvuJS4Ac3AMJDYWDGeGLXGA8PhQFA4Ac3TFxK6mL25YRNOHdu8uwewwaSi69eZtp8OVr2LLbW5Fv+3OTZPS6KOJJcA8Fhr+TtByhOFQsRnEzqRnCyOFUsAHglb7/gcLvZUaQj8kqbfzFjZ7ti02QO6Gn3VEvGwBxGz4ojxe0ug8KKcCDNwGYPSNc1KLjUg9ck6nHAzFvDQ+AkpTo21yJmzDikW29LQNJ1h3FeqP7m6SzkyH3jQj/8E7j45vlcnPanqw4gp/VfAE9WuKeDdNXW5zZ8Ds3DaNqfrnZJR9P/Ia4GDk7uk/JwufaPAMDvfuUHTJ+R7sj993DTsWA0KL209GrylzePGPrWsFxn2arj9Gk4Gp5f5tSafCm/N7Jn1zvIv71O2aOP/ccPlm+4uHbkonsdwYr7zunjbZvefT8ODtAVe1+k3fbSsSdUQfxq2A6MwbZM6SHYT85xeXbkj+8BAiqJ/VgBwz5sDnsKOtFf6D9zZ+edBYCtpa19ddV3mKxXpk1ERJJqjqhqmcxvswdnk2lxwnGLA6WBn2Xc25BlfPl//P/pdJ4DItcX43LWrMQAAAAASUVORK5CYII=

url-loader可以配置将小资源转化为base64编码直接嵌入代码,减少请求数

encodeURIComponent, decodeURIComponent, encodeURI, decodeURI

将url中的特殊字符进行16进制编码。% + 码点

ASCII

American Standard Code for Information Interchange,美国信息交换标准代码

Unicode

provide a unique code for every character, in every language, in every program, on every platform 为每个字符提供一个唯一的码点,不论什么语言,什么项目,什么平台

unicode规定了码点的对应关系,但如何存储不限制

实现方式:

UTF-32

固定长度32位,和Unicode一一对应

UTF-16

2-4位变长

UTF-8

1-4位变长

Unicode符号范围     |        UTF-8编码方式
(十六进制)        |              (二进制)
----------------------+---------------------------------------------
0000 0000-0000 007F | 0xxxxxxx
0000 0080-0000 07FF | 110xxxxx 10xxxxxx
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

charCodeAt, codePointAt

charCodeAt: 返回 0 到 65535 之间的整数,表示给定索引处的 UTF-16 代码单元。如果index超出范围,返回 NaNcodePointAt: 返回 一个 Unicode 编码点值的非负整数

问题:遍历字符串

let s = '𠮷a';
for (let ch of s) {
  console.log(ch.codePointAt(0).toString(16));
}
// 20bb7
// 61
// 或Array.from
let arr = [...'𠮷a']; // arr.length === 2
arr.forEach(
  ch => console.log(ch.codePointAt(0).toString(16))
);
// 20bb7
// 61

二进制

Number.property.toString(radix)

radix: 2-36, 大于10进制的会使用a-z表示大于9的数

ArrayBufferTypedArray, DataView

ArrayBuffer 表示通用的、固定长度的原始二进制数据缓冲区

Blob File

表示一个不可变、原始数据的类文件对象

API

Blob.stream()

Blob.text()

Blob.arrayBuffer()

Buffer

Uint8Array的子类

API

Buffer.from()

Buffer.concat()

URL.createObjectURL(object)

object: 用于创建 URL 的 File 对象、Blob 对象或者 MediaSource 对象。

应用

web中接收ArrayBuffer

const xhr = new XMLHttpRequest();
xhr.open("GET", "/foo.png", true);
xhr.responseType = "arraybuffer";
xhr.onload = function (e) {
  const arrayBuffer = xhr.response;
  // do something
};

xhr.send(null);

小程序中接收ArrayBuffer

wx.request({
  url: 'www.foo.com',
  responseType: 'arraybuffer',
});

小程序中上传ArrayBuffer

const fs = wx.getFileSystemManager();

fs.readFile({
  filePath: 'foo.png',
  success(data) {
    wx.request({
      url: 'www.foo.com',
      data: data.slice(0, 1024 * 512),
    });
  },
});

实例

小程序大文件分段上传

/**
 * Upload a part in a multipart upload transaction
 * @param {String} name the object name
 * @param {String} uploadId the upload id
 * @param {Integer} partNo the part number
 * @param {File} file upload File, whole File
 * @param {Integer} start  part start bytes  e.g: 102400
 * @param {Integer} end  part end bytes  e.g: 204800
 * @param {Object} options
 */
export async function uploadPart(name, uploadId, partNo, file, start, end, options = {}) {
  if (!is.arrayBuffer(file)) {
    if (!options.mime) {
      options.mime = mime.getType(path.extname(file));
    }
    file = await new Promise((resolve, rejcet) => {
      fs.readFile({
        filePath: file,
        success: (res) => resolve(res.data),
        fail: rejcet,
      });
    });
  }

  const data = file.slice(start, end);

  return this._uploadPart(name, uploadId, partNo, data, options);
}

对唱歌词解密

const ENCRYPT_KEY = [63, 91, 97, 119, 94, 52, 39, 71, 86, 54, 49, 45, 02, 210, 110, 105];

export function decryptAndUnzip(xrc: ArrayBuffer): string {
  // decrypt
  const bytes = new Uint8Array(xrc);
  const bytesLength = bytes.length;
  const encryptKeyLength = ENCRYPT_KEY.length;
  for (let i = 0; i < bytesLength; i += 1) {
    // eslint-disable-next-line no-bitwise
    bytes[i] ^= ENCRYPT_KEY[i % encryptKeyLength];
  }

  // unzip
  return pako.inflate(bytes, { to: 'string' });
}

参考

en.wikipedia.org/wiki/Base64 developer.mozilla.org/zh-CN/docs/… es6.ruanyifeng.com/#docs/strin… www.ruanyifeng.com/blog/2007/1…