进制

基础知识

每一个二进制位(bit)有0和1两种状态,因此八个二进制位就可以组合出256(2的8次方)种状态,这被称为一个字节(byte)
image.png

  • 8位 = 1字节 (2进制是8位,16进制就是2位数)
  • 1024字节 = 1K
  • 1024K = 1M

js中的进制

  1. let a = 0b10100;//二进制
  2. let b = 0o24;//八进制
  3. let c = 20;//十进制
  4. let d = 0x14;//十六进制
  5. console.log(a == b);
  6. console.log(b == c);
  7. console.log(c == d);
  8. // 10进制转任意进制 10进制数.toString(目标进制)
  9. console.log(c.toString(2));
  10. // 任意进制转十进制 parseInt('任意进制字符串', 原始进制);
  11. console.log(parseInt('10100', 2));

编码

常见编码

ASCII

标准ASCII 码也叫基础ASCII码,使用7 位二进制数(剩下的1位二进制为0)来表示所有的大写和小写字母,数字0 到9、标点符号,以及在美式英语中使用的特殊控制字符。

举例

Bin
(二进制)
Dec
(十进制)
Hex
(十六进制)
缩写/字符
0011 0000 48 0x30 0
0100 0001 65 0x41 A
0110 0001 97 0x61 a

GB2312 汉字编码字符集
GBK 对GB2312编码的扩展

Unicode

规定必须用两个字节,也就是 16 位来统一表示所有的字符,对于 ASCII 里的那些 半角字符,Unicode 保持其原编码不变,只是将其长度由原来的 8 位扩展为16 位,而其他文化和语言的字符则全部重新统一编码。

UTF-8

Unicode 在很长一段时间内无法推广,直到互联网的出现,为解决 Unicode 如何在网络上传输的问题,于是面向传输的众多 UTF 标准出现了。

  • UTF-8 就是在互联网上使用最广的一种 Unicode 的实现方式
  • UTF-8 就是每次以8个位为单位传输数据
  • 而 UTF-16 就是每次 16 个位
  • UTF-8 最大的一个特点,就是它是一种变长的编码方式
  • Unicode 一个中文字符占 2 个字节,而 UTF-8 一个中文字符占 3 个字节
  • UTF-8 是 Unicode 的实现方式之一
  1. 对于单字节的符号,字节的第一位设为0,后面7位为这个符号的 Unicode 码。因此对于英语字母,UTF-8 编码和 ASCII 码 是相同的。
  2. 对于 n 字节的符号(n > 1),第一个字节的前n位都设为1,第n+ 1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的 Unicode 码。
    1. Unicode符号范围 | UTF-8编码方式
    2. (十六进制) | (二进制)
    3. ----------------------+---------------------------------------------
    4. 0000 0000-0000 007F | 0xxxxxxx
    5. 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
    6. 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
    7. 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

    https://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html

JavaScirpt中的编码

Unicode 字符与编码

  • String.prototype.charCodeAt()
  • String.fromCharCode() ```javascript ‘A’.charCodeAt(); // 65 String.fromCharCode(65); // “A”

‘🚀’.charCodeAt(); // 55357

// 🚀 是 4 字节字符(length 长度为 2 而不是 1),它的 Unicode 编码有 2 组

‘🚀’.charCodeAt(0); // 前两个字节的值:55357 ‘🚀’.charCodeAt(1); // 后两个字节的值:56960

String.fromCharCode(55357, 56960); // “🚀”

  1. ES6 中新增了 codePointAt fromCodePoint 两个 API 来解决这个问题
  2. ```javascript
  3. '🚀'.codePointAt(); // 128640
  4. String.fromCodePoint(128640); // "🚀"

文本编码

使用 NodeJS 编写前端工具时,操作得最多的是文本文件,因此也就涉及到了文件编码的处理问题。我们常用的文本编码有 UTF8 和 GBK 两种,并且 UTF8 文件还可能带 有BOM。在读取不同编码的文本文件时,需要将文件内容转换为 JS 使用的 UTF8 编码字符串后才能正常处理。


BOM的移除

BOM(ByteOrderMark)用于标记一个文本文件使用Unicode编码,其本身是一个Unicode字符("\uFEFF"),位于文本文件头部。在不同的 Unicode 编码下,BOM字符对应的二进制字节如下:

  1. Bytes Encoding
  2. ----------------------------
  3. FE FF UTF16BE
  4. FF FE UTF16LE
  5. EF BB BF UTF8

因此,我们可以根据文本文件头几个字节等于啥来判断文件是否包含 BOM,以及使用哪种 Unicode编码。但是,BOM 符虽然起到了标记文件编码的作用,其本身却不属于文件内容的一部分,如果读取文本文件时不去掉BOM,在某些使用场景下就会有问题。例如我们把几个 JS 文件合并成一个文件后,如果文件中间含有 BOM 字符,就会导致浏览器 JS 语法错误。因此,使用 NodeJS 读取文本文件时,一般需要去掉 BOM。

  1. function readText(pathname) {
  2. var bin = fs.readFileSync(pathname);
  3. if (bin[0] === 0xEF && bin[1] === 0xBB && bin[2] === 0xBF) {
  4. bin = bin.slice(3);
  5. }
  6. return bin.toString('utf-8');
  7. }

GBK转UTF8

NodeJS 支持在读取文本文件时,或者在 Buffer 转换为字符串时指定文本编码,但遗憾的是,GBK编码不在NodeJS 自身支持范围内。因此,一般我们借助 iconv-lite 这个三方包来转换编码。使用 NPM 下载该包后,我们可以按下边方式编写一个读取 GBK 文本文件的函数。

  1. var iconv = require('iconv-lite');
  2. function readGBKText(pathname) {
  3. var bin = fs.readFileSync(pathname);
  4. return iconv.decode(bin, 'gbk');
  5. }

[

](https://segmentfault.com/a/1190000040614613)