用java读取纯文本文件

pbgvytdp  于 2021-07-06  发布在  Java
关注(0)|答案(28)|浏览(568)

在java中,似乎有不同的方法来读取和写入文件的数据。
我想从文件中读取ascii数据。可能的方法和它们的区别是什么?

jyztefdp

jyztefdp16#

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

 }

 }

只需使用Java8流。

cdmah0mi

cdmah0mi17#

在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.*;让扫描器工作。

hpcdzsge

hpcdzsge18#

最直观的方法是在Java11中引入的 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拥有几十年前的奢华!☺ 
bbmckpt7

bbmckpt719#

我最喜欢的读取小文件的方法是使用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();
}

当我读到这样的字符串时,我通常希望每行都进行一些字符串处理,所以我开始使用这个实现。
如果我真的想把一个文件读入一个字符串,我总是使用ApacheCommonsIO类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
}
ubof19bj

ubof19bj20#

下面是用Java8方法实现的一行代码。假设 text.txt 文件位于eclipse的项目目录的根目录中。

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

5anewei621#

如果这是为了简化结构,请使用java kiss:

import static kiss.API.*;

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

pxy2qtax22#

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

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

ajsxfq5m23#

我不得不用不同的方法来衡量。我将对我的发现发表评论,但简而言之,最快的方法是在fileinputstream上使用普通的旧bufferedinputstream。如果必须读取许多文件,那么三个线程将把总执行时间减少到大约一半,但是添加更多的线程将逐渐降低性能,直到使用二十个线程比只使用一个线程要花三倍的时间才能完成。
假设您必须读取一个文件并对其内容做一些有意义的事情。在这里的示例中,从日志中读取行,并对包含超过某个阈值的值的行进行计数。所以我假设一行Java8 Files.lines(Paths.get("/path/to/file.txt")).map(line -> line.split(";")) 不是一个选择。
我在Java1.8、Windows7以及ssd和hdd驱动器上进行了测试。
我写了六个不同的实现:
rawparse:在fileinputstream上使用bufferedinputstream,然后逐字节剪切读取的行。这比任何其他单线程方法都好,但对于非ascii文件来说可能非常不方便。
linereaderparse:在文件读取器上使用bufferedreader,逐行读取,通过调用string.split()拆分行。这比以前慢了大约20%。
linereaderparseparallel:这与linereaderparse相同,但它使用多个线程。这是所有情况下最快的选择。
niofilesparse:使用java.nio.files.files.lines()
nioasyncparse:使用带有完成处理程序和线程池的asynchronousfilechannel。
niomemorymappedparse:使用内存Map文件。这是一个非常糟糕的主意,它的执行时间至少比任何其他实现长三倍。
这是读取204个文件(共4个)的平均时间 四核i7和ssd驱动器上各有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.ioapi的单线程实现相同(甚至更差)。此外,使用completionhandler的异步解析在代码行中要比在旧流上直接实现长得多,而且很难正确实现。
现在,这六个实现后跟一个包含它们的类,再加上一个可参数化的main()方法,该方法允许处理文件数量、文件大小和并发度。请注意,文件大小在正负20%之间变化。这是为了避免由于所有文件的大小完全相同而产生任何影响。
原始解析

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

读线器面板

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

读线器ParseParallel

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

异步解析

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

zmeyuzjn

zmeyuzjn24#

下面是一个简单的解决方案:

String content;

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

2cmtqfgy25#

以下是三种工作和测试方法:

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

使用扫描仪

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

kqlmhetl26#

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

sgtfey8w27#

cactoos为您提供了一个声明性的一行代码:

new TextOf(new File("a.txt")).asString();
l5tcr1uw

l5tcr1uw28#

最简单的方法是使用 Scanner 类和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)

相关问题