前段時間遇到了一個比較有意思的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
這個方案比較粗暴,引了兩個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) } }
⚠️:方案二隻在本地調試過,本地跑起來沒什麼問題。具體的可用性和兼容性不肯定。