java - 无法在 Android 版本 9 上使用编码 UTF-16LE
问题描述
我有一个创建 csv 文件的应用程序。然后由 excel makro 导入该文件。makro 需要使用 UTF-16LE 编码对文件进行编码。问题是,我无法在某些设备上使用此编码。
到目前为止,我使用字符集 UTF-16 来创建文件。当我用记事本++打开文件时,它显示文件是用UTF-16LE编码的。现在我有了一个新设备,当我用它创建 csv 文件时,notepad++ 显示编码是 UTF-16BE。结果,当我尝试使用 excel makro 导入文件时出现错误。
我尝试将编码指定为 UTF-16LE,根据android的开发人员页面,它应该是一个有效的字符集。但是记事本++无法识别我的文件的编码,并且excel makro无法读取它(对于旧设备和新设备)。
在这两种情况下,我都可以通过 notepad++ 将编码转换为 UTF-16LE,并使用我的 makro 成功导入文件,但我需要从我的应用程序中以正确的格式创建文件。
旧设备具有 android 版本5.1
较新的设备具有 android 版本9.0
这是我的代码:
File file = new File("some_name");
if (file.exists()) {
file.delete();
}
file.getParentFile().mkdirs();
file.createNewFile();
Writer osw = new OutputStreamWriter(new FileOutputStream(file),"UTF-16LE"); //Or "UTF-16"
osw.write("foo");
osw.write("bar");
osw.close();
如何在新设备上使用 UTF-16LE 编码?
我确实看了一下这个答案并像这样实现它:
Writer osw = new OutputStreamWriter(new FileOutputStream(file),"UTF-16LE"); //Or "UTF-16"
osw.write(new String(("foo").getBytes("UTF-16LE"), "UTF-16LE"));
osw.write(new String(("bar").getBytes("UTF-16LE"), "UTF-16LE"));
osw.close();
我也使用了,StandardCharsets.UTF_16LE
但它没有改变任何东西。notepad++ 仍然无法识别编码,makro 也无法导入该编码。
解决方案
您可以尝试使用指定编码的字节顺序标记 (bom) 显式强制 UTF-16LE 编码。Notepad++ 和 Excel 都可以解释 bom。例如,以下代码将生成一个适合使用字节顺序标记导入 Excel 的 csv 文件:
public void writeFile(Context context) throws IOException {
File file = new File(context.getFilesDir(), "some_name.csv");
if (file.exists()) file.delete();
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(file), Charsets.UTF_16LE);
// The byte order mark for UTF-16 is "\ufeff" but will appear as "\ufffe" when
// the file is UTF-16LE.
osw.write("\ufeff");
osw.write("Header1,Header2,Header3,Header4\n");
osw.write("text1,text2,text3,text4\n");
osw.write("text5,text6,text7,text8");
osw.close();
}
在 Android 9 模拟器上生成的文件如下所示:
PS C:\> format-hex some_name.csv
Path: C:\some_name.csv
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000 FF FE 48 00 65 00 61 00 64 00 65 00 72 00 31 00 .þH.e.a.d.e.r.1.
00000010 2C 00 48 00 65 00 61 00 64 00 65 00 72 00 32 00 ,.H.e.a.d.e.r.2.
00000020 2C 00 48 00 65 00 61 00 64 00 65 00 72 00 33 00 ,.H.e.a.d.e.r.3.
00000030 2C 00 48 00 65 00 61 00 64 00 65 00 72 00 34 00 ,.H.e.a.d.e.r.4.
00000040 0A 00 74 00 65 00 78 00 74 00 31 00 2C 00 74 00 ..t.e.x.t.1.,.t.
00000050 65 00 78 00 74 00 32 00 2C 00 74 00 65 00 78 00 e.x.t.2.,.t.e.x.
00000060 74 00 33 00 2C 00 74 00 65 00 78 00 74 00 34 00 t.3.,.t.e.x.t.4.
00000070 0A 00 74 00 65 00 78 00 74 00 35 00 2C 00 74 00 ..t.e.x.t.5.,.t.
00000080 65 00 78 00 74 00 36 00 2C 00 74 00 65 00 78 00 e.x.t.6.,.t.e.x.
00000090 74 00 37 00 2C 00 74 00 65 00 78 00 74 00 38 00 t.7.,.t.e.x.t.8.
Notepad++ 像这样解释文件:
导入文件后 Excel 会显示以下内容:
这不会直接回答您的问题,但您应该能够将此代码与您的数据一起使用来帮助诊断问题。
我在评论中留下了这一点,但我会在这里再次提及:UTF 解码器的行为确实随着 Android 9 的变化而变得更加符合 Unicode 标准。此处描述了这些更改。不确定这会对您的情况产生什么影响(如果有的话),但值得一看(IMO)。
推荐阅读
- javascript - 单击按钮时暂停 requestAnimationFrame
- sql - 左连接,但保留 NULL 可能导致 Microsoft SQL 的值
- interop - 从 C# 调用 c++WinRt 运行时类
- android - 我的 android 测验应用程序在 android studio 中不断崩溃
- angular - 不可分配给类型问题
- javascript - Label is too long in Doughnut Chart
- excel - Be more efficient in VBA coding --> efficient VBA looping
- python - 字段中的正值和负值
- java - 如何在共享偏好中为用户添加条件
- angular - 使用 TypeScript 和 Webpack 导入通配符的性能