【问题标题】:What is simplest way to read a file into String? [duplicate]将文件读入字符串的最简单方法是什么? [复制]
【发布时间】:2011-03-25 01:59:16
【问题描述】:

我正在尝试将一个简单的文本文件读入一个字符串。当然,通常的方法是获取输入流并使用 readLine() 进行迭代并将内容读入 String。

过去已经这样做了数百次,我只是想知道如何以最少的代码行数做到这一点? java中没有像String fileContents = XXX.readFile(myFile/*File*/)这样的东西吗?而是看起来像这样简单的东西?

我知道有像 Apache Commons IO 这样的库可以提供这样的简化,甚至我可以编写一个简单的 Util 类来执行此操作。但我想知道的是 - 这是一个每个人都需要的如此频繁的操作,那么为什么 Java 不提供这么简单的功能呢?难道真的没有一种方法可以将文件读入具有某种默认或指定编码的字符串吗?

【问题讨论】:

    标签: java file file-io


    【解决方案1】:

    是的,您可以在一行中完成此操作(尽管对于强大的IOException 处理您不希望这样做)。

    String content = new Scanner(new File("filename")).useDelimiter("\\Z").next();
    System.out.println(content);
    

    这使用java.util.Scanner,告诉它用\Z分隔输入,这是字符串锚的结尾。这最终使输入具有一个实际的标记,即整个文件,因此可以通过调用next() 来读取它。

    a constructor 采用 FileString charSetName(在许多其他重载中)。这两个构造函数可能会抛出FileNotFoundException,但就像所有Scanner 方法一样,除了这些构造函数之外,不能抛出任何IOException

    如果IOException发生与否,您可以通过ioException()方法查询Scanner本身。您可能还想在阅读内容后明确地 close() Scanner,因此最好将 Scanner 引用存储在局部变量中。

    另见

    相关问题


    第三方库选项

    为了完整起见,如果您拥有这些非常有名且非常有用的第三方库,那么这些是一些非常好的选择:

    Guava

    com.google.common.io.Files 包含许多有用的方法。这里相关的是:

    Apache Commons/IO

    org.apache.commons.io.IOUtils 也提供类似的功能:

    • String toString(InputStream, String encoding)
      • 使用指定的字符编码,获取InputStream的内容为String
    • List readLines(InputStream, String encoding)
      • ...作为String 的(原始)List,每行一个条目

    相关问题

    【讨论】:

    • 请参阅下面的解决方案,了解 Java 7 机制,该机制本质上与默认 API 保持一致,因为自这个问题以来 Java 已经稍微推进了许多事情。
    • 不幸的是,Scanner 解决方案因空文件而失败 (NoSuchElementException)
    • 我已经使用了一段时间,但事实证明它并不总是有效!有时\\Z 会实际出现在文件中,会导致此操作失败。
    • return new Scanner(new URL(url).openStream(), "UTF-8").useDelimiter("\\A").next();更好,因为它不会在空文件上失败。
    • 避免这种情况,如果您使用大于 1024 字节的文本文件。扫描器将(至少在 Android 上)将生成的字符串切割为 1024 字节。
    【解决方案2】:

    从 Java 7 (API Description) 开始,您可以这样做:

    new String(Files.readAllBytes(Paths.get(filePath)), StandardCharsets.UTF_8);

    其中 filePath 是一个字符串,表示您要加载的文件。

    【讨论】:

    • 我相信这只有在文件位于平台的默认字符集中时才有效。
    • @Paul 我认为可以作为默认设置。构造新字符串时总是可以指定一个字符集
    • 此解决方案的缺点是不能使用类路径资源(通过Class.getResource() 或类似方法获得),而Scanner 解决方案在这种情况下确实有效。
    • 我上一条评论的纯 java 版本: String iAmAString = new String(Files.readAllBytes(new File(Thread.currentThread().getContextClassLoader().getResource("iAmAFile").toURI() ).toPath()));
    • @Rondo 并非所有的类路径资源都对应于File(例如,考虑一下 jar 中的资源),所以不,它不能用于一般情况。
    【解决方案3】:

    你可以使用apache commons IO..

    FileInputStream fisTargetFile = new FileInputStream(new File("test.txt"));
    
    String targetFileStr = IOUtils.toString(fisTargetFile, "UTF-8");
    

    【讨论】:

    • 当 Java 内置了可以正常工作的设施时,Java 程序员总是尝试使用第三方库是怎么回事。
    • 当然,这些设施“工作得很好”,只是其中一些过于复杂。但是,我同意仅为此使用另一个库有点矫枉过正。
    • 这并不过分。这是一个机会。有机会开始使用 apache 公共库并提高工作效率。或者你可以选择番石榴。
    • 这是一个三班轮 - 你需要对流进行调整。
    【解决方案4】:

    这应该适合你:

    import java.io.IOException;
    import java.nio.file.Files;
    import java.nio.file.Paths;
    
    public static void main(String[] args) throws IOException {
        String content = new String(Files.readAllBytes(Paths.get("abc.java")));
    }
    

    【讨论】:

    • 谢谢!与多数解决方案相比,这也不会删除尾随换行符。一项改进:new String(…, StandardCharsets.UTF_8)
    【解决方案5】:

    使用Apache Commons IO

    import org.apache.commons.io.FileUtils;
    
    //...
    
    String contents = FileUtils.readFileToString(new File("/path/to/the/file"), "UTF-8")
    

    详情可以看javadoc for the method

    【讨论】:

      【解决方案6】:

      不要编写自己的 util 类来执行此操作 - 我建议使用 Guava,它充满了各种优点。在这种情况下,您需要Files 类(如果您真的只是在读取文件)或CharStreams 以进行更通用的读取。它具有将数据读入字符串列表 (readLines) 或完全 (toString) 的方法。

      它对二进制数据也有类似的有用方法。然后是图书馆的其余部分......

      我同意标准库中没有类似的东西很烦人。哎呀,只需将CharSet 提供给FileReader 就会让生活变得有点简单...

      【讨论】:

      • 在 Java 7 上,你会推荐 Guava 还是 new String(Files.readAllBytes(Paths.get(filePath)))
      • @Manu:我肯定不会使用它——我至少会指定一个字符编码。但由于番石榴通常还是有用的(即使是 Java 8),你不妨使用Files.toString,因为它很容易......
      【解决方案7】:

      另一种替代方法是:

      How do I create a Java string from the contents of a file?

      其他选项是使用提供的开源库实用程序
      http://commons.apache.org/io/api-1.4/index.html?org/apache/commons/io/IOUtils.html

      为什么 java 不提供如此通用的 util API?
      a) 以保持 API 的通用性,以便程序员处理编码、缓冲等。
      b) 让程序员做一些工作并编写/共享开源实用程序库:D ;-)

      【讨论】:

        【解决方案8】:

        很遗憾,没有。

        我同意这种频繁的操作应该比在循环中逐行复制输入更容易实现,但是您必须编写辅助方法或使用外部库。

        【讨论】:

          【解决方案9】:

          我发现接受的答案实际上并不总是有效,因为文件中可能出现\\Z。另一个问题是,如果您没有正确的字符集,可能会发生一大堆意想不到的事情,这可能导致扫描仪只读取文件的一部分。

          解决方案是使用您确定文件中永远不会出现的分隔符。然而,这在理论上是不可能的。我们可以做的是使用在文件中出现的可能性很小以至于可以忽略不计的分隔符:这样的分隔符是 UUID,它在 Java 中是原生支持的。

          String content = new Scanner(file, "UTF-8")
              .useDelimiter(UUID.randomUUID().toString()).next();
          

          【讨论】:

          • “文件中可能出现\\Z”是什么意思? \Z (取消转义后)是 java.util.regex.Pattern 的模式之一,而不是文字字符序列。文件中的文字字符序列(后跟 Z 的反斜杠)与模式 \Z 不匹配。
          • @KuroKurosaka 我不是指文字序列\Z,我的意思是文件实际上可能在文件中间某处包含“字符串结尾”字符。它发生在我身上,这就是接受的答案对我不起作用的原因。
          • 我明白了。您正在考虑这样一种情况,即某个软件或操作系统决定对 EOL 序列使用 CR 或 LF(或两者,如果是 Microsoft)以外的控制字符。我会把它写成“'\u001A',例如,如果 Control-Z 被用作 EOF 字符”。
          猜你喜欢
          • 2016-08-20
          • 1970-01-01
          • 2012-08-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-07-01
          • 2011-08-31
          相关资源
          最近更新 更多