ファイルの内容からJava文字列を作成するにはどうすればよいですか?


1513

私はしばらくの間、以下のイディオムを使用しています。そして、少なくとも私がアクセスしたサイトでは、それが最も広く普及しているようです。

Javaでファイルを文字列に読み取るより良い/異なる方法はありますか?

private String readFile(String file) throws IOException {
    BufferedReader reader = new BufferedReader(new FileReader (file));
    String         line = null;
    StringBuilder  stringBuilder = new StringBuilder();
    String         ls = System.getProperty("line.separator");

    try {
        while((line = reader.readLine()) != null) {
            stringBuilder.append(line);
            stringBuilder.append(ls);
        }

        return stringBuilder.toString();
    } finally {
        reader.close();
    }
}

7
誰もがNIOとは非常に簡単な方法で私を説明できますか?それについて読むたびに、チャンネルのn番目の言及で迷子になります:(
OscarRyz 2008年

7
ファイル内の行区切り文字がシステムの行区切り文字と同じである必要はないことは保証されないことを覚えておいてください。
Henrik Paul、

138
最後に適切な試行を挿入して、リーダーを閉じてもらえますか?誰かが実際にこの例を使用して、彼のコードにバグを導入するかもしれません。
Hans-PeterStörr2010年

6
上記のコードには、最後の行に余分な改行文字を追加するバグがあります。if(line = reader.readLine())!= null){stringBuilder.append(line);のようになります。} while(line = reader.readLine())!= null){stringBuilder.append(ls); stringBuilder.append(line); }
ディープ

27
Java 7 byte[] Files.readAllBytes(file);は、「1行」のスキャナーソリューションを提案する人たちに紹介します。閉じる必要はありませんか?
Val

回答:


1535

ファイルからすべてのテキストを読み取る

Java 11は、小さなファイルをとして読み取るためのreadString()メソッドを追加し、改行記号をString保持しています。

String content = Files.readString(path, StandardCharsets.US_ASCII);

Java 7と11の間のバージョンの場合、ユーティリティメソッドにラップされたコンパクトで堅牢なイディオムを次に示します。

static String readFile(String path, Charset encoding) 
  throws IOException 
{
  byte[] encoded = Files.readAllBytes(Paths.get(path));
  return new String(encoded, encoding);
}

ファイルからテキスト行を読み取る

Java 7では、ファイルをテキスト行として読み取る便利なメソッドが追加されましたList<String>。この方法は、行の区切りが各行の終わりから取り除かれるので、「非可逆」です。

List<String> lines = Files.readAllLines(Paths.get(path), encoding);

Java 8はFiles.lines()を生成するメソッドを追加しましたStream<String>。繰り返しになりますが、この方法は行の区切りが取り除かれているため、損失を伴います。IOExceptionファイルの読み取り中にが発生した場合は、チェックされた例外をスローするラムダを受け入れないためUncheckedIOException、にラップされStreamます。

try (Stream<String> lines = Files.lines(path, encoding)) {
  lines.forEach(System.out::println);
}

これにStreamclose()呼び出しが必要です。これはAPIで十分に文書化されておらず、多くの人がメソッドStreamがあることに気づいてさえいないと思いますclose()。必ず図のようにARMブロックを使用してください。

ファイル以外のソースを使用しているlines()場合は、BufferedReader代わりにメソッドを使用できます。

メモリ使用率

改行を保持する最初の方法では、一時的にファイルサイズの数倍のメモリが必要になる可能性があります。これは、生のファイルの内容(バイト配列)とデコードされた文字(エンコードされていてもそれぞれ16ビット)だからです。ファイルの8ビットとして)メモリに一度に常駐します。使用可能なメモリに比べて小さいことがわかっているファイルに適用するのが最も安全です。

2番目の方法である行の読み取りは、デコードのための入力バイトバッファーにファイル全体を含める必要がないため、通常はメモリ効率が向上します。ただし、使用可能なメモリに比べて非常に大きいファイルにはまだ適していません。

