Utils将资源文本文件读取为String(Java)

Loc*_*han 200 java string resources text

是否有任何实用程序可以帮助将资源中的文本文件读入String.我想这是一个很受欢迎的要求,但谷歌搜索后我找不到任何实用程序.

Jon*_*eet 290

是的,GuavaResources课堂上提供了这个.例如:

URL url = Resources.getResource("foo.txt");
String text = Resources.toString(url, Charsets.UTF_8);
Run Code Online (Sandbox Code Playgroud)

  • @JonSkeet这很棒,但对于Web应用程序来说它可能不是最好的解决方案,`getResource`的实现使用`Resource.class.getClassLoader`但在Web应用程序中,这可能不是"你的"类加载器,所以它是建议(例如在[1]中)使用`Thread.currentThread().getContextClassLoader().getResourceAsStream`而不是(参考[1]:http://stackoverflow.com/questions/676250/different-ways-of-loading-一个文件-AS-AN-的InputStream) (20认同)
  • 在资源紧邻您的类的特殊情况下,您可以执行`Resources.toString(MyClass.getResource("foo.txt"),Charsets.UTF_8)`,它保证使用正确的类加载器. (4认同)
  • 根据 SonarQube,`com.google.common.io.Resources` 被标记为不稳定 (4认同)
  • `guava` 改变了实现。对于 guava 23,实现如下。`ClassLoader 加载器 = MoreObjects.firstNonNull( Thread.currentThread().getContextClassLoader(), Resources.class.getClassLoader());` (3认同)
  • @EranMedan:是的,如果你想要上下文类加载器,你想明确地使用它. (2认同)

小智 162

您可以使用旧的Stupid Scanner技巧 oneliner来执行此操作,而无需像guava那样的任何其他依赖:

String text = new Scanner(AppropriateClass.class.getResourceAsStream("foo.txt"), "UTF-8").useDelimiter("\\A").next();
Run Code Online (Sandbox Code Playgroud)

伙计们,除非你真的需要,否则不要使用第三方的东西.JDK中已经有很多功能.

  • 避免第三方是一个合理的原则.不幸的是,核心库似乎对建模现实用例过敏.看看Java 7的文件,并告诉我为什么从类路径资源中读取所有内容并不包含在那里?或者至少使用标准化的"文件系统". (38认同)
  • 虽然我已经使用过这个,但我完全不同意避免使用第三方软件包.事实上,在Java中,轻松读取文件到字符串的唯一方法是使用扫描仪技巧非常难过.使用第三方库的替代方案是每个人都将创建自己的包装器.如果您对此类操作有很多需求,那么用于IO的Guava会获胜.如果您在代码中只有一个地方要执行此操作,我将同意您不应导入第三方程序包.这对你来说太过分了. (5认同)
  • 它是 - 或者不是 - 必须关闭流吗?番石榴内部关闭了流. (3认同)
  • 将 ```CartApplication.class.getResourceAsStream``` 更改为 ```CartApplication.class.getClassLoader().getResourceAsStream``` 以加载当前 jar 中的资源..like srm/test/resources (2认同)

Kov*_*ryi 82

对于java 7:

new String(Files.readAllBytes(Paths.get(getClass().getResource("foo.txt").toURI())));
Run Code Online (Sandbox Code Playgroud)

  • 当资源在jar中时不起作用 (46认同)
  • 一旦将应用程序打包到 jar 中,这将不起作用。 (14认同)
  • 它是java 1.7中的nio 2.它是java的原生胎儿.对于编码使用new String(bytes,StandardCharsets.UTF_8) (4认同)
  • 请解释为什么这样做,为什么它比其他替代方案更好,并且需要任何性能/编码考虑因素. (3认同)
  • 在我的情况下,我需要`getClass().getClassLoader()`但是其他方法很棒! (3认同)

Luc*_*sio 57

Guava有一个"toString"方法,用于将文件读入String:

import com.google.common.base.Charsets;
import com.google.common.io.Files;

String content = Files.toString(new File("/home/x1/text.log"), Charsets.UTF_8);
Run Code Online (Sandbox Code Playgroud)

此方法不要求文件位于类路径中(如Jon Skeet上一个答案).

  • 或者,如果它是一个输入流,guava有一个很好的方法,以及`String stringFromStream = CharStreams.toString(new InputStreamReader(resourceAsStream,"UTF-8"));; (2认同)

Luc*_*iva 54

纯粹而简单的Java 8解决方案

如果您使用的是Java 8,下面这个简单的方法就可以了:

/**
 * Reads given resource file as a string.
 *
 * @param fileName path to the resource file
 * @return the file's contents
 * @throws IOException if read fails for any reason
 */
static String getResourceFileAsString(String fileName) throws IOException {
    ClassLoader classLoader = ClassLoader.getSystemClassLoader();
    try (InputStream is = classLoader.getResourceAsStream(fileName)) {
        if (is == null) return null;
        try (InputStreamReader isr = new InputStreamReader(is);
             BufferedReader reader = new BufferedReader(isr)) {
            return reader.lines().collect(Collectors.joining(System.lineSeparator()));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

它也适用于jar文件中的资源.

没有大型肥胖库.除非您已经在使用Guava或Apache Commons IO,否则将这些库添加到项目中只是为了能够将文件作为字符串读取似乎有点太多了.


从静态上下文加载

由于这通常是一个实用程序函数,因此可能希望可以从静态实用程序类访问它.我稍微更改了实现,因此可以将方法声明为static.它的工作原理是一样的.这里是:

new InputStreamReader(isr, StandardCharsets.UTF_8);
Run Code Online (Sandbox Code Playgroud)

  • @zakmck请尽量保持您的意见建设性.随着您成长为一个成熟的开发人员,您会了解到有时您确实想要"重新发明轮子".例如,您可能需要将二进制文件保持在阈值大小以下.库通常会使您的应用程序大小增加数量级.有人可能会说与你所说的相反:"不需要编写代码.是的,我们每次只需导入库".你真的更喜欢导入一个库只是为了节省3行代码吗?我敢打赌,添加库会使你的LOC增加更多.关键是平衡. (4认同)
  • 好吧,并不是每个人都在云上运行东西。例如,随处可见运行Java的嵌入式系统。考虑到您提到自己将接受直接在自己的代码中直接使用JDK的建议,我只是没有批评批评提供完全有效方法的答案。无论如何,让我们尝试严格保留评论以帮助改善答案,而不是讨论意见。 (2认同)
  • 真好 我用这个 您也可以考虑关闭流/阅读器。 (2认同)

Ste*_*lis 41

yegor256 使用Apache Commons IO找到了一个很好的解决方案:

import org.apache.commons.io.IOUtils;

String text = IOUtils.toString(this.getClass().getResourceAsStream("foo.xml"),
                               "UTF-8");
Run Code Online (Sandbox Code Playgroud)

  • 同样紧凑,但正确关闭输入流:`IOUtils.toString(this.getClass().getResource("foo.xml"),"UTF-8")`. (10认同)
  • IOUtils 的另一个例子:`IOUtils.resourceToString("/foo.xml", StandardCharsets.UTF_8);` (4认同)
  • 如果此解决方案不起作用,请尝试将 `getClassLoader()` 添加到方法链中: `String text = IOUtils.toString( getClass().getClassLoader().getResourceAsStream("foo.xml"), StandardCharsets.UTF_8); ` (2认同)

And*_*s_D 37

apache-commons-io有一个实用程序名称FileUtils:

URL url = Resources.getResource("myFile.txt");
File myFile = new File(url.toURI());

String content = FileUtils.readFileToString(myFile, "UTF-8");  // or any other encoding
Run Code Online (Sandbox Code Playgroud)

  • @Hamidan,选择正确的编码是一种非常复杂的算法.它通常在文本编辑器中实现,但有时无法检测到正确的编码.我不希望文件读取API嵌入这样复杂的算法来读取我的文件. (10认同)
  • 为什么必须指定编码,我不明白。如果我阅读该文件,我只想要其中的内容,它应该像我的编辑器一样找出它的编码。当我在记事本或++中打开时,我不告诉它应该使用什么编码。我正在使用这种方法,然后使用 writeStringToFile ...但内容有所不同。我在克隆文件中得到奇怪的标记。我不明白为什么我应该指定编码。 (2认同)
  • 如果在jar中找到资源,我认为这不会起作用.然后它不会是一个文件. (2认同)

小智 16

我自己经常遇到这个问题.为了避免对小项目的依赖,我经常在不需要commons io等时编写一个小实用程序函数.以下是在字符串缓冲区中加载文件内容的代码:

StringBuffer sb = new StringBuffer();

BufferedReader br = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream("path/to/textfile.txt"), "UTF-8"));
for (int c = br.read(); c != -1; c = br.read()) sb.append((char)c);

System.out.println(sb.toString());   
Run Code Online (Sandbox Code Playgroud)

在这种情况下,指定编码重要,因为您可能已经用UTF-8编辑了文件,然后将其放在jar中,打开文件的计算机可能将CP-1251作为其本机文件编码(例如) ; 所以在这种情况下你永远不会知道目标编码,因此显式编码信息至关重要.此外,通过char读取文件char的循环似乎效率低下,但它在BufferedReader上使用,因此实际上非常快.


Rag*_*air 12

您可以使用以下代码形式Java

new String(Files.readAllBytes(Paths.get(getClass().getResource("example.txt").toURI())));
Run Code Online (Sandbox Code Playgroud)

  • 当资源在jar文件中时它是否有效? (3认同)
  • 两者都是 JDK 7+ 提供的 java.nio.file 包的一部分 (2认同)
  • 在 jar 文件中时不起作用。 (2认同)

Gar*_* S. 6

我喜欢 akosicki 对 Stupid Scanner Trick 的回答。这是我看到的最简单的没有外部依赖的 Java 8(实际上一直回到 Java 5)。如果您可以使用 Java 9 或更高版本(因为InputStream.readAllBytes()是在 Java 9 中添加的),这里有一个更简单的答案:

String text = new String(AppropriateClass.class.getResourceAsStream("foo.txt").readAllBytes());
Run Code Online (Sandbox Code Playgroud)

  • 最佳答案但评分如此之低...... (3认同)

Dil*_*ing 5

这是使用 Java 11 的解决方案Files.readString

public class Utils {
    public static String readResource(String name) throws URISyntaxException, IOException {
        var uri = Utils.class.getResource("/" + name).toURI();
        var path = Paths.get(uri);
        return Files.readString(path);
    }
}
Run Code Online (Sandbox Code Playgroud)