无法在 Android 版本 9 上使用 UTF-16LE 编码

Unable to use encoding UTF-16LE on Android Version 9

我有一个创建 csv 文件的应用程序。然后该文件由 excel makro 导入。 makro 需要使用 UTF-16LE 编码对文件进行编码。问题是,我无法在某些设备上使用此编码。

到目前为止,我使用字符集 UTF-16 来创建文件。当我用 notepad++ 打开文件时,它显示文件是用 UTF-16LE 编码的。现在我有一个新设备,当我用它创建 csv 文件时,notepad++ 显示编码是 UTF-16BE。结果,当我尝试使用 excel makro.

导入文件时出现错误

我尝试将编码指定为 UTF-16LE,根据 android 的 developer page,这应该是一个有效的字符集。但是 notepad++ 无法识别我的文件的编码并且 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 编码?


我确实看过 this answere 并像这样实现它:

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。例如,以下代码将生成一个 csv 文件,适合使用字节顺序标记导入 Excel:

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 标准。 here 描述了这些变化。不确定这会对您的情况产生什么影响,但值得一看 (IMO)。