大きなファイルを読み取るには、プログラムに別の設計が必要です。プログラムは、ストリームからテキストのチャンクを読み取り、それを処理してから、次に移動し、同じ固定サイズのメモリブロックを再利用します。ここで、「大」はコンピュータの仕様によって異なります。現在、このしきい値は数ギガバイトのRAMになる可能性があります。Stream<String>入力「レコード」がたまたま個々の行である場合、3番目の方法は、aを使用してこれを行う1つの方法です。(readLine()メソッドの使用BufferedReaderは、このアプローチに相当する手続きです。)

文字コード

元の投稿のサンプルに欠けているのは、文字エンコーディングです。プラットフォームのデフォルトがあなたの望むものであるいくつかの特別な場合がありますが、それらはまれであり、あなたはあなたの選択を正当化できるはずです。

このStandardCharsetsクラスは、すべてのJavaランタイムに必要なエンコーディング用のいくつかの定数を定義します。

String content = readFile("test.txt", StandardCharsets.UTF_8);

プラットフォームのデフォルトはCharsetクラス自体から利用できます。

String content = readFile("test.txt", Charset.defaultCharset());

注:この回答は、主にJava 6バージョンを置き換えます。Java 7のユーティリティはコードを安全に簡素化し、マップされたバイトバッファーを使用していた古い回答は、マップされたバッファーがガベージコレクションされるまで、読み取られたファイルが削除されないようにしました。この回答の「編集済み」リンクから古いバージョンを表示できます。


3
技術的には、時間と空間ではO(n)です。定性的には、文字列の不変性の要件により、メモリの負荷はかなり高くなります。一時的に、メモリ内にcharデータの2つのコピーと、エンコードされたバイト用のスペースがあります。いくつかのシングルバイトエンコーディングを想定すると、ファイル内の各文字に(一時的に)5バイトのメモリが必要になります。質問は特に文字列を要求するので、それは私が示すものですが、「デコード」によって返されるCharBufferで作業できる場合、メモリ要件ははるかに少なくなります。時間的には、コアJavaライブラリの方が速く見つかるとは思いません。
エリクソン2009年

5
タイプミスの可能性?NIOには、java.nio.charset.CharsetというCharset(CharSetではない)クラスがあります。これはCharSetの本来の姿でしょうか?
ジョナサンライト

31
注:少しそのコードを実行した後、このメソッドで読み取った直後にファイルを確実に削除できないことがわかりました。この問題に関連している可能性があります:bugs.sun.com/bugdatabase/view_bug.do ? bug_id=4715154?私はようやくこのバグに悩まされないジョン・スキートの提案に行きました。とにかく、念のために他の人のために情報を伝えたかっただけです。
SébastienNussbaumer

5
@SébastienNussbaumer:私もこの問題にぶつかりました。バグが「修正されない」とマークされていることは驚くべきことです。これは基本的にFileChannel#map、これが一般に使用できないことを意味します。
Joonas Pulakka、2010年

4
@SébastienNussbaumer:Oracle / Sun Bug Databaseからバグが削除されました:「このバグは利用できません。」Googleはwebcache.googleusercontent.com/search?q=cache:bugs.sun.com/…で
bobndrew

351

外部ライブラリを使用する場合は、Apache Commons IO(200KB JAR)を確認してください。それは含まれていorg.apache.commons.io.FileUtils.readFileToString()ますが、全体読み取ることができる方法FileにはString1行のコードでは。

例:

import java.io.*;
import java.nio.charset.*;
import org.apache.commons.io.*;

public String readFile() throws IOException {
    File file = new File("data.txt");
    return FileUtils.readFileToString(file, StandardCharsets.UTF_8);
}

提供されたURLにそのメソッドが見つかりません。
OscarRyz 2008年

2
クラスorg.apache.commons.io.FileUtilsにあります
Cyrille Ka

2
私もFileUtilsを使用していますが、FileUtilsを使用するか、受け入れられたnioの回答のどちらを使用するほうがよいのでしょうか。
ギヨーム

