代码之家  ›  专栏  ›  技术社区  ›  Meltryllis

java生成的UTF-16LE编码的Desktop.ini在包含中文字符时不起作用

  •  2
  • Meltryllis  · 技术社区  · 10 月前

    我试图创建一个 新欢乐时光 通过java为Windows11文件夹提供一个替代名称(就像 我的文档 看起来像)。

    下面是一个简单的代码示例(可以直接调用它来运行):

    @Test
    public void createDesktopIni() throws IOException {
        String folderPath = Write a folder path here;
        String iniPath = folderPath + "\\desktop.ini";
        File file = new File(iniPath);
        // delete and recreate if exist
        if (file.exists()) {
            file.delete();
        }
        file.createNewFile();
        // Write content
        String alternativeName = "Alternative Name";
        //alternativeName = "这是一个中文别名";
        OutputStreamWriter oStreamWriter = new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_16LE);
        oStreamWriter.write("[.ShellClassInfo]\nLocalizedResourceName = " + alternativeName);
        oStreamWriter.flush();
        oStreamWriter.close();
        // Set system attribute
        Files.setAttribute(Paths.get(folderPath), "dos:system", true, LinkOption.NOFOLLOW_LINKS);
        Files.setAttribute(Paths.get(iniPath), "dos:system", true, LinkOption.NOFOLLOW_LINKS);
        Files.setAttribute(Paths.get(iniPath), "dos:hidden", true, LinkOption.NOFOLLOW_LINKS);
    }
    

    如果我设置一个英文替代名称 新欢乐时光 可以正常工作。(顺便说一句,此时可以通过VSCode正常打开此文件)。

    但是,如果我设置一个中文替代名称,如comment:

    alternativeName = "这是一个中文别名";

    此时 新欢乐时光 文件无法工作。

    如果我通过VSCode打开它,将显示以下内容: VS Code Error Message

    但如果我选择 无论如何打开->使用UTF-16 LE编码重新打开 ,然后通过VS Code将文件另存为UTF-16LE,它再次正常工作。

    以下是我尝试过的一些其他编码:

    1. UTF-8可以工作,但Explorer.exe中的中文字符会出现乱码。
    2. GBK有效,而且没有乱码。但我更喜欢使用UTF-16,我看到 新欢乐时光 在里面 我的文档 文件夹也使用UTF-16LE。
    3. UTF-16不起作用,文件将被编码为UTF-16 be。
    1 回复  |  直到 10 月前
        1
  •  4
  •   Remy Lebeau    10 月前

    A. Desktop.ini 包含Unicode字符的文件(或Windows上的任何INI文件)必须以UTF-16开头 BOM 因此Win32 API知道内容是Unicode。但您并没有像使用时那样生成BOM StandardCharsets.UTF_16LE 这是无BOM的。

    您可以:

    • 使用 StandardCharsets.UTF_16 相反,它有一个BOM(但可能是UTF-16LE或be):

      OutputStreamWriter oStreamWriter = new OutputStreamWriter(..., StandardCharsets.UTF_16);
      
    • 继续使用 UTF_16LE 并在其他任何事情之前手动编写BOM:

      OutputStreamWriter oStreamWriter = new OutputStreamWriter(..., StandardCharsets.UTF_16LE);
      oStreamWriter.write(0xFEFF);
      ...