【问题标题】:Files#write does not work with byte[] and charsetFiles#write 不适用于 byte[] 和 charset
【发布时间】:2019-11-27 07:41:15
【问题描述】:

按照这个3rd answer,我可以写一个这样的文件

Files.write(Paths.get("file6.txt"), lines, utf8,
        StandardOpenOption.CREATE, StandardOpenOption.APPEND);

但是当我在我的代码上尝试它时,我得到了这个错误:

方法write(Path, Iterable, Charset, 文件类型中的 OpenOption...) 不适用于参数 (路径, byte[], Charset, StandardOpenOption)

这是我的代码:

    File dir = new File(myDirectoryPath);
    File[] directoryListing = dir.listFiles();
    if (directoryListing != null) {
        File newScript = new File(newPath + "//newScript.pbd");     
            if (!newScript.exists()) {
                newScript.createNewFile();
            }
        for (File child : directoryListing) {

            if (!child.isDirectory()) {
                byte[] content = null;
                Charset utf8 = StandardCharsets.UTF_8;

                content = readFileContent(child);
                try {

                    Files.write(Paths.get(newPath + "\\newScript.pbd"), content,utf8,
                            StandardOpenOption.APPEND); <== error here in this line.

                } catch (Exception e) {
                    System.out.println("COULD NOT LOG!! " + e);
                }
            }

        }
    }

请注意,如果更改我的代码以使其正常工作并将其写入文件(删除 utf8)。

                    Files.write(Paths.get(newPath + "\\newScript.pbd"), content,
                            StandardOpenOption.APPEND);

【问题讨论】:

  • byte[] 这样的数组不是Iterable
  • 您很可能打算调用此方法docs.oracle.com/en/java/javase/13/docs/api/java.base/java/nio/… 即没有字符集。
  • 它不被视为Iterable,但与您的调用最接近的方法是具有Iterable的版本。但是字节数组并不适用。您想要采用 byte[] 的变体,但该变体不采用字符集。因为如果数据已经是二进制的,字符集就没有意义了。因为字符集的唯一目的是从String 正确转换为二进制byte[]。你之前已经这样做了。
  • 是的,因为字符集在这种情况下毫无意义。需要指定字符集从字符串到二进制的位置,即在您的阅读阶段。请注意,Files 中的所有方法都默认使用 UTF-8,因此无需指定。
  • @Zabuza 好的,谢谢,你很有帮助,请提供它作为接受的答案。

标签: java file file-io nio


【解决方案1】:

说明

Files#write 方法有 3 个重载(参见documentation):

  • 接受Path, byte[], OpenOption...(无字符集)
  • 采用Path, Iterable&lt;? extends CharSequence&gt;, OpenOption...(如List&lt;String&gt;,无字符集,使用UTF-8)
  • 接受Path, Iterable&lt;? extends CharSequence&gt;, Charset, OpenOption...(有字符集)

对于您的电话 (Path, byte[], Charset, OpenOption...),不存在匹配的版本。因此,它无法编译。

它不匹配第一个和第二个重载,因为它们不支持Charset,它不匹配第三个重载,因为数组Iterable(像ArrayList 这样的类)也不匹配,也不是byte 扩展 CharSequenceString 确实)。

在错误消息中,您可以看到 Java 计算出的与您的调用最接近的匹配项,不幸的是(如上所述),它不适用于您的参数。


解决方案

您很可能打算进行第一次重载:

Files.write(Paths.get("file6.txt"), lines,
    StandardOpenOption.CREATE, StandardOpenOption.APPEND);

即没有字符集。


注意事项

字符集在您的上下文中没有意义。字符集的唯一目的是将String 正确转换为二进制byte[]。但是您的数据已经是二进制的,因此字符集在此之前就已经到位。在您的情况下,这将是readFileContent 中的阅读阶段。

另请注意,Files 中的所有方法都默认使用 UTF-8。所以无论如何都不需要额外指定它。

在指定OpenOptions 时,您可能还想指定是StandardOpenOption.READ 还是StandardOpenOption.WRITE 模式。 Files#write 方法默认使用:

WRITE
CREATE
TRUNCATE_EXISTING

所以你可能想用它来调用它

WRITE
CREATE
APPEND

示例

这里有一些关于如何在 UTF-8 中完全读写文本和二进制文件的 sn-ps:

// Text mode
List<String> lines = Files.readAllLines(inputPath);
// do something with lines
Files.write(outputPath, lines);

// Binary mode
byte[] content = Files.readAllBytes(inputPath);
// do something with content
Files.write(outputPath, content);

【讨论】:

    【解决方案2】:

    在第三个答案中,您提到文件的内容是可迭代的,即 List.您不能将此方法与 byte[] 一起使用。让您的 readFileContent() 方法返回类似 List 的可迭代内容(每个元素都是文件的一行)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多