4
@ギラウム:最大の問題は、サードパーティのライブラリに依存することに抵抗がないかどうかです。プロジェクトにCommons IOまたはGuavaがある場合は、それを使用します(コードを単純にするためだけです。それ以外の場合は、目立った違いはありません)。
Jonik 2013

183

に基づく非常に無駄のないソリューションScanner

Scanner scanner = new Scanner( new File("poem.txt") );
String text = scanner.useDelimiter("\\A").next();
scanner.close(); // Put this call in a finally block

または、文字セットを設定する場合:

Scanner scanner = new Scanner( new File("poem.txt"), "UTF-8" );
String text = scanner.useDelimiter("\\A").next();
scanner.close(); // Put this call in a finally block

または、try-with-resourcesブロックを使用するとscanner.close()、次のようになります。

try (Scanner scanner = new Scanner( new File("poem.txt"), "UTF-8" )) {
    String text = scanner.useDelimiter("\\A").next();
}

Scannerコンストラクタはをスローできることに注意してくださいIOException。およびインポートすることを忘れないでくださいjava.iojava.util

出典:Pat Niemeyerのブログ


4
\\ Aが機能するのは、「他のファイルの先頭」がないため、実際には最後のトークンを読み取っています...これも最初のトークンです。\\ Zで試したことがありません。また、Files、InputStreams、channelsなど、Readableであれば何でも読み取ることができることに注意してください。このコードを使用して、Eclipseの表示ウィンドウから読み取ることがあります。はい、クラスパスは私を混乱させます。
Pablo Grisafi、2011

1
投稿者として、ファイルが適切に閉じているかどうか、いつ閉じるかは本当にわからない、と言うことができます...これを製品コードで書くことはなく、テストまたはデバッグにのみ使用します。
Pablo Grisafi

2
1024文字の制限があると思います
Whimusical

