用 Java 读取纯文本文件

It seems there are different ways to read and write data of files in Java.

I want to read ASCII data from a file. What are the possible ways and their differences?

转载于:https://stackoverflow.com/questions/4716503/reading-a-plain-text-file-in-java

csdnceshi61
derek5. This is the simplest way to do this: mkyong.com/java/…
5 年多之前 回复
csdnceshi56
lrony* it's so interesting that there is nothing like "read()" in python , to read the whole file to a string
接近 6 年之前 回复
weixin_41568134
MAO-EYE Without loops: {{{ Scanner sc = new Scanner(file, "UTF-8"); sc.useDelimiter("$^"); // regex matching nothing String text = sc.next(); sc.close(); }}}
6 年多之前 回复
csdnceshi75
衫裤跑路 I also disagree with closing as "not constructive". Fortunately, this could well be closed as duplicate. Good answers e.g. in How to create a String from the contents of a file?, What is simplest way to read a file into String?, What are the simplest classes for reading files?
6 年多之前 回复

24个回答

ASCII is a TEXT file so you would use Readers for reading. Java also supports reading from a binary file using InputStreams. If the files being read are huge then you would want to use a BufferedReader on top of a FileReader to improve read performance.

Go through this article on how to use a Reader

I'd also recommend you download and read this wonderful (yet free) book called Thinking In Java

In Java 7:

new String(Files.readAllBytes(...))

(docs) or

Files.readAllLines(...)

(docs)

In Java 8:

Files.lines(..).forEach(...)

(docs)

csdnceshi79
python小菜 by the way the link to the book "Thinking In Java" is no longer working!
2 年多之前 回复
csdnceshi50
三生石@ My original formulation is not bulletproof, @KlitosKyriacou. The point is that forEach does not guarantee any order and the reason is easy parallelization. If order is to be preserved, use forEachOrdered.
4 年多之前 回复
weixin_41568174
from.. this is interesting, but can you quote from the docs where it says that Files.lines(...).forEach(...) is executed in parallel? I thought this was only the case when you explicitly make the stream parallel using Files.lines(...).parallel().forEach(...).
4 年多之前 回复
csdnceshi50
三生石@ Files.lines(…).forEach(…) does not preserve order of lines but is executed in parallel, @Dash. If the order is important, you can use Files.lines(…).forEachOrdered(…), which should preserve the order (did not verify though).
5 年多之前 回复
csdnceshi63
elliott.david not sure. Either read the javadoc or try it out.
接近 6 年之前 回复
csdnceshi61
derek5. Will the line order be preserved when using "Files.lines(..).forEach(...)". My understanding is that the order will be arbitrary after this operation.
接近 6 年之前 回复
weixin_41568134
MAO-EYE I guess @Vlad is referring to the method of reading entire file into memory explained here java2s.com/Tutorial/Java/0180__File/…
大约 6 年之前 回复
csdnceshi56
lrony* Picking a Reader really depends on what you need the content of the file for. If the file is small(ish) and you need it all, it's faster (benchmarked by us: 1.8-2x) to just use a FileReader and read everything (or at least large enough chunks). If you're processing it line by line then go for the BufferedReader.
接近 7 年之前 回复

My favorite way to read a small file is to use a BufferedReader and a StringBuilder. It is very simple and to the point (though not particularly effective, but good enough for most cases):

BufferedReader br = new BufferedReader(new FileReader("file.txt"));
try {
    StringBuilder sb = new StringBuilder();
    String line = br.readLine();

    while (line != null) {
        sb.append(line);
        sb.append(System.lineSeparator());
        line = br.readLine();
    }
    String everything = sb.toString();
} finally {
    br.close();
}

Some has pointed out that after Java 7 you should use try-with-resources (i.e. auto close) features:

try(BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
    StringBuilder sb = new StringBuilder();
    String line = br.readLine();

    while (line != null) {
        sb.append(line);
        sb.append(System.lineSeparator());
        line = br.readLine();
    }
    String everything = sb.toString();
}

When I read strings like this, I usually want to do some string handling per line anyways, so then I go for this implementation.

Though if I want to actually just read a file into a String, I always use Apache Commons IO with the class IOUtils.toString() method. You can have a look at the source here:

http://www.docjar.com/html/api/org/apache/commons/io/IOUtils.java.html

FileInputStream inputStream = new FileInputStream("foo.txt");
try {
    String everything = IOUtils.toString(inputStream);
} finally {
    inputStream.close();
}

And even simpler with Java 7:

try(FileInputStream inputStream = new FileInputStream("foo.txt")) {     
    String everything = IOUtils.toString(inputStream);
    // do something with everything string
}
csdnceshi52
妄徒之命 please remove this while (line != null)
接近 3 年之前 回复
csdnceshi72
谁还没个明天 why do you need sb.toString()? what is the type of sb which needs to be stringified?
3 年多之前 回复
weixin_41568131
10.24 shouldnt we close file input stream in last one you showed? I think its better to close the file input since there might be starters also here.
接近 4 年之前 回复
csdnceshi69
YaoRaoLov there is no need to use readers directly and also no need for ioutils. java7 has built in methods to read an entire file/all lines: See docs.oracle.com/javase/7/docs/api/java/nio/file/… and docs.oracle.com/javase/7/docs/api/java/nio/file/…
6 年多之前 回复
csdnceshi59
ℙℕℤℝ I haven't added exception handling intentionally as you as the developer should always do the error handling that is proper for your application. Your compiler will assist those that does not see this themselves.
6 年多之前 回复
csdnceshi51
旧行李 Same consideration should be applied within finally too.
6 年多之前 回复
csdnceshi51
旧行李 FileReader may throw FileNotFoundException and BufferedRead may throw IOException so you have to catch them.
6 年多之前 回复
csdnceshi59
ℙℕℤℝ I added your change to my example.
大约 7 年之前 回复
csdnceshi54
hurriedly% For performance always call sb.append('\n') in preference to sb.append("\n") as a char is appended to the StringBuilder faster than a String
大约 7 年之前 回复
csdnceshi54
hurriedly% Similar to Apache Common IO IOUtils#toString() is sun.misc.IOUtils#readFully(), which is included in the Sun/Oracle JREs.
大约 7 年之前 回复
csdnceshi78
程序go I feel it is better to explicitly give the encoding option and use the FileInputStream rather than directly the FileReader ? See this question too stackoverflow.com/questions/696626/… `reader = new InputStreamReader(new FileInputStream("<filePath>", "UTF-8");
大约 7 年之前 回复
csdnceshi74
7*4 I've made a small adjustment to stop adding a newline ( \n ) if the last line is reached. code while (line != null) { sb.append(line); line = br.readLine(); // Only add new line when curline is NOT the last line.. if(line != null) { sb.append("\n"); } }code
7 年多之前 回复

The easiest way is to use the Scanner class in Java and the FileReader object. Simple example:

Scanner in = new Scanner(new FileReader("filename.txt"));

Scanner has several methods for reading in strings, numbers, etc... You can look for more information on this on the Java documentation page.

For example reading the whole content into a String:

StringBuilder sb = new StringBuilder();
while(in.hasNext()) {
    sb.append(in.next());
}
in.close();
outString = sb.toString();

Also if you need a specific encoding you can use this instead of FileReader:

new InputStreamReader(new FileInputStream(fileUtf8), StandardCharsets.UTF_8)
weixin_41568184
叼花硬汉 Must Surround it with try Catch
大约 4 年之前 回复
csdnceshi66
必承其重 | 欲带皇冠 But much easier to use than BufferedReader
接近 6 年之前 回复
csdnceshi61
derek5. not so efficient like BufferedReader
接近 6 年之前 回复
csdnceshi65
larry*wei while (in.hasNext()) { System.out.println (in.next()); }
6 年多之前 回复

Here are the three working and tested methods:

Using BufferedReader

package io;
import java.io.*;
public class ReadFromFile2 {
    public static void main(String[] args)throws Exception {
        File file = new File("C:\\Users\\pankaj\\Desktop\\test.java");
        BufferedReader br = new BufferedReader(new FileReader(file));
        String st;
        while((st=br.readLine()) != null){
            System.out.println(st);
        }
    }
}

Using Scanner

package io;

import java.io.File;
import java.util.Scanner;

public class ReadFromFileUsingScanner {
    public static void main(String[] args) throws Exception {
        File file = new File("C:\\Users\\pankaj\\Desktop\\test.java");
        Scanner sc = new Scanner(file);
        while(sc.hasNextLine()){
            System.out.println(sc.nextLine());
        }
    }
}

Using FileReader

package io;
import java.io.*;
public class ReadingFromFile {

    public static void main(String[] args) throws Exception {
        FileReader fr = new FileReader("C:\\Users\\pankaj\\Desktop\\test.java");
        int i;
        while ((i=fr.read()) != -1){
            System.out.print((char) i);
        }
    }
}

Read the entire file without a loop using the Scanner class

package io;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;

public class ReadingEntireFileWithoutLoop {

    public static void main(String[] args) throws FileNotFoundException {
        File file = new File("C:\\Users\\pankaj\\Desktop\\test.java");
        Scanner sc = new Scanner(file);
        sc.useDelimiter("\\Z");
        System.out.println(sc.next());
    }
}
csdnceshi65
larry*wei What about java.nio.file.Files? We can now just use readAllLines, readAllBytes, and lines.
接近 3 年之前 回复
csdnceshi74
7*4 How to give path if the folders are present inside the project?
3 年多之前 回复

This is basically the exact same as Jesus Ramos' answer, except with File instead of FileReader plus iteration to step through the contents of the file.

Scanner in = new Scanner(new File("filename.txt"));

while (in.hasNext()) { // Iterates each line in the file
    String line = in.nextLine();
    // Do something with line
}

in.close(); // Don't forget to close resource leaks

... throws FileNotFoundException

weixin_41568183
零零乙 File vs FileReader: With a FileReader, the file must exist and operating system permissions must permit access. With a File, it is possible to test those permissions or check if the file is a directory. File has useful functions: isFile(), isDirectory(), listFiles(), canExecute(), canRead(), canWrite(), exists(), mkdir(), delete(). File.createTempFile() writes to the system default temp directory. This method will return a file object that can be used to open FileOutputStream objects, etc. source
3 年多之前 回复

Here is a simple solution:

String content;

content = new String(Files.readAllBytes(Paths.get("sample.txt")));
csdnceshi60
℡Wang Yan The best and simplest.
接近 2 年之前 回复
csdnceshi69
YaoRaoLov Jr, elegant and simple
2 年多之前 回复
weixin_41568174
from.. This is mentioned in the accepted answer.
5 年多之前 回复

This might not be the exact answer to the question. It's just another way of reading a file where you do not explicitly specify the path to your file in your Java code and instead, you read it as a command-line argument.

With the following code,

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

public class InputReader{

    public static void main(String[] args)throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String s="";
        while((s=br.readLine())!=null){
            System.out.println(s);
        }
    }
}

just go ahead and run it with:

java InputReader < input.txt

This would read the contents of the input.txt and print it to the your console.

You can also make your System.out.println() to write to a specific file through the command line as follows:

java InputReader < input.txt > output.txt

This would read from input.txt and write to output.txt.

You can use readAllLines and the join method to get whole file content in one line:

String str = String.join("\n",Files.readAllLines(Paths.get("e:\\text.txt")));

It uses UTF-8 encoding by default, which reads ASCII data correctly.

Also you can use readAllBytes:

String str = new String(Files.readAllBytes(Paths.get("e:\\text.txt")), StandardCharsets.UTF_8);

I think readAllBytes is faster and more precise, because it does not replace new line with \n and also new line may be \r\n. It is depending on your needs which one is suitable.

The methods within org.apache.commons.io.FileUtils may also be very handy, e.g.:

/**
 * Reads the contents of a file line by line to a List
 * of Strings using the default encoding for the VM.
 */
static List readLines(File file)
csdnceshi67
bug^君 Link on apache commons seems dead.
3 年多之前 回复
weixin_41568131
10.24 or you simply use the built in method to get all lines: docs.oracle.com/javase/7/docs/api/java/nio/file/…
6 年多之前 回复
csdnceshi77
狐狸.fox Or if you prefer Guava (a more modern, actively maintained library), it has similar utilities in its Files class. Simple examples in this answer.
6 年多之前 回复

Below is a one-liner of doing it in the Java 8 way. Assuming text.txt file is in the root of the project directory of the Eclipse.

Files.lines(Paths.get("text.txt")).collect(Collectors.toList());
共24条数据 1 3 尾页
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