首页 > 解决方案 > 无法在 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 也无法导入该编码。

标签: javaandroidencodingcharacter-encodingutf-16le

解决方案


您可以尝试使用指定编码的字节顺序标记 (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)。


推荐阅读