Java文件读取与下载 今天学了文件读取与下载的七种方法。
(每次在ide里新建了md,再进入typora里编辑,都会出现一点事故-输入失效,光标跳行)
这篇文章主要是一些代码解析。是什么?干什么用?怎么用?
法一:使用java.nio.file.Files读取文本 核心函数: Files.readAllBytes()
该方法适合读取小文件(相较于内存而言)内存消耗 : 由于该方法一次性将文件的所有行读取到内存中,因此不适合处理非常大的文件,否则可能导致内存不足问题。
NIO: (New Input/Output) 是 Java 中用于处理非阻塞 I/O 操作的 API,提供了更加高效的文件和网络 I/O 处理能力
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 26 27 28 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 ReadFiles { public static void main (String[] args) throws IOException { String fileName = "E:\\Java\\JWeb\\data\\test.txt" ; readUsingFiles(fileName); } private static void readUsingFiles (String fileName) throws IOException { Path path = Paths.get(fileName); byte [] bytes = Files.readAllBytes(path); System.out.println("使用File类读取文件........." ); System.out.println(bytes); System.out.println(new String (bytes)); @SuppressWarnings("unused") List<String> allLines = Files.readAllLines(path, StandardCharsets.UTF_8); System.out.println(allLines); System.out.println( (path)); String content=String.join("\n" , allLines); System.out.println(content); } }
法二:java.io.FileReader 适合处理小到中等大小的文本文件。对于大文件或需要支持不同编码的文件,可以考虑使用更高级的文件读取方式。
核心函数:
1 2 3 4 5 6 FileReader fr=new FileReader (path); BufferedReader br=new BufferedReader (fr); String line; while ((line=br.readLine())!=null ){ System.out.println(line); }
整体解析:
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 26 27 28 29 30 import java.io.BufferedReader;import java.io.File;import java.io.FileReader;import java.io.IOException;public class ReadFileReader { public static void main (String[] args) throws IOException { String fileName = "E:\\Java\\JWeb\\data\\test.txt" ; readUsingFileReader(fileName); } private static void readUsingFileReader (String fileName) throws IOException { File file = new File (fileName); FileReader fr = new FileReader (file); System.out.println("Beginning" ); System.out.println(fr.read()); BufferedReader br = new BufferedReader (fr); System.out.println(br.readLine()); String line; System.out.println("使用FileReader读取文本文件......" ); while ((line = br.readLine()) != null ){ System.out.println(line); } br.close(); fr.close(); } }
法三:java.io.BufferedReader(法二) 特征描述:
适用于处理大文件, 也支持编码。
BufferedReader 是同步的,因此可以安全地从多个线程 完成对 BufferedReader 的读取操作。
BufferedReader 的默认缓冲区大小为: 8KB 。
核心函数:
1 2 3 4 FileInputStream fis=new FileInputStream (fileName); InputStreamReader isr=new InputStreamReader (fis); FileReader fr=new FileReader (fileName); BufferedReader br=new BufferedReader (isr);
整体解析: (编码方式对文件读取的影响)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import java.io.*;import java.nio.charset.StandardCharsets;public class ReadBufferedReader { public static void main (String[] args) throws IOException { String fileName = "E:\\Java\\JWeb\\data\\test.txt" ; readUsingBufferedReader(fileName); } private static void readUsingBufferedReader (String fileName) throws IOException { File file = new File (fileName); FileInputStream fis = new FileInputStream (file); InputStreamReader isr = new InputStreamReader (fis, StandardCharsets.UTF_8); BufferedReader br = new BufferedReader (isr); String line; System.out.println("使用BufferedReader读取文本文件......" ); while ((line = br.readLine()) != null ){ System.out.println(line); } br.close(); } }
法四:Scanner 特征描述:
Scanner 类:
逐行读取文件或
某些java正则表达式读取文件
处理大文件
Scanner 类使用分隔符模式 将其输入分解为标记,分隔符模式默认匹配空格。
然后可以使用各种下一种方法将得到的标记转换 成不同类型的值。
Scanner 类不同步,因此不是线程安全的。
核心函数:
1 2 3 4 5 6 Scanner sc=new Scanner (path); String line; while (sc.hasNextLine()){ line=sc.nextLine(); System.out.println(line); }
法五:RandomAccessFile断点续传 特征描述:
随机流(RandomAccessFile)不属于IO流,支持对文件的读取和写入随机访问。
首先把随机访问的文件对象看作存储在文件系统中的一个大型 byte 数组,然后通过指向该 byte 数组的 光标或索引(即:文件指针 FilePointer)在该数组任意位置读取或写入任意数据。
断点续传 是在下载或上传时,将下载或上传任务(一个文件或一个压缩包)人为的划分为几个部分,每 一个部分采用一个线程进行上传或下载,如果碰到网络故障,可以从已经上传或下载的部分开始继续上 传或者下载未完成的部分,而没有必要从头开始上传或者下载。
断点续传实现原理:
下载断开的时候,记录文件断点的位置position;
继续下载的时候,通过RandomAccessFile找到之前的position位置开始下载
note:
不支持编码后的文件
核心函数:
1 RandomAccessFile file = new RandomAccessFile (fileName, "r" );
r:只读
rw:读写
rws :Open for reading and writing, as with “rw”, and also require that every update to the file’s content or metadata be written synchronously to the underlying storage device.
rwd:Open for reading and writing, as with “rw”, and also require that every update to the file’s conten t be written synchronously to the underlying storage device.
整体实现:
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 MyRandomAccessFile { public static void main (String[] args) throws IOException { String fileName = "E:\\Java\\JWeb\\data\\test.txt" ; RandomAccessFileReading(fileName); } private static void RandomAccessFileReading (String fileName) throws IOException { RandomAccessFile randomAccessFile = new RandomAccessFile (fileName,"r" ); System.out.println(randomAccessFile); String line; while ((line=randomAccessFile.readLine())!=null ){ System.out.println(line); } randomAccessFile.close(); } }
法六:外部库 org.apache.commons.io.FileUtils.readFileToString() 特征描述:
it might not be suitable for very large files, as it loads the entire file into memory 不适合大文件(相较内存而言)
FileUtils.readFileToString() method to read the entire content of the file into a String.将整个文件 读入内存
需要安装依赖项:Commons-io
核心函数:
1 System.out.println(FileUtils.readFileToString(file, StandardCharsets.UTF_8));
整体解析:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; public class MyReadCommonsIo { public static void main(String[] args) throws IOException { String fileName = "E:\\Java\\JWeb\\data\\test.txt"; ReadCommonsIoReading(fileName); } private static void ReadCommonsIoReading(String fileName) throws IOException { System.out.println(FileUtils.readFileToString(new File(fileName), StandardCharsets.UTF_8)); } }
法七:Files.readString() 整体实现:
1 2 3 4 5 6 7 8 9 10 import java.io.IOException;import java.nio.file.Files;import java.nio.file.Path;public class MyreadString { public static void main (String[] args) throws IOException { String fileName = "E:\\Java\\JWeb\\data\\test.txt" ; System.out.println(Files.readString(Path.of(fileName))); } }
Web工程 1 2 3 4 http://127.0.0.1:8080/readUsingRandomAccessFile?fileName=E:\Java\JWeb\data\test.txt http://127.0.0.1:8080/readUsingRandomAccessFile?fileName=E:/Java/JWeb/data/test.txt http://127.0.0.1:8080/readUsingFiles?fileName=E:/Java/JWeb/data/test.txt //注意访问用正斜杠
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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 package org.example.pfilereader;import jakarta.servlet.http.HttpServletResponse;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.ResponseBody;import org.apache.commons.io.FileUtils;import java.io.*;import java.net.URLEncoder;import java.nio.charset.StandardCharsets;import java.nio.file.Files;import java.nio.file.Path;import java.nio.file.Paths;import java.util.List;import java.util.Scanner;@Controller @ResponseBody public class ReadFilesController { @RequestMapping("/readUsingFiles") public String readUsingFiles (String fileName, HttpServletResponse response) 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)); return new String (bytes); } @RequestMapping("/readUsingFileReader") public void readUsingFileReader (String fileName, HttpServletResponse response) throws IOException { File file=new File (fileName); FileReader fr=new FileReader (file); BufferedReader br=new BufferedReader (fr); String line; System.out.println("使用FileReader读取文本文件......" ); response.reset(); response.setContentType("application/octet-stream" ); response.setHeader("Content-Disposition" , "attachment; filename=" + URLEncoder.encode(fileName,"UTF-8" )); PrintWriter pw=response.getWriter(); while ((line=br.readLine())!=null ){ System.out.println(line); pw.println(line); } br.close(); fr.close(); } @RequestMapping("/readBufferedReader") public void readBufferedReader (String fileName, HttpServletResponse response) throws IOException { File file=new File (fileName); FileInputStream fis=new FileInputStream (file); InputStreamReader isr=new InputStreamReader (fis); BufferedReader br=new BufferedReader (isr); String line; response.reset(); response.setContentType("application/octet-stream" ); response.addHeader("Content-Disposition" , "inline; filename=" + URLEncoder.encode(fileName,"UTF-8" )); PrintWriter pw=response.getWriter(); while ((line=br.readLine())!=null ){ System.out.println(line); pw.println(line); } br.close(); } @RequestMapping("/readScanner") public void readScanner (String fileName, HttpServletResponse response) throws IOException { Path path= Paths.get(fileName); Scanner scanner=new Scanner (path); System.out.println("使用Scanner读取文本文件....." ); response.reset(); response.setContentType("application/octet-stream" ); response.addHeader("Content-Disposition" , "attachment; filename=" + URLEncoder.encode(fileName,"UTF-8" )); PrintWriter pw=response.getWriter(); while (scanner.hasNextLine()){ pw.println(scanner.nextLine()); System.out.println(scanner.nextLine()); } scanner.close(); } @RequestMapping("/readUsingRandomAccessFile") public void readUsingRandomAccessFile (String fileName, HttpServletResponse response) throws IOException{ RandomAccessFile file = new RandomAccessFile (fileName, "r" ); String str; response.addHeader("Content-Disposition" , "attachment; filename=" + URLEncoder.encode(fileName,"UTF-8" )); PrintWriter out = response.getWriter(); while ((str = file.readLine()) != null ) { System.out.println("使用RandomAccessFile来实现断点续传读取/下载文件......" ); System.out.println(str); out.print(str); } file.close(); } @RequestMapping("/readUsingCommonsIo") public String readUsingCommonsIo (String fileName,HttpServletResponse response) throws IOException { File file = new File (fileName); response.reset(); response.setContentType("application/octet-stream" ); response.addHeader("Content-Disposition" , "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8" )); System.out.println("使用Commons-io读取文件......" ); System.out.println(FileUtils.readFileToString(file, StandardCharsets.UTF_8)); return FileUtils.readFileToString(file, StandardCharsets.UTF_8); } }
其他 回顾一下java的基础类型:
List: List 的特点是存取有序,可以存放重复的元素
List 类型可转化为 ArrayList 类型,不可转化为LinkedList类型
:movie_camera:ArrayList 类型:
ArrayList 实现了 List 接口,并且是基于数组实现的
ArrayList 在数组的基础上实现了自动扩容
LinkedList类型:链表
LinkedList 是由双向链表实现的,不支持随机存取,只能从一端开始遍历,直到找到需要的元素后返回;
任意位置插入和删除元素都很方便,因为只需要改变前一个节点和后一个节点的引用即可,不像 ArrayList 那样需要复制和移动数组元素;
因为每个元素都存储了前一个和后一个节点的引用,所以相对来说,占用的内存空间会比 ArrayList 多一些。
线程安全 :当多个线程 同时访问一个对象时,如果不用考虑这些线程 在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方进行任何其他的协调操作,调用这个对象的行为都可以获得正确的结果,那就称这个对象时线程安全 的。
指某个函数、函数库在多线程环境中被调用时,能够正确地处理多个线程之间的公用变量,使程序功能正确完成。
编程语言的动静强弱:
public、protected、private public:包内、包外.可以被所有其他类所访问
protected:包内.自身,子类及同一个包中类可以访问
private:本类,只能被自己访问和修改
参考链接 https://javabetter.cn/nio/moxing.html java的学习教程,看起来很精致
https://cloud.tencent.com/developer/article/1332131
https://javabetter.cn/gongju/choco.html#%E5%B0%8F%E7%BB%93 值得学习的好工具:Chocolatey:一款 GitHub 星标 8.2k+ 的 Windows 命令行软件管理器