js实现不同编码格式内容转码
- 支持buffer转化为各类编码格式的字符串
- 支持utf8字符串编码为其他多种类型的buffer
- 支持buffer内容传输与解析
客服端
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Test</title>
</head>
<body>
<button id="button">请求数据</button>
<p>请求内容:</p>
<div id="content"></div>
</body>
<script src=""></script>
<script>
const btn = document.getElementById('button')
btn.addEventListener('click', queryBuffer)
function queryBuffer() {
const reqContent = {name: 'buffer', type: 'gbk', data: []}
const bufferContent = new TextEncoder().encode('正如我');
reqContent.data = bufferContent
// 发送post请求接口数据
var httpRequest = new XMLHttpRequest(); // 第一步:创建需要的对象
httpRequest.open('POST', '/test', true); // 第二步:打开连接
httpRequest.setRequestHeader("Content-type", "application/json"); //设置请求头 注:post方式必须设置请求头(在建立连接后设置请求头)
httpRequest.send();//发送请求 将请求头写在send中
// 获取数据后的处理程序
httpRequest.onreadystatechange = function () { // 请求后的回调接口,可将请求成功后要执行的程序写在其中
if (httpRequest.readyState == 4 && httpRequest.status == 200) { // 验证请求是否发送成功
const response = JSON.parse(httpRequest.response)
const bufferData = response.data
const arr = new Uint8Array(bufferData)
const string = new TextDecoder('gb2312').decode(arr);
document.getElementById('content').innerHTML = string
}
};
}
</script>
</html>
服务端
var express = require('express')
var app = express()
app.use(express.static('src'))
const fs = require("fs")
const path = require("path")
const iconv = require('iconv-lite');
app.use(express.json());
app.get('/', (req, res) => {})
app.post('/test', async function (req, res) {
const reqData = typeof req.body.data
console.log(reqData)
const response = await getGbkData()
const data = JSON.stringify(response) // 转为json字符串
res.send(data)
})
app.listen(8888, () => {
console.log("Successfully connected")
})
const getGbkData = () => {
return new Promise((resolve, reject) => {
fs.readFile(path.join(__dirname, "./gb2312.txt"), function (err, data) {
if (err) {
console.log('err')
}
const utf8String = iconv.decode(data, 'gbk')
const gbkBuffer = iconv.encode(utf8String, 'gbk');
resolve(data)
})
})
}
js实现转码的一些方式
1. Encoding API
Encoding API 提供了一种机制来处理各种字符编码文本,包括传统的非 UTF-8 编码。
API 提供了四个接口:TextDecoder
、TextEncoder
、TextDecoderStream
和 TextEncoderStream
。
TextDecoder
TextDecoder
接口表示一个文本解码器,一个解码器只支持一种特定文本编码,例如 UTF-8
、ISO-8859-2
、KOI8-R
、GBK
,等等。解码器将字节流作为输入,并提供码位流作为输出。
构造方法:
TextDecoder()
构造函数使用参数中指定的编码返回一个新创建的 TextDecoder
对象。
-
语法
new TextDecoder() new TextDecoder(utfLabel) new TextDecoder(utfLabel, options)
参数:
utfLabel
(可选): 一个字符串,默认是"utf-8"
。可以是任意有效的编码。options
(可选):一个具有属性的对象:- fatal:一个布尔值,表示在解码无效数据时,
TextDecoder.decode()
方法是否必须抛出TypeError
。默认是false
,这意味着解码器将用替换字符替换错误的数据。
// 示例 const textDecoder1 = new TextDecoder("iso-8859-2"); const textDecoder2 = new TextDecoder(); const textDecoder3 = new TextDecoder("csiso2022kr", { fatal: true }); // Allows TypeError
- fatal:一个布尔值,表示在解码无效数据时,
-
实例属性
encoding
:只读属性TextDecoder.encoding
返回一个字符串,其中包含了指定的解码器的解码算法的名称。编码由构造函数的label
参数设置,并且默认是utf-8
。fatal
:只读属性fatal
是一个布尔值,表示错误模式是否是致命的。ignoreBOM
:只读属性ignoreBOM
是一个布尔值,表示是否忽略字节顺序标记 -
实例方法
decode()
:返回一个字符串,其包含作为参数传递的缓冲区解码后的文本。解码方法在当前的TextDecoder
对象中定义。这包含了数据的预期编码,以及如何处理解码时发生的错误。语法:
decode(buffer, options)
参数:
buffer
可选:一个ArrayBuffer
、TypedArray
或包含要解码的编码文本的DataView
对象。options
可选:具有以下属性的对象:- stream:一个布尔标志,表示在后续调用
decode()
将跟随附加数据。
返回值: 一个字符串。
示例:
const array = new Uint8Array([226, 130, 172]) const decoder = new TextDecoder(); const str = decoder.decode(array); // String "€"
- stream:一个布尔标志,表示在后续调用
TextEncoder
TextEncoder
接受码位流作为输入,并提供 UTF-8 字节流作为输出。
构造函数
TextEncoder()
返回一个新构造的 TextEncoder
,它默认使用 UTF-8 编码将码位流转换成字节流。
-
语法
new TextEncoder()
-
实例属性
encoding
:只读属性返回一个字符串,其中包含特定编码器使用的编码算法的名称。值只能为:utf-8
。 -
实例方法
encode()
:接受一个字符串作为输入,返回一个对参数中给定的文本的编码后的Uint8Array
,编码的方法通过TextEncoder
对象指定。语法:
encode(string)
参数:
string
可选:一个包含了将要编码的文本。返回值: 一个
Uint8Array
(en-US) 对象。示例:
const string = 'hello' const textEncoder = new TextEncoder(); let encoded = textEncoder.encode(string);
2. icon-lite
iconv-lite是一个用于字符编码转换的JavaScript库。它的主要功能是将一种字符编码转换为另一种字符编码
iconv-lite支持多种字符编码,包括UTF-8、ISO-8859-1、GBK、GB2312、Big5等。它还支持流式转换和批量转换,可以快速处理大量数据。
iconv-lite安装:
npm install iconv-lite
安装完成后,在JavaScript代码中引入iconv-lite库:
const iconv = require('iconv-lite');
Basic API
iconv.encode(str, encoding, options)
:将字符串编码为指定编码格式。其中,str为要编码的字符串,encoding为目标编码格式,options为可选参数,用于指定是否添加BOM、是否忽略无效字符等。iconv.decode(buffer, encoding, options)
:将Buffer对象解码为字符串。其中,buffer为要解码的Buffer对象,encoding为源编码格式,options为可选参数,用于指定是否忽略无效字符等。
// 将Buffer转换为js字符串
str = iconv.decode(Buffer.from([0x68, 0x65, 0x6c, 0x6c, 0x6f]), 'win1251');
// 从js字符串转换为Buffer
buf = iconv.encode("Sample input string", 'gbk');
// 检查指定编码格式是否被支持
iconv.encodingExists("us-ascii")
Streaming API
iconv.encodeStream(encoding, options)
:创建一个可写流,用于将数据流转换为指定编码格式。其中,encoding为目标编码格式,options为可选参数,用于指定是否添加BOM、是否忽略无效字符等。iconv.decodeStream(encoding, options)
:创建一个可读流,用于将数据流解码为字符串。其中,encoding为源编码格式,options为可选参数,用于指定是否忽略无效字符等。
// 解码流(从二进制数据流到js字符串)
http.createServer(function(req, res) {
var converterStream = iconv.decodeStream('win1251');
req.pipe(converterStream);
converterStream.on('data', function(str) {
console.log(str); // TODO: 对解码后的字符串逐个执行操作。
});
});
// 转换编码流示例
fs.createReadStream('file-in-win1251.txt')
.pipe(iconv.decodeStream('win1251'))
.pipe(iconv.encodeStream('ucs2'))
.pipe(fs.createWriteStream('file-in-ucs2.txt'));
// Sugar:所有编码/解码流都有.collect(cb)方法来累积数据。
http.createServer(function(req, res) {
req.pipe(iconv.decodeStream('win1251')).collect(function(err, body) {
assert(typeof body == 'string');
console.log(body); // full request body string
});
});
支持的编码类型
所有node.js本机编码:utf8、ucs2/utf16le、ascii、binary、base64、hex。
其他unicode编码:utf16、utf16-be、utf-7、utf-7-imap、utf32、utf32-le和utf32-be。
所有广泛使用的单字节编码:Windows 125x系列、ISO-8859系列、IBM/DOS代码页、Macintosh系列、KOI8系列,以及iconv库支持的所有其他代码。别名,如“latin1”、“us-ascii”也受支持。
所有广泛使用的多字节编码:CP932、CP936、CP949、CP950、GB2312、GBK、GB18030、Big5、Shift_JIS、EUC-JP。
3. 扩展内容
3.1.Buffer对象与ArrayBuffer和Uint8Array等对象对比
相同点:
- 它们都可以用于存储二进制数据,并且可以通过索引访问数据。
不同点:
- 定义:Buffer对象是Node.js中特有的用于处理二进制数据的类。它是一个全局变量,可以通过require('buffer')获取。ArrayBuffer和Uint8Array等对象是HTML5标准中定义的。
- 设计目标:Buffer对象的设计目标是为了处理网络通信、文件I/O等场景下的二进制数据。ArrayBuffer和Uint8Array等对象则是为了处理在Web环境下的二进制数据。
- 底层实现方式:Buffer对象是在C++层面实现的,而ArrayBuffer和Uint8Array等对象则是在JavaScript层面实现的。在处理大量二进制数据时,Buffer对象的性能可能更好一些。
- API:Buffer对象提供了toString()方法用于将二进制数据转换为字符串,ArrayBuffer和Uint8Array等对象没有类似方法。Buffer对象还提供了一些其他的API,例如copy()、slice()、fill()等方法,用于复制、分割、填充等操作。
互转:
在处理二进制数据时,它们也可以相互转换。可以使用Buffer.from()方法将ArrayBuffer对象转换为Buffer对 象,也可以使用Buffer的buffer属性将Buffer对象转换为ArrayBuffer对象。
Buffer.from方法
Node.js中用于创建Buffer对象的方法之一。它可以将字符串、数组或其他数据类型转换为Buffer对象。
Buffer.from()方法的语法如下:
Buffer.from(string[, encoding]) // encoding为可选参数,指定string的编码格式,默认为'utf8';
Buffer.from(array)
Buffer.from(buffer)
Buffer.from(arrayBuffer[, byteOffset[, length]]) // byteOffset为可选参数,指定从arrayBuffer的哪个字节开始转换,默认为0,length为可选参数,指定转换的字节数,默认为arrayBuffer的长度减去byteOffset。
例如,将一个字符串转换为Buffer对象:
const buf = Buffer.from('hello world', 'utf8');
console.log(buf); // Buffer(11) [104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]
Buffer.from()方法还可以将整数数组、另一个Buffer对象或ArrayBuffer对象转换为Buffer对象。例如,将一个整数数组转换为Buffer对象:
const buf = Buffer.from([0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64]);
console.log(buf.toString('utf8')); // hello world
整数数组成功转换为Buffer对象,并且可以将其转换回字符串。
3.2 ArrayBuffer与Uint8Array等对象对比
都是用于处理二进制数据的工具
ArrayBuffer: JavaScript中的一种数据类型,用于表示一段二进制数据。它本身并不能直接进行读写操作,需要使用TypedArray视图或DataView视图来读写数据。
TypedArray: 是一系列与ArrayBuffer关联的视图类型,例如Uint8Array、Int16Array、Float32Array等,用于读写特定类型的二进制数据。 Uint8Array是一种TypedArray类型,用于表示一个包含8位无符号整数的数组。它本质上是ArrayBuffer的一个视图,可以使用下标访问其中的数据,并且支持一些常见的数组操作,例如slice()、concat()等。
区别
-
使用方式和适用场景: ArrayBuffer适用于存储任意类型的二进制数据,而TypedArray则适用于存储特定类型的二进制数据。例如,如果需要存储一个包含8位无符号整数的数组,可以使用Uint8Array,它提供了方便的数组操作和类型转换功能。如果需要存储一个复杂的二进制数据结构,可以使用ArrayBuffer,并使用DataView视图进行读写操作。
-
性能: 在处理大量二进制数据时,使用TypedArray视图可能比使用DataView视图和Buffer对象更高效一些,因为它们可以将数据存储在连续的内存块中,避免了内存碎片问题。
互转
ArrayBuffer -> TypedArray
通过将ArrayBuffer实例传入TypedArray的构造函数,可以得到TypedArray实例
const arrayBuffer = new ArrayBuffer(32)
const unit8Array = new Unit8Array(arrayBuffer)
TypedArray -> ArrayBuffer
TypedArray可以通过实例的buffer属性得到ArrayBuffer实例
const unit8Array = new Unit8Array(arrayBuffer)
const ab = unit8Array.buffer