unicode
首先搞清两个概念,字符集 与 编码
- 字符集:字符集是一张码表,它规定了文字与数字的一一对应关系。与计算机的内部表示没有必然的联系。比如ASCII字符集,它规定了0~127这128个数字与哪些字符的对应关系。常见的字符集包括:ASCII,GB2312,unicode等。
- 编码: 字符集是数字与字符对应起来的方案,编码则是在计算机与网络中存储、传输这些数字的方案。常见的编码方式有utf8、utf16、GBK等。
unicode(统一码、万国码、单一码、标准万国码)是世界范围内通用的字符集,是一种标准,它可以使电脑同时显示世界上数十种文字。unicode编码系统为表达任意语言的任意字符而设计,使用4字节的数字来表达每个字母、符号,或者表意文字。在unicode出现之前,世界各地都搞一套自己语音的字符集,混乱不堪,于是unicode组织就挺身而出,它们的目标是囊括世界上所有的字符,同时解决历史问题,将既有的字符编码方案以Unicode 编码方案来加以取代。
历史元老中,ASCII、GB2312是兼字符集与编码方案为一身的,而unicode则是单纯的字符集,它有多种编码方案的实现,如utf8、GBK等等。字符集和编码的概念被彻底分离且模块化的模型,其实是 Unicode 时代才得到广泛认同的。不同的编码方案在存储空间上各有长处,有的存英文省,有的存中文省。
JavaScript的字符串是unicode字符串,内部以utf-16编码保存。
ES6中的String.prototype.codePointAt()
方法可以得到指定字符的unicode码点。
JavaScript中不存在gbk字符串、utf8字符串这样的东西,但可以通过宿主环境或是第三方库提供的转码方法,来将js字符串转化为其他编码,并用某种数据结构(如浏览器中的ArrayBuffer,Node中的Buffer)来保存。
node支持的编码类型
目前有:
- ascii
- base64
- binary
- hex
- ucs2/ucs-2/utf16le/utf-16le
- utf8/utf-8
- latin1 (ISO8859-1, only in node 6.4.0+)
使用node的读写流时,若data是string,则可以指定encoding参数,以指定的编码类型来读写字符串;若data是buffer,则忽略encoding参数。例如文件读写:
fs.writeFile('./xx.txt', '哈哈哈', 'utf8') // use string and encoding
fs.writeFile('./xx.txt', new Buffer('哈哈哈', 'utf8')) // use string
fs.readFile('./xx.txt', 'utf8', (err, data) => {...}) // data is a string
fs.readFile('./xx.txt', (err, data) => {...}) // data is a raw buffer
node中转换字符编码
node是不支持gbk、gb2312等上述以外编码的,如果指定encoding为它们会报错Unknown encoding: xx
。但可以通过第三方模块iconv-lite来转换编码。基本操作如下:
// 读
const iconv = require('iconv-lite')
let data = fs.readFileSync('./xx.txt') // 假设txt是GB2312编码的,data是一个buffer,存储GB2312编码的字符串数据
let str = iconv.decode(data, 'GB2312') // 将buffer解码为string
// 拿到一个buffer欲将它转为string,必须先知道它的编码类型
// 写
const str = '国庆节万岁'
let b = iconv.encode(str, 'GB2312') // b是一个buffer,存储的是str的GB2312编码的二进制
fs.writeFile('./xx.txt', b) // 将str的GB2312编码数据写入到文件中
Base64/hex
Base64与hex都是将二进制数据编码成字符串的编码方式,针对的是二进制字节而非字符串。
因此,要获得某个string的base64编码时,应该先得到string的二进制,再对二进制进行base6编码:
// 编码
const str = '哈哈'
let b = Buffer.from(str) // b中存的是哈哈的utf8编码二进制
let base64Code = b.toString('base64') // '5ZOI5ZOI'
// 解码
const code = '5ZOI5ZOI'
let str = Buffer.from('5ZOI5ZOI', 'base64') // '哈哈'