リソーステキストファイルを文字列に読み取るためのユーティリティ(Java)[クローズ]


231

リソース内のテキストファイルを文字列に読み込むのに役立つユーティリティはありますか?これは一般的な要件だと思いますが、グーグルした後はユーティリティが見つかりませんでした。


1
「リソーステキストファイル」と「リソース内のテキストファイル」の意味を明確にしてください。何を達成しようとしているのかを理解するのは簡単ではありません。
マット

これは、「classpath *:mytext / text.txt」のようなクラスパスの下にある単なるテキストファイルです
Loc Phan

回答:


306

はい、グアバResourcesクラスでこれを提供します。例えば:

URL url = Resources.getResource("foo.txt");
String text = Resources.toString(url, StandardCharsets.UTF_8);

22
@JonSkeetこれは素晴らしいことですが、Webアプリケーションの場合は最善の解決策ではない可能性があり、の実装getResourceはを使用してResource.class.getClassLoaderいますが、Webアプリケーションでは、これは「あなたの」クラスローダーではない可能性があるため、([1]などで)使用することをお勧めしますThread.currentThread().getContextClassLoader().getResourceAsStream代わりに(参照[1]:stackoverflow.com/questions/676250/…
Eran Medan

2
@EranMedan:はい、コンテキストクラスローダーが必要な場合は、明示的に使用する必要があります。
Jon Skeet 2013年

6
リソースがクラスの隣にある特別な場合にResources.toString(MyClass.getResource("foo.txt"), Charsets.UTF_8)は、正しいクラスローダーの使用を保証することができます。
ボグダンカルマック2015年

3
com.google.common.io.ResourcesSonarQube
Ghilterasに

2
guava実装が変更されました。guava 23の場合、実装は次のようになります。ClassLoader loader = MoreObjects.firstNonNull( Thread.currentThread().getContextClassLoader(), Resources.class.getClassLoader());
xxy

180

古いStupidScannerトリックonelinerを使用して、guavaのような追加の依存関係なしでそれを行うことができます。

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

みんな、本当に必要な場合を除いて、サードパーティのものを使用しないでください。JDKにはすでに多くの機能があります。


44
サードパーティを避けることは合理的な原則です。残念ながら、コアライブラリは実際のユースケースのモデリングにアレルギーがあるようです。Java 7のファイルを見て、クラスパスリソースからすべてを読み取ることが含まれていなかった理由を教えてください。または、少なくとも標準化された「ファイルシステム」を使用します。
Dilum Ranatunga 2014

3
ストリームも閉じる必要がありますか?それともそうではありませんか?Guavaは内部的にストリームを閉じます。
virgo47 2014年

私にとっても美しく働きました!サードパーティのことについても同意します。多くの回答では、デフォルトの応答は常にサードパーティのライブラリを使用しているようです。Apacheまたは他の誰かからのものです。
Terje Dahl

1
に変更CartApplication.class.getResourceAsStreamCartApplication.class.getClassLoader().getResourceAsStreamて、現在のjarにリソースをロードします。srm/ test / resourcesなど
Chris DaMour 2016

7
私はこれを使用しましたが、サードパーティのパッケージを避けることに完全に同意しません。Javaでは、ファイルを文字列に簡単に読み取る唯一の方法がスキャナーのトリックを使用することであるという事実はかなり悲しいことです。サードパーティのlibを使用する代わりに、誰もが独自のラッパーを作成するだけです。この種の操作が必要な場合は、Guava forIOが勝ちます。私が同意するのは、コード内にこれを実行したい場所が1つしかない場合は、サードパーティのパッケージをインポートしないことです。それはやり過ぎだろう。
ケニーケイソン2016年

93

Java 7の場合:

new String(Files.readAllBytes(Paths.get(getClass().getResource("foo.txt").toURI())));

4
これが機能する理由、他の選択肢よりも優れている理由、および必要なパフォーマンス/エンコーディングの考慮事項を説明してください。
nanofarad 2014年

5
Java1.7ではnio2です。これは、Javaのネイティブ機能です。エンコードには、新しいString(bytes、StandardCharsets.UTF_8)を使用します
Kovalsky Dmitryi 2014年

6
私の場合、私は必要でしたgetClass().getClassLoader()が、そうでなければ素晴らしい解決策です!
Emmanuel Touzery 2016

7
アプリがjarにパッケージ化されると、これは機能しません。
ダニエルボー

68

純粋でシンプルな、jarに適したJava8 +ソリューション

以下のこの簡単な方法は、Java8以降を使用している場合に問題なく機能します。

/**
 * 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()));
        }
    }
}

また、jarファイル内のリソースで機能します

テキストエンコーディングについて:InputStreamReader指定しない場合は、デフォルトのシステム文字セットを使用します。次のようなデコードの問題を回避するために、自分で指定することをお勧めします。

new InputStreamReader(isr, StandardCharsets.UTF_8);

不要な依存関係を回避する

大きくて太いライブラリに依存しないことを常に好みます。すでにGuavaまたはApacheCommons IOを他のタスクに使用している場合を除いて、ファイルから読み取るためだけにこれらのライブラリをプロジェクトに追加するのは少し多すぎるようです。

「簡単な」方法?バカにしてるね

このような単純なタスクを実行する場合、純粋なJavaはうまく機能しないことを理解しています。たとえば、Node.jsのファイルから読み取る方法は次のとおりです。

const fs = require("fs");
const contents = fs.readFileSync("some-file.txt", "utf-8");

シンプルで読みやすい(ただし、ほとんどの場合、無知のために、とにかく多くの依存関係に依存することを好む人がいます)。またはPythonの場合:

with open('some-file.txt', 'r') as f:
    content = f.read()

悲しいことですが、Javaの標準ではそれでも簡単であり、上記のメソッドをプロジェクトにコピーして使用するだけです。私はあなたにそこで何が起こっているのかを理解するようにさえ求めません。なぜならそれは本当に誰にとっても重要ではないからです。それはうまくいきます、期間:-)


4
@zakmckコメントは建設的なものにしてください。成熟した開発者として成長するにつれて、「車輪の再発明」をしたい場合があることを学びます。たとえば、バイナリをしきい値サイズ未満に保つ必要がある場合があります。ライブラリを使用すると、アプリケーションのサイズが桁違いに大きくなることがよくあります。「コードを書く必要はありません。ええ、毎回ライブラリをインポートしましょう」とあなたが言ったこととは正反対の議論をするかもしれません。3行のコードを節約するためだけに、ライブラリをインポートしたいですか?ライブラリを追加すると、LOCがそれ以上に増えると思います。重要なのはバランスです。
Lucio Paiva 2017

3
ええと、すべての人がクラウド上で何かを実行しているわけではありません。たとえば、Javaを実行している組み込みシステムはどこにでもあります。自分のコードでJDKを直接使用するという提案を受け入れるつもりだと自分自身に言っていることを考えると、完全に有効なアプローチを提供する回答を批判することにあなたの主張はわかりません。とにかく、意見を議論するのではなく、答えを改善するために厳密にコメントを保持するようにしてください。
Lucio Paiva 2017

1
優れたJDKのみのソリューション。InputStream変数isがそうであるnullかどうかのチェックを追加するだけです。
scrutari 2018

2
いいね。これを使いました。ストリーム/リーダーを閉じることも検討してください。
DIMPLEX

1
@RobertBain回答を編集して、文字セットの警告に関する情報を追加しました。AWSのクラスローダーで何が問題だったのかがわかったらお知らせください。回答に追加することもできます。ありがとう!
LucioPaiva19年

57

Guavaには、ファイルを文字列に読み込むための「toString」メソッドがあります。

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);

このメソッドでは、ファイルがクラスパスにある必要はありません(Jon Skeetの前の回答のように)。


2
または、入力ストリームの場合、グアバにはこれにも適した方法がありますString stringFromStream = CharStreams.toString(new InputStreamReader(resourceAsStream, "UTF-8"));
Eran Medan 2013年

1
これはGuava24.1で非推奨になりました
Andrey

49

yegor256は、Apache CommonsIO使用し優れたソリューションを見つけました。

import org.apache.commons.io.IOUtils;

String text = IOUtils.toString(this.getClass().getResourceAsStream("foo.xml"),
                               "UTF-8");

これが利用できない場合、私はこれよりも「」を好みます
user833970 2015年

12
コンパクトですが、入力ストリームを適切に閉じる必要がありますIOUtils.toString(this.getClass().getResource("foo.xml"), "UTF-8")
ボグダンカルマック2015年

1
このソリューションは、仕事をしない場合、追加してみてくださいgetClassLoader()メソッドチェーンに: String text = IOUtils.toString( getClass().getClassLoader().getResourceAsStream("foo.xml"), StandardCharsets.UTF_8);
Abdull

IOUtilsの別の例:IOUtils.resourceToString("/foo.xml", StandardCharsets.UTF_8);
Alex Rewa

39

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

1
なぜエンコーディングを指定する必要があるのですか、私はそれを取得しません。私がファイルを読んだ場合、私はその中に何が入っているのかが欲しいだけです、それは私のエディタがするようにそれがどんなエンコーディングであるかを理解するはずです。メモ帳または++で開いたときに、使用するエンコードを教えてくれません。私はこのメソッドを使用していて、その後writeStringToFile ...を使用していますが、内容が異なります。クローンファイルに奇妙なトークンが含まれています。エンコーディングを指定する必要がある理由がわかりません。
mmm 2011

11
@Hamidan、適切なエンコーディングの選択は非常に複雑なアルゴリズムです。多くの場合、テキストエディタで実装されますが、正しいエンコーディングを検出できない場合があります。私は、ファイル読み取りAPIが私のファイルを読み取るためにそのような複雑なアルゴリズムを埋め込むことを期待していません。
ヴィンセントロバート

1
@SecretServiceまた、これらのアルゴリズムは、オペレーティングシステムの言語、ロケール、その他の地域設定などの情報を利用します。つまり、エンコーディングを指定せずにファイルを読み取ることは、自分のセットアップでは機能しますが、他の人のセットアップでは機能しない可能性があります。
Feuermurmel 2014

アパッチのfileutilsreadLines(ファイル)&copyURLToFile(URL、tempFile)。
ヤシュ2016

2
リソースがjar内にある場合、これは機能しないと思います。その後、それはファイルではありません。
Ville Oikarinen 2018年

16

Javaから次のコードを使用できます

new String(Files.readAllBytes(Paths.get(getClass().getResource("example.txt").toURI())));

「ファイル」クラスと「パス」クラスを取り込むには、どのインポートステートメントが必要ですか?
スティーブシェラー2016

1
どちらもJDK7 +から入手できるjava.nio.fileパッケージの一部です
Raghu K Nair

1
jarファイル内では機能しません。
解散

15

私はしばしばこの問題を自分で抱えていました。小さなプロジェクトへの依存を避けるために、commonsioなどが必要ないときに小さなユーティリティ関数を書くことがよくあります。ファイルの内容を文字列バッファにロードするコードは次のとおりです。

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());   

その場合、エンコードを指定すること重要です。ファイルをUTF-8で編集してから、jarファイルに入れ、ファイルを開くコンピューターのネイティブファイルエンコードがCP-1251である可能性があるためです(たとえば)。 ; したがって、この場合、ターゲットエンコーディングがわからないため、明示的なエンコーディング情報が重要です。また、charごとにファイルを読み取るループは非効率に見えますが、BufferedReaderで使用されるため、実際には非常に高速です。


4

プロジェクトのsrc / main / resourcesにあるファイルtestcase / foo.jsonなどのプロジェクトリソースから文字列を取得する場合は、次のようにします。

String myString= 
 new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("testcase/foo.json").toURI())));

他のいくつかの例では、getClassLoader()メソッドが欠落していることに注意してください。


2

ApachecommonsのFileUtilsを使用します。readFileToStringメソッドがあります


ファイルは、ファイルであるクラスパスリソースに対してのみ機能します。それらが.jarファイルの要素である場合、またはファットjarの一部である場合は、他のクラスローダー実装の1つではありません。
toolforger

2

私は以下からリソースファイルを読み取るために以下を使用していますclasspath

import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.util.Scanner;

public class ResourceUtilities
{
    public static String resourceToString(String filePath) throws IOException, URISyntaxException
    {
        try (InputStream inputStream = ResourceUtilities.class.getClassLoader().getResourceAsStream(filePath))
        {
            return inputStreamToString(inputStream);
        }
    }

    private static String inputStreamToString(InputStream inputStream)
    {
        try (Scanner scanner = new Scanner(inputStream).useDelimiter("\\A"))
        {
            return scanner.hasNext() ? scanner.next() : "";
        }
    }
}

サードパーティの依存関係は必要ありません。


2

私は愚かなスキャナートリックでakosickiの答えが好きです。これは、Java 8で機能する(実際にはJava 5までさかのぼる)外部依存関係なしで私が見る最も単純なものです。Java 9以降を使用できる場合(Java 9InputStream.readAllBytes()で追加されたため)、さらに簡単な答えは次のとおりです

String text = new String(AppropriateClass.class.getResourceAsStream("foo.txt").readAllBytes());

1

静的インポートのセットを使用すると、Guavaソリューションは非常にコンパクトなワンライナーになります。

toString(getResource("foo.txt"), UTF_8);

次のインポートが必要です。

import static com.google.common.io.Resources.getResource
import static com.google.common.io.Resources.toString
import static java.nio.charset.StandardCharsets.UTF_8

1
package test;

import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        try {
            String fileContent = getFileFromResources("resourcesFile.txt");
            System.out.println(fileContent);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //USE THIS FUNCTION TO READ CONTENT OF A FILE, IT MUST EXIST IN "RESOURCES" FOLDER
    public static String getFileFromResources(String fileName) throws Exception {
        ClassLoader classLoader = Main.class.getClassLoader();
        InputStream stream = classLoader.getResourceAsStream(fileName);
        String text = null;
        try (Scanner scanner = new Scanner(stream, StandardCharsets.UTF_8.name())) {
            text = scanner.useDelimiter("\\A").next();
        }
        return text;
    }
}

1

少なくともApachecommons-io 2.5の時点では、IOUtils.toString()メソッドはURI引数をサポートし、クラスパスのjar内にあるファイルの内容を返します。

IOUtils.toString(SomeClass.class.getResource(...).toURI(), ...)

0

GuavaにはFiles.readLines()、戻り値を1List<String>行ずつ表示する場合もあります。

List<String> lines = Files.readLines(new File("/file/path/input.txt"), Charsets.UTF_8);

テキストファイルから取得する3つの方法(対グアバ対グアバ)を比較するには、ここを参照しください。BufferedReaderFilesResourcesString


Charsetsクラスとは何ですか?ネイティブではありません
e-info128 2017

@ e-info128Charsetsもグアバにあります。これを参照してください:google.github.io/guava/releases/23.0/api/docs
philipjkim

0

これが私のアプローチがうまくいった

public String getFileContent(String fileName) {
    String filePath = "myFolder/" + fileName+ ".json";
    try(InputStream stream = Thread.currentThread().getContextClassLoader().getResourceAsStream(filePath)) {
        return IOUtils.toString(stream, "UTF-8");
    } catch (IOException e) {
        // Please print your Exception
    }
}

2
IOUtilsはどこから来たのですか?ソースは明確に参照する必要があります。
エエカトル

0

ここにreadResource()メソッドを記述して、1回の簡単な呼び出しで実行できるようにしました。Guavaライブラリに依存しますが、他の回答で提案されているJDKのみの方法が好きで、そのように変更すると思います。


0

Guavaを含めると、次のものを使用できます。

String fileContent = Files.asCharSource(new File(filename), Charset.forName("UTF-8")).read();

(他のソリューションはグアバの他の方法に言及しましたが、それらは非推奨です)


0

次のタラは私のために働きます:

compile group: 'commons-io', name: 'commons-io', version: '2.6'

@Value("classpath:mockResponse.json")
private Resource mockResponse;

String mockContent = FileUtils.readFileToString(mockResponse.getFile(), "UTF-8");

0

Java11を使用したソリューションは次の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);
    }
}

0

私はこのようなNO依存性の静的メソッドを作成しました:

import java.nio.file.Files;
import java.nio.file.Paths;

public class ResourceReader {
    public  static String asString(String resourceFIleName) {
        try  {
            return new String(Files.readAllBytes(Paths.get(new CheatClassLoaderDummyClass().getClass().getClassLoader().getResource(resourceFIleName).toURI())));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
class CheatClassLoaderDummyClass{//cheat class loader - for sql file loading
}

0

私はこのタイプのものにApachecommons utilsが好きで、テスト時に、特に/src/test/resourcesユニット/統合テストの一部としてJSONファイルを読み取るために、この正確なユースケース(クラスパスからファイルを読み取る)を広く使用します。例えば

public class FileUtils {

    public static String getResource(String classpathLocation) {
        try {
            String message = IOUtils.toString(FileUtils.class.getResourceAsStream(classpathLocation),
                    Charset.defaultCharset());
            return message;
        }
        catch (IOException e) {
            throw new RuntimeException("Could not read file [ " + classpathLocation + " ] from classpath", e);
        }
    }

}

テストの目的で、をキャッチしIOExceptionてスローするのは良いことですRuntimeException-テストクラスは次のようになります。

    @Test
    public void shouldDoSomething () {
        String json = FileUtils.getResource("/json/input.json");

        // Use json as part of test ...
    }

-2
public static byte[] readResoureStream(String resourcePath) throws IOException {
    ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
    InputStream in = CreateBffFile.class.getResourceAsStream(resourcePath);

    //Create buffer
    byte[] buffer = new byte[4096];
    for (;;) {
        int nread = in.read(buffer);
        if (nread <= 0) {
            break;
        }
        byteArray.write(buffer, 0, nread);
    }
    return byteArray.toByteArray();
}

Charset charset = StandardCharsets.UTF_8;
String content = new   String(FileReader.readResoureStream("/resource/...*.txt"), charset);
String lines[] = content.split("\\n");

あなたの答えに簡単な説明を追加してください。
ニコライミハイロフ2016
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.