20
ScannerはCloseableを実装しています(ソースでcloseを呼び出します)。そのため、エレガントではありますが、実際にはワンライナーではありません。バッファーのデフォルトサイズは1024ですが、スキャナーは必要に応じてサイズを増やします(Scanner#makeSpace()を参照)
earcam

8
これは、空のファイルにjava.util.NoSuchElementException
SpaceTrucker 2013

117
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;

String content = new String(Files.readAllBytes(Paths.get("readMe.txt")), StandardCharsets.UTF_8);

Java 7以降では、この方法で実行できます。


これは答えとして受け入れられるべきです-単一行、外部ライブラリはありません。
チェリー

これにより、ファイルに存在しない場合でも、末尾に改行文字が追加されました
Stefan Haberl

79

サードパーティのライブラリを含まない代替手段(Commons I / Oなど)を探している場合は、Scannerクラスを使用できます。

private String readFile(String pathname) throws IOException {

    File file = new File(pathname);
    StringBuilder fileContents = new StringBuilder((int)file.length());        

    try (Scanner scanner = new Scanner(file)) {
        while(scanner.hasNextLine()) {
            fileContents.append(scanner.nextLine() + System.lineSeparator());
        }
        return fileContents.toString();
    }
}

2
これが最良の方法だと思います。java.sun.com/docs/books/tutorial/essential/io/scanning.htmlを
Tarski

3
文字列を受け入れるScannerコンストラクタは、文字列を読み取るファイルの名前としてではなく、スキャンするテキストとして扱います。私はいつもその間違いを犯します。:-/
アランムーア

@アラン、良いキャッチ。私はそれを修正するためにドンの答えを少し編集しました(私は願っています)。
Jonik、2010

3
fileContents.append(scanner.nextLine())。append(lineSeparator);
ban-geoengineering 2013年

1
初期化ステートメントをに変更しますScanner scanner = new Scanner((Readable) new BufferedReader(new FileReader(file)));。そうしないと、ファイルの一部しかキャプチャできません。
魏ヤン

71

Guavaには、Willi aus Rohrが言及したCommons IOUtilsのメソッドと同様のメソッドがあります。

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

// ...

String text = Files.toString(new File(path), Charsets.UTF_8);

PiggyPigletによるEDIT
Files#toStringは非推奨で、Octobor 2019の削除が予定されています。代わりに Files.asCharSource(new File(path), StandardCharsets.UTF_8).read();

オスカーレイエスによる編集

これは、引用されたライブラリの(簡略化された)基礎となるコードです。

InputStream in = new FileInputStream(file);
byte[] b  = new byte[file.length()];
int len = b.length;
int total = 0;

while (total < len) {
  int result = in.read(b, total, len - total);
  if (result == -1) {
    break;
  }
  total += result;
}

return new String( b , Charsets.UTF_8 );

編集(Jonik):上記は、最近のGuavaバージョンのソースコードと一致しません。現在のソースについては、com.google.common.ioパッケージのクラスFilesCharStreamsByteSource、およびCharSourceを参照してください。


このコードはlongからintにキャストするため、大きなファイルでいくつかのクレイジーな動作を引き起こす可能性があります。余分なスペースがあり、どこで入力ストリームを閉じますか?
Mohamed Taher Alrefaie 2013

@MTA:ストリーム閉じています。CharSourceでの使用に注意Closerしてください。回答のコードは、実際の現在のGuavaソースではありません。
Jonik

54
import java.nio.file.Files;

……

 String readFile(String filename) {
            File f = new File(filename);
            try {
                byte[] bytes = Files.readAllBytes(f.toPath());
                return new String(bytes,"UTF-8");
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return "";
    }

6
またはさらに単純な:new String(Files.readAllBytes(FileSystems.getDefault().getPath( filename)));

12
またはnew String(Files.readAllBytes(Paths.get(filename)));:-)
assafmo 2013

1
うまくプレイされており、次の人であるグーグルを救うためには、Paths1.7 +が現状のままですFileSystems。(Dang it!)
ruffin 2013

4
それは残念ですが、この回答には投票数がありません。私は、テキストファイルを文字列に変換する最も簡単な方法を探していました。これで、上下にスクロールしなければ、見逃していたでしょう。OPは、この回答を受け入れてトップに移動することを検討する必要があります。
ソーン

@Thornこの回答には恐ろしいエラー処理があります。本番コードでこのメソッドを使用しないでください。
xehpuk 2015

51

文字列処理(並列処理)が必要な場合、Java 8には優れたStream APIがあります。

String result = Files.lines(Paths.get("file.txt"))
                    .parallel() // for parallel processing 
                    .map(String::trim) // to change line   
                    .filter(line -> line.length() > 2) // to filter some lines by a predicate                        
                    .collect(Collectors.joining()); // to join lines

Oracle Java SE 8のダウンロードページsample/lambda/BulkDataOperationsからダウンロードできるJDKサンプルには、他の例が用意されています。

別のワンライナーの例

String out = String.join("\n", Files.readAllLines(Paths.get("file.txt")));

.parallel()は、行を読み取った後、またはその前に発生しますか?
イストヴァン

端末操作collect(...)が呼び出されてから、実際の作業が始まります。ストリームは1行ずつ遅延して入力されます。処理(フィルタリングやマッピングなど)の前にメモリ内のファイル全体を読み取る必要はありません。
Andrei N

空でない行を選択する前にトリムしますか?
するThorbjörnRavnアンデルセン

50

そのコードは改行を正規化しますが、これは本当にやりたいことかもしれませんし、そうでないかもしれません。

これを行わない代替方法を以下に示します。これは、NIOコードよりも(IMO)の方が理解しやすいです(ただし、それでもが使用されますjava.nio.charset.Charset)。

public static String readFile(String file, String csName)
            throws IOException {
    Charset cs = Charset.forName(csName);
    return readFile(file, cs);
}

public static String readFile(String file, Charset cs)
            throws IOException {
    // No real need to close the BufferedReader/InputStreamReader
    // as they're only wrapping the stream
    FileInputStream stream = new FileInputStream(file);
    try {
        Reader reader = new BufferedReader(new InputStreamReader(stream, cs));
        StringBuilder builder = new StringBuilder();
        char[] buffer = new char[8192];
        int read;
        while ((read = reader.read(buffer, 0, buffer.length)) > 0) {
            builder.append(buffer, 0, read);
        }
        return builder.toString();
    } finally {
        // Potential issue here: if this throws an IOException,
        // it will mask any others. Normally I'd use a utility
        // method which would log exceptions and swallow them
        stream.close();
    }        
}

1
この古いコメントを復活させたことを許してください。「file」と呼ばれるStringオブジェクトを渡すつもりでしたか、それともFileオブジェクトである必要がありますか?
ブライアンラーソン

28

ファイルをディスクまたはネットワークから文字列として読み取るためのすべての可能な方法を収集しました。

  • グアバ:グーグルを使ったクラスResourcesFiles

    static Charset charset = com.google.common.base.Charsets.UTF_8;
    public static String guava_ServerFile( URL url ) throws IOException {
        return Resources.toString( url, charset );
    }
    public static String guava_DiskFile( File file ) throws IOException {
        return Files.toString( file, charset );
    }

  • APACHE-クラスIOUtils、FileUtilsを使用する一般的なIO

    static Charset encoding = org.apache.commons.io.Charsets.UTF_8;
    public static String commons_IOUtils( URL url ) throws IOException {
        java.io.InputStream in = url.openStream();
        try {
            return IOUtils.toString( in, encoding );
        } finally {
            IOUtils.closeQuietly(in);
        }
    }
    public static String commons_FileUtils( File file ) throws IOException {
        return FileUtils.readFileToString( file, encoding );
        /*List<String> lines = FileUtils.readLines( fileName, encoding );
        return lines.stream().collect( Collectors.joining("\n") );*/
    }

  • Stream APIを使用したJava 8 BufferReader

    public static String streamURL_Buffer( URL url ) throws IOException {
        java.io.InputStream source = url.openStream();
        BufferedReader reader = new BufferedReader( new InputStreamReader( source ) );
        //List<String> lines = reader.lines().collect( Collectors.toList() );
        return reader.lines().collect( Collectors.joining( System.lineSeparator() ) );
    }
    public static String streamFile_Buffer( File file ) throws IOException {
        BufferedReader reader = new BufferedReader( new FileReader( file ) );
        return reader.lines().collect(Collectors.joining(System.lineSeparator()));
    }

  • 正規表現を使用したスキャナークラス\A。入力の最初と一致します。

    static String charsetName = java.nio.charset.StandardCharsets.UTF_8.toString();
    public static String streamURL_Scanner( URL url ) throws IOException {
        java.io.InputStream source = url.openStream();
        Scanner scanner = new Scanner(source, charsetName).useDelimiter("\\A");
        return scanner.hasNext() ? scanner.next() : "";
    }
    public static String streamFile_Scanner( File file ) throws IOException {
        Scanner scanner = new Scanner(file, charsetName).useDelimiter("\\A");
        return scanner.hasNext() ? scanner.next() : "";
    }

  • Java 7(java.nio.file.Files.readAllBytes

    public static String getDiskFile_Java7( File file ) throws IOException {
        byte[] readAllBytes = java.nio.file.Files.readAllBytes(Paths.get( file.getAbsolutePath() ));
        return new String( readAllBytes );
    }

  • BufferedReaderを使用してInputStreamReader

    public static String getDiskFile_Lines( File file ) throws IOException {
        StringBuffer text = new StringBuffer();
        FileInputStream fileStream = new FileInputStream( file );
        BufferedReader br = new BufferedReader( new InputStreamReader( fileStream ) );
        for ( String line; (line = br.readLine()) != null; )
            text.append( line + System.lineSeparator() );
        return text.toString();
    }

上記のメソッドにアクセスするmainメソッドの例。

public static void main(String[] args) throws IOException {
    String fileName = "E:/parametarisation.csv";
    File file = new File( fileName );

    String fileStream = commons_FileUtils( file );
            // guava_DiskFile( file );
            // streamFile_Buffer( file );
            // getDiskFile_Java7( file );
            // getDiskFile_Lines( file );
    System.out.println( " File Over Disk : \n"+ fileStream );


    try {
        String src = "https://code.jquery.com/jquery-3.2.1.js";
        URL url = new URL( src );

        String urlStream = commons_IOUtils( url );
                // guava_ServerFile( url );
                // streamURL_Scanner( url );
                // streamURL_Buffer( url );
        System.out.println( " File Over Network : \n"+ urlStream );
    } catch (MalformedURLException e) {
        e.printStackTrace();
    }
}

@見る


26

テキストファイルの場合は、Apache commons-ioを使用しないでください。

以下の方法があります

public static String readFileToString(File file) throws IOException

行をリストとして使用したい場合

public static List<String> readLines(File file) throws IOException

25

JDK 11以降:

String file = ...
Path path = Paths.get(file);
String content = Files.readString(path);
// Or readString(path, someCharset), if you need a Charset different from UTF-8

なぜ、なぜ、2018年にデフォルトの文字セットに依存する新しいメソッドを導入するのですか?
mryan 2018

2
@mryanこのメソッドは、デフォルトのシステム文字セットに依存しません。デフォルトはUTF-8ですが、問題ありません。
leventov 2018

@leventovあなたは正しい!Files.readAllLinesも同様です。これにより、files APIは古いメソッドとあまり一致しなくなりますが、より良い方法です:)
mryan

17

ファイルをバイナリとして読み取り、最後に変換するには

public static String readFileAsString(String filePath) throws IOException {
    DataInputStream dis = new DataInputStream(new FileInputStream(filePath));
    try {
        long len = new File(filePath).length();
        if (len > Integer.MAX_VALUE) throw new IOException("File "+filePath+" too large, was "+len+" bytes.");
        byte[] bytes = new byte[(int) len];
        dis.readFully(bytes);
        return new String(bytes, "UTF-8");
    } finally {
        dis.close();
    }
}

16

Java 7では、これがUTF-8ファイルを読み取るための私の推奨オプションです。

String content = new String(Files.readAllBytes(Paths.get(filename)), "UTF-8");

Java 7以降、JDK java.nio.fileには多くのショートカットを提供する新しいAPIが含まれているため、単純なファイル操作にサードパーティのライブラリが必ずしも必要ではありません。


15

Javaは、非常に一般的で柔軟であることを目指しています。その結果、スクリプト言語で比較的単純なもの(open(file).read()Python ではコードが " "に置き換えられます)は、はるかに複雑になります。(Willi aus Rohrが言及したような)外部ライブラリを使用することを除いて、それを行うためのより短い方法はないようです。あなたのオプション:

  • 外部ライブラリを使用します。
  • このコードをすべてのプロジェクトにコピーします。
  • 頻繁に使用する関数を含む独自のミニライブラリを作成します。

依存関係が最も少ないので、おそらく2番目の方法が最適です。


4
うん。「高」レベルの言語に別の意味を持たせます。JavaはCと比較して高レベルですが、PythonまたはRubyと比較すると低い
OscarRyz 2008年

3
便利なメソッドにJavaは、高レベルの抽象化での長さであることに同意したが、短い
ドナル・

3
確かに、Javaには非常に多くの方法でファイルを処理する方法があり、それらの多くは複雑に見えます。しかし、これは私たちがより高いレベルの言語で持っているものにかなり近いです:byte[] bytes = Files.readAllBytes(someFile.toPath());
Thorn

11

JDK 8以降の使用:

外部ライブラリは使用されていません

ファイルのコンテンツから新しいStringオブジェクトを作成できます(java.nio.fileパッケージのクラスを使用):

public String readStringFromFile(String filePath) throws IOException {
    String fileContent = new String(Files.readAllBytes(Paths.get(filePath)));
    return fileContent;
}

作成したMoritz Petersen回答の複製:String content = new String(Files.readAllBytes(Paths.get(filename))、 "UTF-8");
Jean-Christophe Blanchard、

8

行変数のスコープを制限するために、whileループの代わりにforループを使用する同じテーマのバリエーションがあります。それが「より良い」かどうかは、個人的な好みの問題です。

for(String line = reader.readLine(); line != null; line = reader.readLine()) {
    stringBuilder.append(line);
    stringBuilder.append(ls);
}

3
これにより、改行がデフォルトの改行選択に変更されます。これは望ましい場合もあれば、意図しない場合もあります。
Peter Lawrey、2010

line変数のスコープを狭めることがポイントであったため、この回答への編集をロールバックしました。編集はそれを2回宣言しましたが、これはコンパイルエラーになります。
Dan Dyer 2013

7

Filesクラスにアクセスできない場合は、ネイティブソリューションを使用できます。

static String readFile(File file, String charset)
        throws IOException
{
    FileInputStream fileInputStream = new FileInputStream(file);
    byte[] buffer = new byte[fileInputStream.available()];
    int length = fileInputStream.read(buffer);
    fileInputStream.close();
    return new String(buffer, 0, length, charset);
}

呼び出す文字セットの例?
Thufir 2018

4

使用した柔軟なソリューションIOUtilsをアパッチからコモンズ-IOとの組み合わせでにStringWriter

Reader input = new FileReader();
StringWriter output = new StringWriter();
try {
  IOUtils.copy(input, output);
} finally {
  input.close();
}
String fileContents = output.toString();

たとえば、URLから読み取る場合など、ファイルだけでなく、任意のリーダーまたは入力ストリームで動作します。


3

fileInputStream.available()返される整数を使用する場合は実際のファイルサイズを表す必要はなく、システムがIOをブロックせずにストリームから読み取ることができると予想されるバイト数に注意してください。安全でシンプルな方法は次のようになります

public String readStringFromInputStream(FileInputStream fileInputStream) {
    StringBuffer stringBuffer = new StringBuffer();
    try {
        byte[] buffer;
        while (fileInputStream.available() > 0) {
            buffer = new byte[fileInputStream.available()];
            fileInputStream.read(buffer);
            stringBuffer.append(new String(buffer, "ISO-8859-1"));
        }
    } catch (FileNotFoundException e) {
    } catch (IOException e) { }
    return stringBuffer.toString();
}

このアプローチは、UTF-8のようなマルチバイト文字エンコーディングに適していないことを考慮してください。


1
このコードは予期しない結果をもたらす可能性があります。メソッドのドキュメントによるavailable()と、メソッドが0を返した場合にファイルの終わりに到達する保証はありません。その場合、ファイルが不完全になる可能性があります。さらに悪いことに、実際に読み取られたバイト数はavailable()、によって返される値よりも小さい場合があり、その場合、出力が破損します。
wau

3

これはメソッドを使用してRandomAccessFile.readFullyおり、JDK 1.0から利用できるようです!

public static String readFileContent(String filename, Charset charset) throws IOException {
    RandomAccessFile raf = null;
    try {
        raf = new RandomAccessFile(filename, "r");
        byte[] buffer = new byte[(int)raf.length()];
        raf.readFully(buffer);
        return new String(buffer, charset);
    } finally {
        closeStream(raf);
    }
} 


private static void closeStream(Closeable c) {
    if (c != null) {
        try {
            c.close();
        } catch (IOException ex) {
            // do nothing
        }
    }
}

3

あなたはスキャナーとファイルクラス、数行のソリューションを試すことができます

 try
{
  String content = new Scanner(new File("file.txt")).useDelimiter("\\Z").next();
  System.out.println(content);
}
catch(FileNotFoundException e)
{
  System.out.println("not found!");
}

3

java.nio.Filesファイルのすべての行を読み取るユーザー。

public String readFile() throws IOException {
        File fileToRead = new File("file path");
        List<String> fileLines = Files.readAllLines(fileToRead.toPath());
        return StringUtils.join(fileLines, StringUtils.EMPTY);
}

3
public static String slurp (final File file)
throws IOException {
    StringBuilder result = new StringBuilder();

    BufferedReader reader = new BufferedReader(new FileReader(file));

    try {
        char[] buf = new char[1024];

        int r = 0;

        while ((r = reader.read(buf)) != -1) {
            result.append(buf, 0, r);
        }
    }
    finally {
        reader.close();
    }

    return result.toString();
}

これには、プラットフォームのデフォルトのエンコーディングを使用する不便なosがあると思います。とにかく+1 :)
OscarRyz

