JAVA: Java8流逐行读取文件

在Java8中,可以使用Files.lines读取文件的流。

c://lines.txt – 用于测试的简单文本文件
line1
line2
line3
line4
line5

核心代码:

Write to file using BufferedWriter

//Get the file reference
Path path = Paths.get("c:/output.txt");
 
//Use try-with-resource to get auto-closeable writer instance
try (BufferedWriter writer = Files.newBufferedWriter(path))
{
    writer.write("Hello World !!");
}

Write to file using Files.write()

String content = "Hello World !!";
Files.write(Paths.get("c:/output.txt"), content.getBytes());

下面的例子中,lines()方法返回字符串流,字符串使用的是UTF-8编码。如下:

Files.lines(Paths.get("D:\\jd.txt"), StandardCharsets.UTF_8).forEach(System.out::println);

或者

System.out.println(new String(readAllBytes(get("d:/jd.txt"))));

 

1. Java 8 读取文件+流

TestReadFile.java

package com.ikeepstudying.java8;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.stream.Stream;

public class TestReadFile {
	public static void main(String args[]) {
		String fileName = "c://lines.txt";
		//read file into stream, try-with-resources
		try (Stream<String> stream = Files.lines(Paths.get(fileName))) {
			stream.forEach(System.out::println);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

输出结果

line1
line2
line3
line4
line5

2. Java 8 读取文件+流+额外

这个例子说明了如何使用数据流过滤内容,其全部内容转换为大写并返回一个列表。

TestReadFile2.java

package com.ikeepstudying.java8;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class TestReadFile2 {
	public static void main(String args[]) {
		String fileName = "c://lines.txt";
		List<String> list = new ArrayList<>();
		try (Stream<String> stream = Files.lines(Paths.get(fileName))) {
			//1. filter line 3
			//2. convert all content to upper case
			//3. convert it into a List
			list = stream
					.filter(line -> !line.startsWith("line3"))
					.map(String::toUpperCase)
					.collect(Collectors.toList());
		} catch (IOException e) {
			e.printStackTrace();
		}
		list.forEach(System.out::println);
	}
}

输出结果

LINE1
LINE2
LINE4
LINE5

3. BufferedReader + Stream

一种新的方法lines() ,已经在JDK1.8已经添加,它让 BufferedReader 返回流的内容。

TestReadFile3.java

package com.ikeepstudying.java8;

import java.io.BufferedReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class TestReadFile3{
	public static void main(String args[]) {
		String fileName = "c://lines.txt";
		List<String> list = new ArrayList<>();
		try (BufferedReader br = Files.newBufferedReader(Paths.get(fileName))) {
			//br returns as stream and convert it into a List
			list = br.lines().collect(Collectors.toList());

		} catch (IOException e) {
			e.printStackTrace();
		}
		list.forEach(System.out::println);
	}
}

输出结果

line1
line2
line3
line4
line5

4. BufferedReader和Scanner

上面我们已经足够了解Java8和流,现在重温经典BufferedReader(JDK1.1)和Scanner (JDK1.5)的例子来逐行读取文件中的行。

4.1 BufferedReader + 尝试使用资源的例子。

TestReadFile4.java

package com.ikeepstudying.core;

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

public class TestReadFile4{
	public static void main(String args[]) {
		String fileName = "c://lines.txt";
		try (BufferedReader br = new BufferedReader(new FileReader(fileName))) {
			String line;
			while ((line = br.readLine()) != null) {
				System.out.println(line);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

4.2 Scanner+使用资源的例子。

TestReadFile5.java

package com.ikeepstudying.core;

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

public class TestReadFile5 {
	public static void main(String args[]) {
		String fileName = "c://lines.txt";
		try (Scanner scanner = new Scanner(new File(fileName))) {
			while (scanner.hasNext()){
				System.out.println(scanner.nextLine());
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

参考

  1. Java 8 File.lines()
  2. Java 8 Stream
  3. Java BufferedReader

 

较”复杂”版本

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

public class Entity {
    public static void main(String[] args) throws IOException {
         if (!Files.exists(Paths.get(".\\test.txt"))) Files.write(Paths.get(".\\test.txt"), new byte[0]);
        if (!Files.exists(Paths.get(".\\newtest.txt"))) Files.write(Paths.get(".\\newtest.txt"), new byte[0]);
        try (
                FileInputStream fis = new FileInputStream(".\\test.txt");
                FileOutputStream fos = new FileOutputStream(".\\newtest.txt");
        ) {
            if (Files.readAllLines(Paths.get(".\\test.txt")).size() == 0) {
                Files.write(Paths.get(".\\test.txt"), ("first write------" + System.currentTimeMillis()).getBytes());
            }else{
                //一行代码写入文件.
                Files.write(Paths.get(".\\test.txt"), ("more write------" + System.currentTimeMillis()).getBytes());
            }
            int result = 0;
            byte[] by = new byte[1024];
            while ((result = fis.read(by)) != -1) {
                fos.write((new String(by) + "---" + System.currentTimeMillis()).getBytes());
            }
            /*
             * java 8 一行代码读取文件内容
               *
               1)文件可能很大,可能会超出内存空间,使用前要做评估。
               2)要输出日志,记录为什么无法读取文件或者在阅读文件时遇到的任何错误。
               3)在把字节转换成字符时,应该指定字符编码。
               4)要处理文件不存在的情况。
               还要注意,如果读入的文件的编码是ANSI编码,那么上面的例子在读取文件内容时会报java.nio.charset.MalformedInputException: Input length = 1错误。
             *
             */
            Files.readAllLines(Paths.get(".\\newtest.txt"), Charset.defaultCharset()).forEach(t -> System.out.println("newtest.txt:" + t));
        }
    }
}

更加”偷懒”的版本

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

public class Entity {
    public static void main(String[] args) throws IOException {
        //检查文件是否存在
        if (!Files.exists(Paths.get(".\\test.txt"))) Files.write(Paths.get(".\\test.txt"), new byte[0]);
        if (!Files.exists(Paths.get(".\\newtest.txt"))) Files.write(Paths.get(".\\newtest.txt"), new byte[0]);
        //end.
        if (Files.readAllLines(Paths.get(".\\test.txt")).size() == 0) {
            Files.write(Paths.get(".\\test.txt"), ("first write------" + System.currentTimeMillis()).getBytes());
        } else {
            //一行代码写入文件.
            Files.write(Paths.get(".\\test.txt"), ("more write------" + System.currentTimeMillis()).getBytes());
        }
            Files.write(Paths.get(".\\newtest.txt"), (Files.readAllLines(Paths.get(".\\test.txt"))));
        
            /*
             * java 8 一行代码读取文件内容
               *
               1)文件可能很大,可能会超出内存空间,使用前要做评估。
               2)要输出日志,记录为什么无法读取文件或者在阅读文件时遇到的任何错误。
               3)在把字节转换成字符时,应该指定字符编码。
               4)要处理文件不存在的情况。
               还要注意,如果读入的文件的编码是ANSI编码,那么上面的例子在读取文件内容时会报java.nio.charset.MalformedInputException: Input length = 1错误。
             *
             */
        Files.readAllLines(Paths.get(".\\newtest.txt"), Charset.defaultCharset()).forEach(t -> System.out.println("newtest.txt:" + t));
    }
}

较为”舒适”的版本

下面这个是我自己觉得比较好的版本,虽然改进空间很大,但对于这个小程序来说,应该是足够了.

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

public class Entity {
    public static void main(String[] args) throws IOException {
        //检查文件是否存在
        if (!Files.exists(Paths.get(".\\test.txt"))) write(".\\test.txt", new byte[0]);
        if (!Files.exists(Paths.get(".\\newtest.txt"))) write(".\\newtest.txt", new byte[0]);
        //end.
        if (Files.readAllLines(Paths.get(".\\test.txt")).size() == 0) {
            write(".\\test.txt", ("first write------" + System.currentTimeMillis()).getBytes());
        } else {
            //一行代码写入文件.
            write(".\\test.txt", ("more write------" + System.currentTimeMillis()).getBytes());
        }
        write(".\\newtest.txt", (Files.readAllLines(Paths.get(".\\test.txt"))));
        show(".\\newtest.txt");
    }

    //还有两个就懒得实现了,只是第二个参数不同

    /**
     * 一行代码写文件的封装.
     *
     * @param paths
     * @param content
     * @throws IOException
     */
    private static void write(String paths, Iterable<? extends CharSequence> content) throws IOException {
        Files.write(Paths.get(paths), content);
    }

    /**
     * 一行代码写文件的封装
     *
     * @param paths
     * @param content
     * @throws IOException
     */
    private static void write(String paths, byte[] content) throws IOException {
        Files.write(Paths.get(paths), content);
    }


    /**
     * 一行代码输出文件
     *
     * java 8 一行代码读取文件内容
     *
     1)文件可能很大,可能会超出内存空间,使用前要做评估。
     2)要输出日志,记录为什么无法读取文件或者在阅读文件时遇到的任何错误。
     3)在把字节转换成字符时,应该指定字符编码。
     4)要处理文件不存在的情况。
     还要注意,如果读入的文件的编码是ANSI编码,那么上面的例子在读取文件内容时会报java.nio.charset.MalformedInputException: Input length = 1错误。
     *
     * @param filepath
     * @throws IOException
     */
    private static void show(String filepath) throws IOException {
        Files.readAllLines(Paths.get(filepath), Charset.defaultCharset()).forEach(t -> System.out.println(filepath + "------>#" + t));
    }
}

如果使用的不是JDK7,而是JDK8,那么一行代码即可完成读文件。

import static java.lang.System.out;  
import static java.nio.file.Files.readAllBytes;  
import static java.nio.file.Paths.get;  
  
import java.io.IOException;  
public class FileIntoString {  
    public static void main(String[] args) throws IOException {  
        // 一行代码搞定读文件,默认是UTF-8编码  
        out.println(new String(readAllBytes(get("d:/jd.txt"))));  
    }  
}

如果使用JDK8,那么还可以使用流API来读写文件,这样代码更简洁、高效。
下面的例子中,lines()方法返回字符串流,字符串使用的是UTF-8编码。如下:

import java.io.IOException;  
import java.nio.charset.StandardCharsets;  
import java.nio.file.Files;  
import java.nio.file.Paths;  
  
  
public class Java8FileReader {  
    public static void main(String[] args) throws IOException {  
        // Java8用流的方式读文件,更加高效  
        Files.lines(Paths.get("D:\\jd.txt"), StandardCharsets.UTF_8).forEach(System.out::println);  
    }  
}

 

文本:JAVA: Java8流逐行读取文件

2 Comments

Leave a Reply