【代码审计】六种JAVA读取文件方法

0x00 版权声明

JAVA基础系列是笔者学习@炼石星球的笔记,大部分文字描述取自星球内发布的教程文件,仅作学习。

0x01 java.nio.file.Files

使用 Files 类将文件的所有内容读入字节数组。 Files 类还有一个方法可以读取所 有行到字符串列表。 Files 类是在Java 7中引入的,如果想加载所有文件内容,使用 这个类是比较适合的。只有在处理小文件并且需要加载所有文件内容到内存中时才应使用此方法。

新建Maven项目,无需选择模板,直接默认创建,下面几种方法均在此项目模板下进行。

在src/main/java新建nioRead.class文件,键入代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
public class nioRead {
public static void main(String[] args) throws IOException {
String fileName = "C:\\\\Users\\\\admins\\\\Desktop\\\\test.txt";
//使用Java 7中的Files类处理小文件,获取完整的文件数据
readUsingFiles(fileName);
}
private static void readUsingFiles(String fileName) throws
IOException {
Path path = Paths.get(fileName);
//将文件读取到字节数组
byte[] bytes = Files.readAllBytes(path);
System.out.println("使用File类读取文件.........");
@SuppressWarnings("unused")
List<String> allLines = Files.readAllLines(path,
StandardCharsets.UTF_8);
System.out.println(new String(bytes));
}
}

https://zebpic-1301715962.cos.ap-nanjing.myqcloud.com/blog/202210101747450.png

0x02 java.io.FileReader

可以使用 FileReader 获取 BufferedReader ,然后逐行读取文件。 FileReader 不支持编码并使用系统默认编码,因此它不是一种java中读取文本文件的非常有效的方法.。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
public class javaioRead {
public static void main(String[] args) throws IOException {
String fileName = "C:\\\\Users\\\\admins\\\\Desktop\\\\test.txt";
//使用FileReader读取,没有编码支持,效率不高
readUsingFileReader(fileName);
}
private static void readUsingFileReader(String fileName) throws
IOException {
File file = new File(fileName);
FileReader fr = new FileReader(file);
BufferedReader br = new BufferedReader(fr);
String line;
System.out.println("使用FileReader读取文本文件......");
while((line = br.readLine()) != null){
//逐行读取
System.out.println(line);
}
br.close();
fr.close();
}
}

https://zebpic-1301715962.cos.ap-nanjing.myqcloud.com/blog/202210101750277.png

0x03 java.io.BufferedReader

如果想逐行读取文件并对它们进行处理,那么 BufferedReader 是非常合适的。它适 用于处理大文件,也支持编码。 BufferedReader 是同步的,因此可以安全地从多个线程完成对 BufferedReader 的读取操作。 BufferedReader 的默认缓冲区大小为: 8KB

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import java.io.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
public class BufferRead {
public static void main(String[] args) throws IOException {
String fileName = "C:\\\\Users\\\\admins\\\\Desktop\\\\test.txt";
//使用BufferedReader读取,逐行读取,并设置编码为UTF_8
readUsingBufferedReader(fileName, StandardCharsets.UTF_8);
}
private static void readUsingBufferedReader(String fileName,
Charset cs) throws IOException {
File file = new File(fileName);
FileInputStream fis = new FileInputStream(file);
InputStreamReader isr = new InputStreamReader(fis, cs);
BufferedReader br = new BufferedReader(isr);
String line;
System.out.println("使用BufferedReader读取文本文件......");
while((line = br.readLine()) != null){
//逐行读取
System.out.println(line);
}
br.close();
}
}

https://zebpic-1301715962.cos.ap-nanjing.myqcloud.com/blog/202210101753109.png

0x04 Scanner

如果要逐行读取文件或基于某些java正则表达式读取文件,则可使用 Scanner 类。 Scanner 类使用分隔符模式将其输入分解为标记,分隔符模式默认匹配空格。然后可以使用各种下一种方法将得到的标记转换成不同类型的值。

Scanner 类不同步,因此不是线程安全的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Scanner;

public class ScannerRead {
public static void main(String[] args) throws IOException {
String fileName = "C:\\\\Users\\\\admins\\\\Desktop\\\\test.txt";
//使用Scanner类来处理大文件,逐行读取
readUsingScanner(fileName);
}
private static void readUsingScanner(String fileName) throws
IOException {
Path path = Paths.get(fileName);
Scanner scanner = new Scanner(path);
System.out.println("使用Scanner读取文本文件.....");
//逐行读取
while(scanner.hasNextLine()){
//逐行处理
String line = scanner.nextLine();
System.out.println(line);
}
scanner.close();
}
}

https://zebpic-1301715962.cos.ap-nanjing.myqcloud.com/blog/202210110954185.png

0x05 RandomAccessFile断点续传

随机流(RandomAccessFile)不属于IO流,支持对文件的读取和写入随机访问。 首先把随机访问的文件对象看作存储在文件系统中的一个大型 byte 数组,然后通过指向该 byte 数组的光标或索引(即:文件指针 FilePointer)在该数组任意位置读取或写入任意数据。 断点续传是在下载或上传时,将下载或上传任务(一个文件或一个压缩包)人为的划分为几个部分,每一个部分采用一个线程进行上传或下载,如果碰到网络故障,可以从已经上传或下载的部分开始继续上传或者下载未完成的部分,而没有必要从头开始上传或者下载。 断点续传实现原理:

  1. 下载断开的时候,记录文件断点的位置position;
  2. 继续下载的时候,通过RandomAccessFile找到之前的position位置开始下载
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.io.IOException;
import java.io.RandomAccessFile;
public class ReadRandomAccessFile {
public static void main(String[] args) throws IOException {
String fileName = "C:\\\\Users\\\\admins\\\\Desktop\\\\test.txt";
//使用RandomAccessFile来实现断点续传读取/下载文件
readUsingRandomAccessFile(fileName);
}
private static void readUsingRandomAccessFile(String fileName)
throws IOException {
RandomAccessFile file = new RandomAccessFile(fileName, "r");
String str;
while ((str = file.readLine()) != null) {
System.out.println("使用RandomAccessFile来实现断点续传读取/下载
文件......");
System.out.println(str);
}
file.close();
}
}

但是这种方法有个问题就是读取的是乱码:

https://zebpic-1301715962.cos.ap-nanjing.myqcloud.com/blog/202210111103309.png

0x06org.apache.commons.io.FileUtils.readFileToString

在pom.xml中引入commons-io依赖

1
2
3
4
5
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>

代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
public class ReadCommonsIo {
public static void main(String[] args) throws IOException {
String fileName = "C:\\\\Users\\\\admins\\\\Desktop\\\\test.txt";
readUsingCommonsIo(fileName);
}
private static void readUsingCommonsIo(String fileName) throws
IOException {
File file = new File(fileName);
System.out.println("使用Commons-io读取文件......");
System.out.println(FileUtils.readFileToString(file,
StandardCharsets.UTF_8));
}
}

https://zebpic-1301715962.cos.ap-nanjing.myqcloud.com/blog/202210111108304.png