写在后面

前段时间遇到了一个比拟有意思的bug,txt文件资源用浏览器关上预览的时候乱码。而后就想给大家分享一下,最初的解决计划。

问题&&剖析

问题:须要把txt文件对立转成utf-8的编码格局
剖析:txt罕用的编码格局包含 ANSI、UTF-8、GB2312 ,再简体中文的零碎下,ASNI 和 GB2312 是一样的,所以咱们要解决的只有GB2312 和 UTF-8

⚠️:windows office 2003 的 txt 文件默认编码格局是 GB2312

计划一

第一个计划就比拟有意思了,用的是 FileReader.readAsText,这个属性能够指定文件编码格局,取出文件的纯文本。然而如果指定的编码格局和源文件编码格局不一样,提取进去的文本就会乱码。所以这里的思路是:
1️ 先用“utf-8”拿一次文本
2️ 检测 string 有没有中文,如果没有中文的话一律当成乱码解决(gb2312和utf-8的英文编码一样)
3️ 如果后面检测进去乱码了,就用“gb2312”从新拿一次文本,这一次就不必检测了,拿进去的就是失常文本了
4️ 用没有乱码的文本生成一个新的文件

function txt2utf8(file, callback){    let newBlob = null    const reader = new FileReader()    // readAsText 能够 指定编码格局 将文件提取成 纯文本    reader.readAsText(file,'utf-8')    reader.onload = e => {        const txtString = e.target.result        // utf-8 的 中文编码 正则表达式        const patrn=/[\uFE30-\uFFA0]/gi;        // 检测以后文本是否含有中文(如果没有,则当乱码解决)        // 两个格局的英文编码一样,所以纯英文文件也当成乱码再解决一次        if (!patrn.exec(txtString)) {            let reader_gb2312 = new FileReader()            // 再拿一次纯文本,这一次拿到的文本肯定不会乱码            reader_gb2312.readAsText(file,'gb2312')            reader_gb2312.onload = e2 => {                newBlob = new Blob([e2.target.result])                callback&&callback(newBlob)            }        } else {            // 这里其实能够间接输入源文件,我是为了对立,都转成blob了            newBlob = new Blob([txtString])            callback&&callback(newBlob)        }    }}
⚠️:不要调整 “utf-8” 和 “gb2312” 的程序。因为readAsText外部的实现问题,用gb2312去拿utf-8的txt再做中文检测不精确。

实现流程图:

计划二

这个计划比拟粗犷,引了两个nodejs,前端也能跑。对于这个计划我只是做了个简略的尝试,不过扩展性上一个计划好不少,有趣味的小伙伴能够试一试。

import iconv from 'iconv-lite'import jschardet from 'jschardet'function txt2utf8(file, callback){    const reader = new FileReader()    reader.readAsBinaryString(file)    reader.onload = e => {        const txtBinary = e.target.result        // 用 jschardet 拿文件流编码 ,可能会存在偏差        const binaMg = jschardet.detect(txtBinary)        const buf = new Buffer(txtBinary, 'binary')        // 用 iconv 转码        const str = iconv.decode(buf, binaMg.encoding)        const newBlob = new Blob([str])        callback&&callback(newBlob)    }}
⚠️:计划二只在本地调试过,本地跑起来没什么问题。具体的可用性和兼容性不确定。