用Java读取纯文本文件


933

似乎有不同的方法可以用Java读写文件数据。

我想从文件中读取ASCII数据。有哪些可能的方法及其区别?


24
我也不同意结束语为“非建设性的”。幸运的是,这很可能作为重复项关闭。好的答案,例如在如何从文件内容创建字符串中?将文件读入String的最简单方法是什么?读取文件最简单的类是什么?
约尼克

无循环:{{{Scanner sc = new Scanner(file,“ UTF-8”); sc.useDelimiter(“ $ ^”); //正则表达式不匹配任何内容String text = sc.next(); sc.close(); }}}
Aivar

3
有趣的是,python中没有像“ read()”这样的东西可以将整个文件读取为字符串
kommradHomer 2014年

2
这是执行此操作的最简单方法:mkyong.com/java/…–
dellasavia

Answers:


567

ASCII是一个TEXT文件,因此您将Readers用于读取。Java还支持使用读取二进制文件InputStreams。如果正在读取的文件很大,则您可能需要BufferedReaderFileReader来提高读取性能。

浏览这篇文章,了解如何使用Reader

我还建议您下载并阅读这本名为《Thinking In Java》的精彩(尚未免费)的书。

在Java 7中

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

(docs)

Files.readAllLines(...)

(文档)

在Java 8中

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

(文档)


14
选择阅读器确实取决于您需要文件内容的内容。如果文件很小(ish)而您全部需要,则使用FileReader读取所有内容(或至少足够大的块)会更快(由我们测试:1.8-2x)。如果您要逐行处理它,请使用BufferedReader。
Vlad13年

3
使用“ Files.lines(..)。forEach(...)”时是否保留行顺序。我的理解是,此操作后的顺序将是任意的。
Daniil Shevelev 2014年

38
Files.lines(…).forEach(…)不保留行顺序,而是并行执行@Dash。如果订单很重要,则可以使用Files.lines(…).forEachOrdered(…),它应保留订单(尽管未验证)。
Palec 2015年

2
@Palec,这很有趣,但是您可以引用其中Files.lines(...).forEach(...)并行执行的文档吗?我以为只有在使用显式使流并行时,情况才如此Files.lines(...).parallel().forEach(...)
Klitos Kyriacou 2015年

3
我最初的说法不是防弹@KlitosKyriacou。关键是forEach不能保证任何顺序,原因是易于并行化。如果要保留订单,请使用forEachOrdered
Palec 2015年

687

我最喜欢的读取小文件的方法是使用BufferedReader和StringBuilder。这很简单并且很关键(尽管不是特别有效,但是对于大多数情况来说已经足够了):

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

有人指出,在Java 7之后,您应该使用try-with-resources(即自动关闭)功能:

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

当我读取这样的字符串时,无论如何我通常还是想对每行进行一些字符串处理,因此我继续进行此实现。

尽管如果我实际上只是想将文件读入字符串,我总是使用Apache Commons IO与IOUtils.toString()方法一起使用。您可以在这里查看源代码:

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

使用Java 7甚至更简单:

try(FileInputStream inputStream = new FileInputStream("foo.txt")) {     
    String everything = IOUtils.toString(inputStream);
    // do something with everything string
}

6
如果已到达最后一行,我做了一些小的调整以停止添加换行符(\ n)。code while(line!= null){sb.append(line); 行= br.readLine(); //仅当curline不是最后一行时才添加新行。.if(line!= null){sb.append(“ \ n”); }code
拉蒙·芬肯

2
与Apache通用IO IOUtils#toString()类似的是sun.misc.IOUtils#readFully(),它包含在Sun / Oracle JRE中。
gb96

3
为了提高性能,始终优先于sb.append(“ \ n”)调用sb.append('\ n'),因为将char附加到StringBuilder的速度比字符串快
gb96 2013年

2
FileReader可能会抛出FileNotFoundException,而BufferedRead可能会抛出IOException,因此您必须捕获它们。
kamaci 2014年

4
不需要直接使用阅读器,也不需要ioutils。java7内置了读取整个文件/所有行的方法:请参阅docs.oracle.com/javase/7/docs/api/java/nio/file/…docs.oracle.com/javase/7/docs/api / java / nio / file /…
kritzikratzi 2014年

142

最简单的方法是使用ScannerJava中的类和FileReader对象。简单的例子:

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

Scanner 有几种读取字符串,数字等的方法。您可以在Java文档页面上找到有关此内容的更多信息。

例如,将全部内容读入String

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

另外,如果您需要特定的编码,则可以使用此编码代替FileReader

new InputStreamReader(new FileInputStream(fileUtf8), StandardCharsets.UTF_8)

28
while(in.hasNext()){System.out.println(in.next()); }
Gene Bo

16
@Hissain但比使用起来容易得多BufferedReader
Jesus Ramos

3
必须尝试捕捉围绕着它
拉哈尔迦腻色迦

@JesusRamos不是,您为什么这么认为?有什么比这更容易的while ((line = br.readLine()) != null) { sb.append(line); }呢?
user207421 '19

83

这是一个简单的解决方案:

String content;

content = new String(Files.readAllBytes(Paths.get("sample.txt")));

2
@Nery Jr,优雅又简单
Mahmoud Saleh

1
最好和最简单的。
Dary

57

这是不使用外部库的另一种方法:

import java.io.File;
import java.io.FileReader;
import java.io.IOException;

public String readFile(String filename)
{
    String content = null;
    File file = new File(filename); // For example, foo.txt
    FileReader reader = null;
    try {
        reader = new FileReader(file);
        char[] chars = new char[(int) file.length()];
        reader.read(chars);
        content = new String(chars);
        reader.close();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if(reader != null){
            reader.close();
        }
    }
    return content;
}

10
或使用“尝试使用资源” try(FileReader reader = new FileReader(file))
HernánEche 2014年

3
我注意到file.length(),它对utf-16文件的工作情况如何?
韦恩2014年

5
该技术假定read()填充了缓冲区。字符数等于字节数;字节数适合内存;并且字节数适合一个整数。-1
user207421

1
@HermesTrismegistus我提供了四个错误原因。StefanReich非常同意我的观点。
user207421

34

我不得不对不同的方法进行基准测试。我将对我的发现发表评论,但总之,最快的方法是在FileInputStream上使用普通的BufferedInputStream。如果必须读取许多文件,则三个线程将使总执行时间减少到大约一半,但是添加更多线程将逐渐降低性能,直到完成二十个线程所需的时间比仅使用一个线程花费三倍的时间。

假定您必须读取文件并对其内容进行有意义的操作。在示例中,这里是从日志中读取行,并对包含超过某个阈值的值的行进行计数。所以我假设Java 8是单线的Files.lines(Paths.get("/path/to/file.txt")).map(line -> line.split(";"))不是一个选择。

我在Java 1.8,Windows 7以及SSD和HDD驱动器上进行了测试。

我写了六个不同的实现:

rawParse:在FileInputStream上使用BufferedInputStream,然后读取字节。这优于任何其他单线程方法,但是对于非ASCII文件可能非常不便。

lineReaderParse:在FileReader上使用BufferedReader,逐行读取,并通过调用String.split()拆分行。这大约比rawParse慢20%。

lineReaderParseParallel:与lineReaderParse相同,但是它使用多个线程。在所有情况下,这都是最快的选择。

nioFilesParse:使用java.nio.files.Files.lines()

nioAsyncParse:将AsynchronousFileChannel与完成处理程序和线程池一起使用。

nioMemoryMappedParse:使用内存映射文件。这确实是一个坏主意,其执行时间至少是其他任何实现的三倍。

这些是在四核i7和SSD驱动器上平均读取204个4 MB的文件的平均时间。这些文件是动态生成的,以避免磁盘缓存。

rawParse                11.10 sec
lineReaderParse         13.86 sec
lineReaderParseParallel  6.00 sec
nioFilesParse           13.52 sec
nioAsyncParse           16.06 sec
nioMemoryMappedParse    37.68 sec

我发现,在SSD或HDD驱动器上运行时,两者之间的差异比我预期的要小15%。这可能是因为文件是在未碎片整理的HDD上生成的,并且它们是顺序读取的,因此旋转驱动器几乎可以充当SSD。

nioAsyncParse实现的性能低下令我感到惊讶。我用错误的方式实现了某些东西,或者使用NIO的多线程实现和完成处理程序执行的效果与使用java.io API的单线程实现相同(甚至更差)。而且,用CompletionHandler进行的异步解析在代码行中要长得多,并且要正确实现比在旧流上直接实现要花更多的时间。

现在有六个实现,后面是一个包含所有实现的类,以及一个可参数化的main()方法,该方法允许播放文件数量,文件大小和并发度。请注意,文件大小的变化范围为负20%。这是为了避免由于所有文件的大小完全相同而造成的任何影响。

rawParse

public void rawParse(final String targetDir, final int numberOfFiles) throws IOException, ParseException {
    overrunCount = 0;
    final int dl = (int) ';';
    StringBuffer lineBuffer = new StringBuffer(1024);
    for (int f=0; f<numberOfFiles; f++) {
        File fl = new File(targetDir+filenamePreffix+String.valueOf(f)+".txt");
        FileInputStream fin = new FileInputStream(fl);
        BufferedInputStream bin = new BufferedInputStream(fin);
        int character;
        while((character=bin.read())!=-1) {
            if (character==dl) {

                // Here is where something is done with each line
                doSomethingWithRawLine(lineBuffer.toString());
                lineBuffer.setLength(0);
            }
            else {
                lineBuffer.append((char) character);
            }
        }
        bin.close();
        fin.close();
    }
}

public final void doSomethingWithRawLine(String line) throws ParseException {
    // What to do for each line
    int fieldNumber = 0;
    final int len = line.length();
    StringBuffer fieldBuffer = new StringBuffer(256);
    for (int charPos=0; charPos<len; charPos++) {
        char c = line.charAt(charPos);
        if (c==DL0) {
            String fieldValue = fieldBuffer.toString();
            if (fieldValue.length()>0) {
                switch (fieldNumber) {
                    case 0:
                        Date dt = fmt.parse(fieldValue);
                        fieldNumber++;
                        break;
                    case 1:
                        double d = Double.parseDouble(fieldValue);
                        fieldNumber++;
                        break;
                    case 2:
                        int t = Integer.parseInt(fieldValue);
                        fieldNumber++;
                        break;
                    case 3:
                        if (fieldValue.equals("overrun"))
                            overrunCount++;
                        break;
                }
            }
            fieldBuffer.setLength(0);
        }
        else {
            fieldBuffer.append(c);
        }
    }
}

lineReaderParse

public void lineReaderParse(final String targetDir, final int numberOfFiles) throws IOException, ParseException {
    String line;
    for (int f=0; f<numberOfFiles; f++) {
        File fl = new File(targetDir+filenamePreffix+String.valueOf(f)+".txt");
        FileReader frd = new FileReader(fl);
        BufferedReader brd = new BufferedReader(frd);

        while ((line=brd.readLine())!=null)
            doSomethingWithLine(line);
        brd.close();
        frd.close();
    }
}

public final void doSomethingWithLine(String line) throws ParseException {
    // Example of what to do for each line
    String[] fields = line.split(";");
    Date dt = fmt.parse(fields[0]);
    double d = Double.parseDouble(fields[1]);
    int t = Integer.parseInt(fields[2]);
    if (fields[3].equals("overrun"))
        overrunCount++;
}

lineReaderParseParallel

public void lineReaderParseParallel(final String targetDir, final int numberOfFiles, final int degreeOfParalelism) throws IOException, ParseException, InterruptedException {
    Thread[] pool = new Thread[degreeOfParalelism];
    int batchSize = numberOfFiles / degreeOfParalelism;
    for (int b=0; b<degreeOfParalelism; b++) {
        pool[b] = new LineReaderParseThread(targetDir, b*batchSize, b*batchSize+b*batchSize);
        pool[b].start();
    }
    for (int b=0; b<degreeOfParalelism; b++)
        pool[b].join();
}

class LineReaderParseThread extends Thread {

    private String targetDir;
    private int fileFrom;
    private int fileTo;
    private DateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private int overrunCounter = 0;

    public LineReaderParseThread(String targetDir, int fileFrom, int fileTo) {
        this.targetDir = targetDir;
        this.fileFrom = fileFrom;
        this.fileTo = fileTo;
    }

    private void doSomethingWithTheLine(String line) throws ParseException {
        String[] fields = line.split(DL);
        Date dt = fmt.parse(fields[0]);
        double d = Double.parseDouble(fields[1]);
        int t = Integer.parseInt(fields[2]);
        if (fields[3].equals("overrun"))
            overrunCounter++;
    }

    @Override
    public void run() {
        String line;
        for (int f=fileFrom; f<fileTo; f++) {
            File fl = new File(targetDir+filenamePreffix+String.valueOf(f)+".txt");
            try {
            FileReader frd = new FileReader(fl);
            BufferedReader brd = new BufferedReader(frd);
            while ((line=brd.readLine())!=null) {
                doSomethingWithTheLine(line);
            }
            brd.close();
            frd.close();
            } catch (IOException | ParseException ioe) { }
        }
    }
}

nioFilesParse

public void nioFilesParse(final String targetDir, final int numberOfFiles) throws IOException, ParseException {
    for (int f=0; f<numberOfFiles; f++) {
        Path ph = Paths.get(targetDir+filenamePreffix+String.valueOf(f)+".txt");
        Consumer<String> action = new LineConsumer();
        Stream<String> lines = Files.lines(ph);
        lines.forEach(action);
        lines.close();
    }
}


class LineConsumer implements Consumer<String> {

    @Override
    public void accept(String line) {

        // What to do for each line
        String[] fields = line.split(DL);
        if (fields.length>1) {
            try {
                Date dt = fmt.parse(fields[0]);
            }
            catch (ParseException e) {
            }
            double d = Double.parseDouble(fields[1]);
            int t = Integer.parseInt(fields[2]);
            if (fields[3].equals("overrun"))
                overrunCount++;
        }
    }
}

nioAsyncParse

public void nioAsyncParse(final String targetDir, final int numberOfFiles, final int numberOfThreads, final int bufferSize) throws IOException, ParseException, InterruptedException {
    ScheduledThreadPoolExecutor pool = new ScheduledThreadPoolExecutor(numberOfThreads);
    ConcurrentLinkedQueue<ByteBuffer> byteBuffers = new ConcurrentLinkedQueue<ByteBuffer>();

    for (int b=0; b<numberOfThreads; b++)
        byteBuffers.add(ByteBuffer.allocate(bufferSize));

    for (int f=0; f<numberOfFiles; f++) {
        consumerThreads.acquire();
        String fileName = targetDir+filenamePreffix+String.valueOf(f)+".txt";
        AsynchronousFileChannel channel = AsynchronousFileChannel.open(Paths.get(fileName), EnumSet.of(StandardOpenOption.READ), pool);
        BufferConsumer consumer = new BufferConsumer(byteBuffers, fileName, bufferSize);
        channel.read(consumer.buffer(), 0l, channel, consumer);
    }
    consumerThreads.acquire(numberOfThreads);
}


class BufferConsumer implements CompletionHandler<Integer, AsynchronousFileChannel> {

        private ConcurrentLinkedQueue<ByteBuffer> buffers;
        private ByteBuffer bytes;
        private String file;
        private StringBuffer chars;
        private int limit;
        private long position;
        private DateFormat frmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        public BufferConsumer(ConcurrentLinkedQueue<ByteBuffer> byteBuffers, String fileName, int bufferSize) {
            buffers = byteBuffers;
            bytes = buffers.poll();
            if (bytes==null)
                bytes = ByteBuffer.allocate(bufferSize);

            file = fileName;
            chars = new StringBuffer(bufferSize);
            frmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            limit = bufferSize;
            position = 0l;
        }

        public ByteBuffer buffer() {
            return bytes;
        }

        @Override
        public synchronized void completed(Integer result, AsynchronousFileChannel channel) {

            if (result!=-1) {
                bytes.flip();
                final int len = bytes.limit();
                int i = 0;
                try {
                    for (i = 0; i < len; i++) {
                        byte by = bytes.get();
                        if (by=='\n') {
                            // ***
                            // The code used to process the line goes here
                            chars.setLength(0);
                        }
                        else {
                                chars.append((char) by);
                        }
                    }
                }
                catch (Exception x) {
                    System.out.println(
                        "Caught exception " + x.getClass().getName() + " " + x.getMessage() +
                        " i=" + String.valueOf(i) + ", limit=" + String.valueOf(len) +
                        ", position="+String.valueOf(position));
                }

                if (len==limit) {
                    bytes.clear();
                    position += len;
                    channel.read(bytes, position, channel, this);
                }
                else {
                    try {
                        channel.close();
                    }
                    catch (IOException e) {
                    }
                    consumerThreads.release();
                    bytes.clear();
                    buffers.add(bytes);
                }
            }
            else {
                try {
                    channel.close();
                }
                catch (IOException e) {
                }
                consumerThreads.release();
                bytes.clear();
                buffers.add(bytes);
            }
        }

        @Override
        public void failed(Throwable e, AsynchronousFileChannel channel) {
        }
};

完全可实施的所有案例

https://github.com/sergiomt/javaiobenchmark/blob/master/FileReadBenchmark.java


24

以下是三种经过测试的有效方法:

使用 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);
        }
    }
}