7
finallyブロックは、tryブロックで定義された変数を認識していないようです。javac 1.6.0_21はエラーをスローしますcannot find symbol
ceving

独自のコードを試したことはありますか?リーダーをtry / catchブロックで定義したので、finallyブロックではアクセスできません。
mauron85 2018年

2

他のエントリにはまだコメントできないので、ここに残しておきます。

ここでの最良の答えの1つ(https://stackoverflow.com/a/326448/1521167):

private String readFile(String pathname) throws IOException {

File file = new File(pathname);
StringBuilder fileContents = new StringBuilder((int)file.length());
Scanner scanner = new Scanner(file);
String lineSeparator = System.getProperty("line.separator");

try {
    while(scanner.hasNextLine()) {        
        fileContents.append(scanner.nextLine() + lineSeparator);
    }
    return fileContents.toString();
} finally {
    scanner.close();
}
}

まだ1つの欠陥があります。これは常に文字列の最後に改行文字を置きます。これはいくつかの奇妙なバグを引き起こす可能性があります。私の提案は、次のように変更することです。

    private String readFile(String pathname) throws IOException {
    File file = new File(pathname);
    StringBuilder fileContents = new StringBuilder((int) file.length());
    Scanner scanner = new Scanner(new BufferedReader(new FileReader(file)));
    String lineSeparator = System.getProperty("line.separator");

    try {
        if (scanner.hasNextLine()) {
            fileContents.append(scanner.nextLine());
        }
        while (scanner.hasNextLine()) {
            fileContents.append(lineSeparator + scanner.nextLine());
        }
        return fileContents.toString();
    } finally {
        scanner.close();
    }
}

最初のケースでは、最後に余分な改行を追加する場合があります。2番目のケースでは、1つを省略している可能性があります。したがって、どちらも同じように間違っています。この記事を
Patrick Parker

2

スキャナーの後にCtrl + Fを押すと、スキャナーソリューションもリストに表示されるはずです。最も読みやすい方法では、次のようになります。

public String fileToString(File file, Charset charset) {
  Scanner fileReader = new Scanner(file, charset);
  fileReader.useDelimiter("\\Z"); // \Z means EOF.
  String out = fileReader.next();
  fileReader.close();
  return out;
}

Java 7以降を使用している場合(そして本当にそうする必要がある場合)、コードを読みやすくするためにtry-with-resourcesの使用を検討してください。すべてを散らかしているドットクローズのものはもうありません。しかし、それは主に文体の選択です。

私はこれを主に補完主義のために投稿しています。なぜなら、これをたくさん行う必要がある場合、java.nio.file.Filesにはより適切に機能するものがあるはずだからです。

私の提案は、Files#readAllBytes(Path)を使用してすべてのバイトを取得し、それを新しいString(byte [] Charset)にフィードして、信頼できるストリングを取得することです。Charsetsは一生あなたにとって意地悪ですので、今はこのことに注意してください。

他の人たちはコードやものを与えてくれました、そして私は彼らの栄光を盗みたくありません。;)



2

また、ファイルがjar内にある場合は、これを使用することもできます。

public String fromFileInJar(String path) {
    try ( Scanner scanner 
            = new Scanner(getClass().getResourceAsStream(path))) {
        return scanner.useDelimiter("\\A").next();
    }
}

/ たとえば、jarが次の場合、パスは

my.jar/com/some/thing/a.txt

次に、次のように呼び出します。

String myTxt = fromFileInJar("/com/com/thing/a.txt");

2

1行(Java 8)では、読者がいると仮定します。

String sMessage = String.join("\n", reader.lines().collect(Collectors.toList()));

2

@ erickson`の答えに基づいて、あなたは使うことができます:

public String readAll(String fileName) throws IOException {
    List<String> lines = Files.readAllLines(new File(fileName).toPath());
    return String.join("\n", lines.toArray(new String[lines.size()]));
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.