txt 文件轉碼

寫在前面

前段時間遇到了一個比較有意思的bug,txt文件資源用瀏覽器打開預覽的時候亂碼。而後就想給你們分享一下,最後的處理方案。前端

問題&&分析

問題:須要把txt文件統一轉成utf-8的編碼格式
分析:txt經常使用的編碼格式包括 ANSI、UTF-八、GB2312 ,再簡體中文的系統下,ASNI 和 GB2312 是同樣的,因此咱們要處理的只有GB2312 和 UTF-8node

⚠️: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再作中文檢測不許確。

實現流程圖:segmentfault

image.png

方案二

這個方案比較粗暴,引了兩個nodejs,前端也能跑。關於這個方案我只是作了個簡單的嘗試,不過擴展性上一個方案好很多,有興趣的小夥伴能夠試一試。windows

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)
    }
}
⚠️:方案二隻在本地調試過,本地跑起來沒什麼問題。具體的可用性和兼容性不肯定。
相關文章
相關標籤/搜索