使用 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());
        }
    }
}

使用 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);
        }
    }
}

使用Scanner类无循环地读取整个文件

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

1
如果项目中存在文件夹,如何给出路径?
卡维普里亚

2
java.nio.file.Files呢 现在,我们可以直接使用readAllLinesreadAllByteslines
克洛德·马丁

21

其中的方法org.apache.commons.io.FileUtils也可能非常方便,例如:

/**
 * 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)

或者,如果您更喜欢Guava(一个更为现代,主动维护的库),则它的Files类中具有类似的实用程序。这个答案简单的例子
约尼克,

1
或者您只需使用内置的方法来获取所有行:docs.oracle.com/javase/7/docs/api/java/nio/file/...
kritzikratzi

Apache Commons上的链接似乎已死。
kebs 2017年

17

您要如何处理文字?文件足够小以适合内存吗?我会尝试找到最简单的方法来处理您需要的文件。FileUtils库对此非常有用。

for(String line: FileUtils.readLines("my-text-file"))
    System.out.println(line);


@PeterLawrey可能意味着org.apache.commons.io.FileUtils。随着最广泛的含义发生变化,Google链接可能会随着时间的推移而改变内容,但这与他的查询相符并且看起来正确。
Palec 2015年

2
不幸的是,如今没有readLines(String)readLines(File)并且不赞成readLines(File, Charset)。编码也可以字符串形式提供。
Palec 2015年


12

我记录了15种用Java读取文件的方法,然后测试了各种文件大小的速度(从1 KB到1 GB),这是执行此操作的前三种方法:

  1. java.nio.file.Files.readAllBytes()

    经测试可在Java 7、8和9中工作。

    import java.io.File;
    import java.io.IOException;
    import java.nio.file.Files;
    
    public class ReadFile_Files_ReadAllBytes {
      public static void main(String [] pArgs) throws IOException {
        String fileName = "c:\\temp\\sample-10KB.txt";
        File file = new File(fileName);
    
        byte [] fileBytes = Files.readAllBytes(file.toPath());
        char singleChar;
        for(byte b : fileBytes) {
          singleChar = (char) b;
          System.out.print(singleChar);
        }
      }
    }
  2. java.io.BufferedReader.readLine()

    经测试可在Java 7、8、9中运行。

    import java.io.BufferedReader;
    import java.io.FileReader;
    import java.io.IOException;
    
    public class ReadFile_BufferedReader_ReadLine {
      public static void main(String [] args) throws IOException {
        String fileName = "c:\\temp\\sample-10KB.txt";
        FileReader fileReader = new FileReader(fileName);
    
        try (BufferedReader bufferedReader = new BufferedReader(fileReader)) {
          String line;
          while((line = bufferedReader.readLine()) != null) {
            System.out.println(line);
          }
        }
      }
    }
  3. java.nio.file.Files.lines()

    经过测试,它可以在Java 8和9中运行,但由于需要lambda表达式,因此无法在Java 7中运行。

    import java.io.File;
    import java.io.IOException;
    import java.nio.file.Files;
    import java.util.stream.Stream;
    
    public class ReadFile_Files_Lines {
      public static void main(String[] pArgs) throws IOException {
        String fileName = "c:\\temp\\sample-10KB.txt";
        File file = new File(fileName);
    
        try (Stream linesStream = Files.lines(file.toPath())) {
          linesStream.forEach(line -> {
            System.out.println(line);
          });
        }
      }
    }

9

下面是用Java 8方式进行的一种分析。假设text.txt文件位于Eclipse项目目录的根目录中。

Files.lines(Paths.get("text.txt")).collect(Collectors.toList());

7

使用BufferedReader:

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

BufferedReader br;
try {
    br = new BufferedReader(new FileReader("/fileToRead.txt"));
    try {
        String x;
        while ( (x = br.readLine()) != null ) {
            // Printing out each line in the file
            System.out.println(x);
        }
    }
    catch (IOException e) {
        e.printStackTrace();
    }
}
catch (FileNotFoundException e) {
    System.out.println(e);
    e.printStackTrace();
}

7

基本上,这与Jesus Ramos的回答完全相同,只是使用File而不是FileReader加上迭代来逐步浏览文件的内容。

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

...抛出 FileNotFoundException


3
文件与FileReader:使用FileReader,文件必须存在,并且操作系统权限必须允许访问。使用文件,可以测试这些权限或检查文件是否为目录。File具有有用的功能:isFile(),isDirectory(),listFiles(),canExecute(),canRead(),canWrite(),existing(),mkdir(),delete()。File.createTempFile()写入系统默认的临时目录。此方法将返回可以被用来打开FileOutputStream中对象,文件对象等
ThisClark

7

实际上,缓冲流类的性能要好得多,以至于NIO.2 API包含专门返回这些流类的方法,部分是为了鼓励您始终在应用程序中使用缓冲流。

这是一个例子:

Path path = Paths.get("/myfolder/myfile.ext");
try (BufferedReader reader = Files.newBufferedReader(path)) {
    // Read from the stream
    String currentLine = null;
    while ((currentLine = reader.readLine()) != null)
        //do your code here
} catch (IOException e) {
    // Handle file I/O exception...
}

您可以替换此代码

BufferedReader reader = Files.newBufferedReader(path);

BufferedReader br = new BufferedReader(new FileReader("/myfolder/myfile.ext"));

我推荐这篇文章以学习Java NIO和IO的主要用法。


6

可能不像使用缓冲I / O那样快,但是非常简洁:

    String content;
    try (Scanner scanner = new Scanner(textFile).useDelimiter("\\Z")) {
        content = scanner.next();
    }

\Z模式Scanner表明分隔符为EOF。


1
一个非常相关且已经存在的答案是耶稣拉莫斯。
Palec'1

1
正确,应该是: if(scanner.hasNext()) content = scanner.next();
David Soroko

1
这对于我在Android 4.4上失败。仅读取1024个字节。YMMV。
罗杰·基斯

3

到目前为止,我还没有看到其他答案中提到的内容。但是,如果“最好”意味着速度,那么新的Java I / O(NIO)可能会提供最快的性能,但对于学习的人来说却并非总是最容易找出来的。

http://download.oracle.com/javase/tutorial/essential/io/file.html


您应该已经说明了它的完成方式,并且没有给出任何关注的链接
Orar

3

在Java中,从文件中读取数据的最简单方法是利用File类读取文件,并使用Scanner类读取文件内容。

public static void main(String args[])throws Exception
{
   File f = new File("input.txt");
   takeInputIn2DArray(f);
}

public static void takeInputIn2DArray(File f) throws Exception
{
    Scanner s = new Scanner(f);
    int a[][] = new int[20][20];
    for(int i=0; i<20; i++)
    {
        for(int j=0; j<20; j++)
        {
            a[i][j] = s.nextInt();
        }
    }
}

PS:不要忘记导入java.util。*;以便扫描仪正常工作。


2

番石榴为此提供了一线服务:

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

String contents = Files.toString(filePath, Charsets.UTF_8);

2

这可能不是该问题的确切答案。这是读取文件的另一种方式,您无需在Java代码中显式指定文件的路径,而是将其作为命令行参数读取。

使用以下代码,

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

只需继续运行以下命令即可:

java InputReader < input.txt

这将读取的内容input.txt并将其打印到控制台。

您还可以使您System.out.println()通过命令行写入特定文件,如下所示:

java InputReader < input.txt > output.txt

这将读取input.txt和写入output.txt


2

您可以使用readAllLines和join方法在一行中获取整个文件内容:

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

默认情况下,它使用UTF-8编码,可以正确读取ASCII数据。

您也可以使用readAllBytes:

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

我认为readAllBytes更快,更精确,因为它不会用替换新行,\n也可能替换新行\r\n。根据您的需求,哪种才合适。


1

对于基于JSF的Maven Web应用程序,只需使用ClassLoader和该Resources文件夹即可读取所需的任何文件:

  1. 将要读取的任何文件放入“资源”文件夹中。
  2. 将Apache Commons IO依赖项放入您的POM中:

    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-io</artifactId>
        <version>1.3.2</version>
    </dependency>
  3. 使用下面的代码读取它(例如,下面的代码正在读取.json文件):

    String metadata = null;
    FileInputStream inputStream;
    try {
    
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        inputStream = (FileInputStream) loader
                .getResourceAsStream("/metadata.json");
        metadata = IOUtils.toString(inputStream);
        inputStream.close();
    }
    catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return metadata;

您可以对文本文件,.properties文件,XSD架构等执行相同的操作。


您不能在“任何您想要的文件”上使用它。您只能将其用于已打包到JAR或WAR文件中的资源。
user207421


0

如果这是关于结构的简单性,请使用Java Kiss

import static kiss.API.*;

class App {
  void run() {
    String line;
    try (Close in = inOpen("file.dat")) {
      while ((line = readLine()) != null) {
        println(line);
      }
    }
  }
}

0
import java.util.stream.Stream;
import java.nio.file.*;
import java.io.*;

class ReadFile {

 public static void main(String[] args) {

    String filename = "Test.txt";

    try(Stream<String> stream = Files.lines(Paths.get(filename))) {

          stream.forEach(System.out:: println);

    } catch (IOException e) {

        e.printStackTrace();
    }

 }

 }

只需使用Java 8 Stream。


0
try {
  File f = new File("filename.txt");
  Scanner r = new Scanner(f);  
  while (r.hasNextLine()) {
    String data = r.nextLine();
    JOptionPane.showMessageDialog(data);
  }
  r.close();
} catch (FileNotFoundException ex) {
  JOptionPane.showMessageDialog("Error occurred");
  ex.printStackTrace();
}

0

Java 11中引入了最直观的方法 Files.readString

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

public class App {
    public static void main(String args[]) throws IOException {
        String content = Files.readString(Paths.get("D:\\sandbox\\mvn\\my-app\\my-app.iml"));
        System.out.print(content);
    }
}

PHP拥有数十年前的这种奢侈!☺


-3

对于大型文件,我编写的这段代码要快得多:

public String readDoc(File f) {
    String text = "";
    int read, N = 1024 * 1024;
    char[] buffer = new char[N];

    try {
        FileReader fr = new FileReader(f);
        BufferedReader br = new BufferedReader(fr);

        while(true) {
            read = br.read(buffer, 0, N);
            text += new String(buffer, 0, read);

            if(read < N) {
                break;
            }
        }
    } catch(Exception ex) {
        ex.printStackTrace();
    }

    return text;
}

10
如果您使用简单的字符串连接而不是StringBuilder,我会怀疑的快得多
PhiLho

6
我认为主要的速度提高是通过读取1MB(1024 * 1024)块获得的。但是,您可以通过将1024 * 1024作为第二个arg传递给BufferedReader构造函数来简单地进行此操作。
gb96

3
我完全不相信这是经过测试的。+=以这种方式使用时,对于应该为线性复杂度的任务,您可以得到二次(!)复杂度。这将开始抓取超过mb的文件。为了解决这个问题,您应该将文本块保留在list <string>中,或者使用前面提到的stringbuilder。
kritzikratzi 2014年

5
比什么快得多?这肯定是超过附加到一个StringBuffer更快。-1
user207421 2014年

1
@ gb96我对缓冲区大小也有同样的想法,但是在这个问题上进行的详细实验在类似的情况下给出了令人惊讶的结果:16KB缓冲区始终如一且明显更快。
chiastic-security 2014年

-3
String fileName = 'yourFileFullNameWithPath';
File file = new File(fileName); // Creates a new file object for your file
FileReader fr = new FileReader(file);// Creates a Reader that you can use to read the contents of a file read your file
BufferedReader br = new BufferedReader(fr); //Reads text from a character-input stream, buffering characters so as to provide for the efficient reading of characters, arrays, and lines.

上面这行代码可以写成1行:

BufferedReader br = new BufferedReader(new FileReader("file.txt")); // Optional

添加到字符串生成器(如果文件很大,建议使用字符串生成器,否则使用普通的String对象)

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();
    }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.