打算用微信小程序将数据存为UTF-8格式的CSV,让Excel编辑.
使用wx.writeFile或者writeFileSync可以设置编码为UTF-8保存. 但此后的坑就连续不断出现了.
通过shareFileMessage转给自己, 用Excel打开, 就会发现是乱码. 原因是Excel只支持带BOM的UTF-8. 开始解决这个问题, 然而微信和Excel都有坑, 分别说下:

微信的系统差异

要给文件前面加UTF-8 BOM, 最简单是在保存的字符串前加入 \ufeff 再用writeFile+UTF8格式保存. 你会发现Android版本微信很好地完成了这个任务, Excel顺利打开, 然而ios版本微信会把你加入的\ufeff自动删除! 保存了个寂寞

微信用binary方式保存

问遍教程,都会让你用Buffer和TextEncoder通过UTF8编码转为ArrayBuffer前面再加入BOM头0xEF、0xBB、0xBF, 但是微信小程序不支持这两个常见的类Buffer和TextEncoder. 除非你自己实现一个.

微信曲线救国方式

碰到ios, 先保存,再读取,再在前面加入BOM头,再保存. 利用微信writeFile保存功能支持UTF8来解决

    tableStr = '\ufeff' + tableStr // 增加UTF8 BOM头
    const fs = wx.getFileSystemManager()
    fs.writeFileSync(filename, tableStr, 'utf-8')
    const deviceInfo = wx.getDeviceInfo()
    if(deviceInfo.platform == 'ios'){
      // 由于iOS系统上会把utf8保存的文件的前面的bom头删除(android不会),所以需要以arrayBuffer的方式读入文件之后重新加上utf8 BOM头。
      // 之所以不在内存中完成转换,而是通过文件读写的方式转换, 原因是内存中转换字符串到Utf8的两种手段Buffer/TextEncoder在微信小程序中都不支持。
      let file = fs.readFileSync(filename) 
      const bom = new Uint8Array([0xEF, 0xBB, 0xBF]);
      // 将文件内容转换为 Uint8Array 并合并
      const contentArray = new Uint8Array(file);
      const mergedArray = new Uint8Array(bom.length + contentArray.length);
      mergedArray.set(bom, 0);
      mergedArray.set(contentArray, bom.length);
      fs.writeFileSync(filename, mergedArray.buffer, 'binary')
    }

Excel的坑: 从2016版本才开始支持CSV UTF-8格式

如果你是2016以前的版本就不要挣扎了, 还不如用Win10/11上的记事本编辑了.

标签: none 阅读量: 104

添加新评论