Java File与IO流学习笔记
内存中存放的都是临时数据,但是在断电或者程序终止时都会丢失
而硬盘则可以长久存储数据,即使断电,程序终止,也不会丢失
File
File
是java.io.
包下的类,File
类的对象,用于代表当前操作系统的文件(可以是文件,或文件夹)- 可以获取文件信息(大小,文件名,修改时间)
- 判断文件的类型
- 创建文件或者文件夹
- 删除文件或者文件夹…
- 但是
File
类只能对文件本身进行操作,不能读写文件里面存储的数据
创建File对象
构造器 | 说明 |
---|---|
public File(String pathname) | 根据文件路径创建文件对象 |
public File(String parent,String child) | 根据父路径和子路径名字创建文件对象 |
public File(File parent,String child) | 根据父路径对应文件对象和子路径名字创建文件对象 |
案例
Main.java
import java.io.File;public class Main {public static void main(String[] args) {// 创建一个File对象,指代某个具体的文件File file = new File("C:\\Users\\huihui\\Desktop\\test.txt");System.out.println(file); // C:\Users\huihui\Desktop\test.txtSystem.out.println(file.length()); // 文件大小 0File file1 = new File("C:/Users/huihui/Desktop/test.txt");System.out.println(file1); // C:\Users\huihui\Desktop\test.txtFile file2 = new File("C:" + File.separator +"Users"+ File.separator + "huihui"+ File.separator + "Desktop"+ File.separator + "test.txt");System.out.println(file2); // C:\Users\huihui\Desktop\test.txt}
}
注意:File
对象也可以指代一个不存在的文件路径
Main.java
import java.io.File;public class Main {public static void main(String[] args) {File file = new File("aa/bb/cc");System.out.println(file.length()); // 0// 可以通过exists()方法判断文件是否存在System.out.println(file.exists()); // false}
}
路径
- 路径分为绝对路径(带盘符)和相对路径(不带盘符)
import java.io.File;public class Main {public static void main(String[] args) {// 据对路径,带盘符(是种写死的路径)File file = new File("D:\\Idea\\Codeing\\Day01\\src\\Demo\\Student.java");System.out.println(file); // D:\Idea\Codeing\Day01\src\Demo\Student.java// 相对路径,不带盘符(是种灵活的路径),默认回去当前工程下寻找文件File file1 = new File("src\\Demo\\Student.java");System.out.println(file1); // src\Demo\Student.java}
}
方法
判断文件类型,获取文件信息
案例
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.logging.SimpleFormatter;public class Main {public static void main(String[] args) {File file = new File("C:\\Users\\huihui\\Desktop\\test.txt");// 1. exists() 文件是否存在System.out.println(file.exists()); // true// 2. isFile() 判断是否是文件System.out.println(file.isFile()); // true// 3. isDirectory() 判断是否是文件夹System.out.println(file.isDirectory()); // false// 4. getName() 获取文件的名称包括后缀System.out.println(file.getName()); // test.txt// 5. length() 获取文件大小,返回字节个数System.out.println(file.length()); // 0// 6. laseModified() 获取文件的最后修改时间,默认返回的是时间戳// System.out.println(file.lastModified()); // 1696232257337SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");System.out.println(sdf.format(file.lastModified())); // 2023-10-02 15:37:37// 7. getPath() 获取创建文件对象时,使用的路径(你写的是什么路径,它就会返回什么路径)System.out.println(file.getPath()); // C:\Users\huihui\Desktop\test.txt// 8. getAbsolutePath() 获取绝对路径System.out.println(file.getAbsolutePath()); // C:\Users\huihui\Desktop\test.txt}
}
创建或者删除文件
案例
import java.io.File;
import java.io.IOException;public class Main {public static void main(String[] args) throws IOException {// 1. createNewFile() 创建一个新的文件,但是需要抛出异常。返回一个布尔值,如果存在,再创建就会返回falseFile file = new File("D:\\Idea\\Codeing\\Day01\\src\\Demo\\test.txt");System.out.println(file.createNewFile()); // true// 2. mkdir() 用于创建文件夹,但是只能创建一级文件夹。返回一个布尔值File f2 = new File("D:\\Idea\\Codeing\\Day01\\src\\Demo01");System.out.println(f2.mkdir()); // true// 3. mkdirs() 用于创建文件夹,可以创建多级文件夹File f3 = new File("D:/Idea/Codeing/Day01/src/Demo02/aa/bb");System.out.println(f3.mkdirs()); // true// 4. delete() 删除文件或者空文件,但是不能删除非空文件夹}
}
遍历文件夹
File
类提供的遍历文件夹的功能
方法 | 说明 |
---|---|
public String[] list() | 获取当前目录下所有的“一级文件名称”,返回一个字符串数组 |
public File[] listFiles() | 获取当前目录下所有的“一级文件对象”,返回一个文件对象数组 |
使用listFiles
注意事项:
- 当主调是文件,或者路径不存在时,返回
null
- 当主调是空文件夹时,返回一个长度为
0
的数组 - 当主调是一个有内容的文件夹时,将里面所有一级文件和文件夹的路径放在
File
数组中返回 - 当主调是一个文件夹,且里面有隐藏文件时,将里面所有文件和文件夹的路径放在
File
数组中返回,包含隐藏文件 - 当主调是一个文件夹,但是没有权限访问改文件夹时,返回
null
import java.io.File;
import java.util.Arrays;public class Main {public static void main(String[] args) {File file = new File("D:\\Idea\\Codeing\\Day01\\src\\Demo");// 1. public String[] list(): 获取当前目录下所有的 "一级文件名称"String[] list = file.list();System.out.println(Arrays.toString(list)); // [Student.java, test.txt]// 2. public File[] listFiles(): 获取当前目录下所有的 "一级文件对象"File[] files = file.listFiles();for (File file1 : files) {System.out.println(file1.isFile()); // true trueSystem.out.println(file1.getAbsolutePath()); // }}
}
递归
案例1:修改文件序号
import java.io.File;public class Main {public static void main(String[] args) {// 改变某个文件夹下的文件的序号,要求从19开始File f = new File("C:\\Users\\huihui\\Desktop\\test");// 1. 得到里面所有的文件对象File[] files = f.listFiles();for (File file : files) {String name = file.getName();String start = name.substring(0, name.indexOf("."));String end = name.substring(name.indexOf("."));String newName = (Integer.valueOf(start) + 18) + end;// 开始改名file.renameTo(new File(f, newName));}}
}
递归就是方法调用自身,递归一定要有一个结束条件,不然会无限递归,造成栈内存溢出(因为方法会进入栈内,每次调用都会进栈,但是一直没有出来的话,栈内存中的方法就会越来越多,就会溢出)
递归形式:
- 直接递归:方法自己调用自己
- 间接递归:方法调用其他方法,其他方法又回调方法自己
直接递归:
public class Main {public static void main(String[] args) {print(0);}// 直接递归:方法内部直接调用自己public static void print(int num) {if(num < 10) {System.out.println("打印输出");print(++num);}}
}
间接递归:
public class Main {public static void main(String[] args) {print(0);}public static void print(int num) {temp(num);}// 间接递归:别的方法调用自己public static void temp(int num) {if(num < 10) {System.out.println("打印输出");print(++num);}}
}
求阶乘
public class Main {public static void main(String[] args) {System.out.println(print(5)); // 120}// 计算结阶乘public static int print(int num) {if(num == 1) return 1;return print((num - 1)) * num;}
}
求1-n的和
public class Main {public static void main(String[] args) {System.out.println(sum(5)); // 15}// 计算1-n的和public static int sum(int num) {if(num == 1) return 1;return sum(num - 1) + num;}
}
猴子吃桃
猴子第一天摘下若干桃子,当即吃了一般,觉得好不过瘾,于是又多吃了一个。第二天又吃了前天剩余桃子数量的一般,觉得好不过瘾于是又多吃了一个。以后每天都是吃昨天剩余桃子数量的一半加一个。到第十天就只剩一个桃子了。问猴子摘了多少桃子?
f(x) - f(x)/2 - 1 = f(x + 1) // 昨天吃的减去前天的一半再减1,就是今天的
public class Main {public static void main(String[] args) {System.out.println(sum(1)); // 1534}// 计算1-n的和public static int sum(int num) {if(num == 10) return 1;return 2 * sum(num + 1) + 2;}
}
搜索文件
从D:
盘中,搜索QQScLauncher.exe
这个文件,找到后直接输出位置并打开
import java.io.File;
import java.io.IOException;public class Main {public static void main(String[] args) throws IOException {String path = getPath(new File("D:\\QQ\\Bin"), "QQScLauncher.exe");System.out.println(path); // C:\Users\huihui\Desktop\Test\test.txt}// 在c盘中找到 test.txt 文件,并输出位置public static String getPath(File dir, String fileName) throws IOException {if(dir == null || !dir.exists() || dir.isFile()) return "您输入的路径有误";// 首先遍历一级文件File[] files = dir.listFiles();// 判断当前目录下是否存在一级文件对象,一级是否可以拿到一级文件对象if(files != null && files.length > 0) {// 找到里面的文件并对比for (File file : files) {if(file.isFile() && file.getName().contains(fileName)) {// 打开文件 运行时对象Runtime runtime = Runtime.getRuntime();runtime.exec(file.getAbsolutePath());return file.getAbsolutePath();} else {getPath(file, fileName);}}}return "没有搜索到";}
}
删除非空文件夹
import java.io.File;public class Main {public static void main(String[] args) {delFile(new File("C:/Users/huihui/Desktop/kong"));}// 删除非空文件夹public static void delFile(File file) {// 判空,不存在或者传的为空则不处理if(!file.exists() || file == null) return;// 如果是文件,则直接删除if(file.isFile()) {file.delete();return;}// 存在且是文件夹File[] files = file.listFiles(); // 拿到下面的一级文件对象if(files == null) return; // 如果文件夹为空(没有权限),则不处理// 有权限,不为空的文件夹,遍历进行删除里面的内容,并且最后要把自己空的文件夹删除for (File f : files) {if(f.isFile()) { // 是文件,直接删除f.delete();} else { // 文件夹,接着递归delFile(f);}}file.delete(); // 最后别忘了把自己空的文件夹删除}
}
字符集
UTF-8
重点:
ASCII
字符集:只有英文,数字,符号等。占1个字节GBK
字符集:汉字占2个字节,英文,数字占1个字节UTF-8
字符集:汉字占3个字节,英文,数字占1个字节
字符编码时使用的字符集,喝解码时使用的字符集必须一致,否则就会出现乱码。
但是数字和英文一般都不会出现乱码,因为大部分字符集都要兼容ASCII
编码与解码
编码:把字符按照指定字符集编码成字节
解码:把字节按照指定字符集解码成字符
编码
方法名 | 说明 |
---|---|
byte[] getBayes() | 使用平台的默认字符集将改String编码为一系列字节,将结果存储到新的字节数组中 |
byte[] getBytes(String charsetName) | 使用指定的字符集将改String编码为一系列字节,将结果存储到新的字节数组中 |
import java.io.UnsupportedEncodingException;
import java.util.Arrays;public class Main {public static void main(String[] args) throws UnsupportedEncodingException {String str = "a的1";// 编码byte[] b1 = str.getBytes(); // 按照平台默认的字符编码规则编码System.out.println(Arrays.toString(b1)); // [97, -25, -102, -124, 49] 97:a 49:1 中间3个表示中文byte[] gbks = str.getBytes("GBK");System.out.println(Arrays.toString(gbks)); // [97, -75, -60, 49] gbk编码规则中中文是2个字节}
}
解码
方法名 | 说明 |
---|---|
String(byte[] bytes) | 通过使用平台的默认字符集解码,指定的字节数组,来构造新的String |
String(byte[] bytes, String charsetName) | 通过指定的字符集解码,指定的租界数组,来构造新的String |
import java.io.UnsupportedEncodingException;
import java.util.Arrays;public class Main {public static void main(String[] args) throws UnsupportedEncodingException {String str = "a的1";// 编码byte[] b1 = str.getBytes(); // 按照平台默认的字符编码规则编码System.out.println(Arrays.toString(b1)); // [97, -25, -102, -124, 49] 97:a 49:1 中间3个表示中文byte[] gbks = str.getBytes("GBK");System.out.println(Arrays.toString(gbks)); // [97, -75, -60, 49] gbk编码规则中中文是2个字节// 解码String s = new String(b1);System.out.println(s); // a的1String gbk = new String(gbks, "GBK");System.out.println(gbk); // a的1}
}
IO流
File
代表文件。而IO
流则可以读写数据
应用:
分类:
具体体系
输入输出都是以内存为基准的。程序在内存中运行,读写速度快,但是断电或者关闭就会清空数据。而硬盘(又叫磁盘)却可以永久存储数据,但是读写速度相对较慢。
输入:磁盘向内存中输入,也可以说内存读磁盘的数据
输出:内存向磁盘输出,也可以说内存向磁盘写入数据
内存和磁盘想要读写数据,就必须建立连接,而这个链接,就是流。类似与一个管道,只不过管道中流的是数据
数据又分为字节和字符,字节可以操作任意文件,而字符专注与操作各种文本文件(例如txt
文件.java
文件。。。)
输入流
- 然后按照文件的最小单位,又可以分为 字节输入流 和 字符输入流
字节输入流
- 用
InputStream
抽象类表示,比较常用的实现类是FileInputStream
作用:
- 以内存为基准,可以把磁盘文件中的数据以字节的ing是读入到内存中去(也就是读入带程序中去,因为程序放在内存中运行)
首先要创建管道,链接磁盘和内存
构造器 | 说明 |
---|---|
public FileInputStream(File file) | 创建字节输入流管道与源文件接通 |
public FileInputStream(String pathName) | 创建字节输入流管道与源文件接通 |
然后就可以Java
提供的方法进行读写了
方法名 | 说明 |
---|---|
public int read() | 每次读取一个字节返回,如果发现没有数据可读会返回-1 |
public int read(byte[] buffer) | 每次用一个字节数组去读取数据,返回字节数组读取了多少个字节,如果返现没有数据可读就会返回-1 |
测试文件
a测试文件
读取一个字节
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;public class Main {public static void main(String[] args) throws IOException {// 首先创建管道链接InputStream fis = new FileInputStream("D:\\Idea\\Codeing\\Day01\\src\\test.txt");// 读数据,一次只读一个字节int read = fis.read();System.out.println((char) read); // a// 最后别忘关闭通道(关闭流)fis.close();}
}
对上面的改造优化
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;public class Main {public static void main(String[] args) throws IOException {// 首先创建管道链接InputStream fis = new FileInputStream("D:\\Idea\\Codeing\\Day01\\src\\test.txt");// 读数据,一次只读一个字节int num; // 记录读取的字符while ((num = fis.read()) != -1) { // 不等于-1说明还有字节System.out.print((char) num); // a测试文件}// 最后别忘关闭通道(关闭流)fis.close();}
}
但是这种有问题:读取汉字的时候会乱码(因为utf8中,汉字是3个字节,这一次只能读一个,肯定会乱码),并且读取性能不高
读取多个字节
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;public class Main {public static void main(String[] args) throws IOException {// 首先创建管道链接InputStream fis = new FileInputStream("D:\\Idea\\Codeing\\Day01\\src\\test.txt");// 读数据,可以自己设定一次读多少个字节byte[] bytes = new byte[3];// 第一次读取// read(byte[] buffer) 返回的是一次读取了多少个字节个数。如果最后一次读取,不到3个字节,那有几个字节,它就是几int len = fis.read(bytes);System.out.println(len); // 3// bytes 中存放的就是读取的3个字节 ['a','1','2']System.out.println(new String(bytes)); // a12// 第二次读取int len2 = fis.read(bytes);System.out.println(len2); // 2 因为最后的字节只有2个,不到3个,所以为2// bytes 中存放的就是读取的最新的3个字节 ['3','4','2'] 最后一个因为没有,所以还是用的原先的System.out.println(new String(bytes)); // 342// 但是显然上面的是不对的,正确的应该是 34 不应该有2System.out.println(new String(bytes, 0, len2)); // 34 第2个参数是开始位置,第3个参数是结束位置}
}
进行循环优化
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;public class Main {public static void main(String[] args) throws IOException {// 首先创建管道链接InputStream fis = new FileInputStream("D:\\Idea\\Codeing\\Day01\\src\\test.txt");// 读数据,可以自己设定一次读多少个字节byte[] bytes = new byte[3];// 当读取的长度不为我们设定的3时,就说明读取到到最后一个了int len; // 每次读取的字节长度while (((len = fis.read(bytes)) != -1)) {String s = new String(bytes, 0, len);System.out.println(s); // a12 34}// 关闭管道fis.close();}
}
但是这种一次读取多个字节,汉字依然是无法读取的。但是文件肯定是要有读取中文的现象,那我们改如何解决中文乱码的问题呢?
其实有一种办法,就是定义一个与文件一样大的字节数组,一次性读取文件的全部字节,这样不会出现中文乱码了
解决中文乱码的方法1
读取的文件:
a中文
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;public class Main {public static void main(String[] args) throws IOException {// 首先创建管道链接InputStream fis = new FileInputStream("D:\\Idea\\Codeing\\Day01\\src\\test.txt");// 获取文件大小File file = new File("D:\\Idea\\Codeing\\Day01\\src\\test.txt");long length = file.length(); // 硬盘中的存储空间比较大,所以用的long类型// 读数据,可以自己设定一次读多少个字节byte[] bytes = new byte[(int)length]; // 内存里的存储空间比较小,所以用的int类型fis.read(bytes);System.out.println(new String(bytes)); // a中文fis.close();}
}
但是上面的方法,其实只能读取小的文件,超过int
范围的文件一次性就读取不了了
解决中文乱码的方法2
Java
官方为InputStrem
提供了方法,可以直接把文件的全部字节读取到一个字节数组中返回
public byte[] readAllbytes() throw IOException // 直接将当前字节输入流对应的文件对象的字节数据撞到一个字节数组返回
那上面方法1就可以进行下面的简化
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;public class Main {public static void main(String[] args) throws IOException {// 首先创建管道链接InputStream fis = new FileInputStream("D:\\Idea\\Codeing\\Day01\\src\\test.txt");// 获取全部字节文件,并返回到一个新的字节数组byte[] bytes = fis.readAllBytes();String s = new String(bytes);System.out.println(s); // a中文fis.close();}
}
字符输入流
- 用
Reader
抽象类表示,比较常用的实现类是FileReader
作用:
- 以内存为基准,可以把文件中的数据以字符的形式读入到内存中去
首先要创建管道,链接磁盘和内存
构造器 | 说明 |
---|---|
public FileReader(File file) | 创建字符输入流管道与文件接通 |
public FileReader(String pathName) | 创建字符输入流管道与源文件接通 |
然后就是方法进行写入
方法名 | 说明 |
---|---|
public int read() | 每次读取一个字符返回,如果发现没有数据可读会返回-1 |
public int read(char[] buffer) | 每次用一个字符数组去读取数据,返回字符数组读取了多少个字符,如果发现没有数据可读会返回-1 |
读取一个字符
import java.io.FileReader;
import java.io.IOException;public class Main {public static void main(String[] args) throws IOException {// 首先创建一个字符链接管道FileReader fr = new FileReader("D:\\Idea\\Codeing\\Day01\\src\\test.txt");// 然后开始读,一次读取一个字符int read = fr.read();System.out.println((char) fr.read());fr.close();}
}
上面的可以进行优化
import java.io.FileReader;
import java.io.IOException;public class Main {public static void main(String[] args) throws IOException {// 首先创建一个字符链接管道FileReader fr = new FileReader("D:\\Idea\\Codeing\\Day01\\src\\test.txt");// 然后开始读,一次读取一个字符int num;while ((num = fr.read()) != -1) {System.out.println((char) num);}fr.close();}
}
读取多个字符
import java.io.FileReader;
import java.io.IOException;public class Main {public static void main(String[] args) throws IOException {// 首先创建一个字符链接管道FileReader fr = new FileReader("D:\\Idea\\Codeing\\Day01\\src\\test.txt");char[] chars = new char[3];// 读取多个字符int len; // 记住每次读取了多少个字符while ((len = fr.read(chars)) != -1) {System.out.print(new String(chars,0,len)); // 被复制的内容}fr.close();}
}
输出流
- 然后按照文件的最小单位,又可以分为 字节输出流 和 字符输出流
字节输出流
- 用
OutputStream
抽象类表示,比较常用的实现类是FileOutputStream
作用:
- 以内存为基准,把内存中的数据以字节的形式写出到文件中去
首先要创建管道,链接磁盘和内存
构造器 | 说明 |
---|---|
public FileOutputStream(File file) | 创建字节输出流管道与源文件接通 |
public FileOutputStream(String filePath) | 创建字节输出流管道与源文件接通 |
public FileOutputStream(File file,boolean append) | 创建字节输出流管道与源文件对象接通,可追加数据 |
public FileOutputStream(String filePath,boolean append) | 创建字节输出流管道与源文件对象接通,可追加数据 |
然后就可以Java
提供的方法进行读写了
方法名 | 说明 |
---|---|
public void write(int a) | 写一个字节出去 |
public void write(byte[] buffer) | 写一个字节数组进去 |
public void write(byte[] buffer, int pos, int len) | 写一个字节数组的一部分进去 |
public void close() throw IOException | 关闭流 |
测试文件(空文件)
写入磁盘一个字节
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;public class Main {public static void main(String[] args) throws IOException {// 首先创建一个内存到硬盘的管道OutputStream fos = new FileOutputStream("D:\\Idea\\Codeing\\Day01\\src\\test.txt");// 往磁盘中写入一个字节fos.write(97); // 97 ASCII 表示afos.write('b'); // '' 单引号包裹的本来就是一个字节 byte类型fos.close();}
}
也是不能直接写入中文,因为在utf-8
编码中,一个中文是占3个字节,这里是只写入一个字节。所以写入中文会乱码,但是我们可以通过写入一个字节数组,来进行添加中文,通过调用String
的getBytes()
方法可以得到对应的字节数组
添加中文
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;public class Main {public static void main(String[] args) throws IOException {// 首先创建一个内存到硬盘的管道OutputStream fos = new FileOutputStream("D:\\Idea\\Codeing\\Day01\\src\\test.txt");// 往磁盘中写入一个字节fos.write(97); // 97 ASCII 表示afos.write('b'); // '' 单引号包裹的本来就是一个字节 byte类型// 添加中文 通过 String 的 getBytes() 方法可以直接得到一个字节数组byte[] bytes = "中文".getBytes();fos.write(bytes);fos.close();}
}
指定添加部分
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;public class Main {public static void main(String[] args) throws IOException {// 首先创建一个内存到硬盘的管道OutputStream fos = new FileOutputStream("D:\\Idea\\Codeing\\Day01\\src\\test.txt");// 往磁盘中写入一个字节fos.write(97); // 97 ASCII 表示afos.write('b'); // '' 单引号包裹的本来就是一个字节 byte类型// 添加中文 通过 String 的 getBytes() 方法可以直接得到一个字节数组byte[] bytes = "中文".getBytes();fos.write(bytes);// 当然,也可以指定添加的部分byte[] bytes2 = "添加前两个字".getBytes();fos.write(bytes2,0,6); // 一个中文是3个字节,所以添加前两个字,只需要添加6个字节fos.close();}
}
但是上面的添加,都会直接把原先文件里的东西全替代掉。有的时候,我们其实是不想让添加的内容把原先的内容替换掉的,所以就需要创建管道的时候指定是添加的(构造器的第二个参数为true
)
后面追加内容
测试文件
文件原本的内容
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;public class Main {public static void main(String[] args) throws IOException {// 首先创建一个内存到硬盘的管道,如果是追加内容,则需要把第二个参数设为trueOutputStream fos = new FileOutputStream("D:\\Idea\\Codeing\\Day01\\src\\test.txt",true);// 往磁盘中写入一个字节fos.write(97); // 97 ASCII 表示afos.write('b'); // '' 单引号包裹的本来就是一个字节 byte类型// 添加中文 通过 String 的 getBytes() 方法可以直接得到一个字节数组byte[] bytes = "中文".getBytes();fos.write(bytes);// 当然,也可以指定添加的部分byte[] bytes2 = "添加前两个字".getBytes();fos.write(bytes2,0,6); // 一个中文是3个字节,所以添加前两个字,只需要添加6个字节// 添加换行fos.write("\r\n".getBytes());fos.close();}
}
最后文件显示
文件原本的内容
ab中文添加
文件复制
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;public class Main {public static void main(String[] args) throws IOException {// 1. 首先创建一个输入流,把需要复制的内容用一个字节数组存储起来FileInputStream fis = new FileInputStream("D:\\Idea\\Codeing\\Day01\\src\\test.txt");// 1.1 创建一个存储字节的数组byte[] bytes = fis.readAllBytes();// 2. 把存起来的字符数组输出到指定的文件里去FileOutputStream fos = new FileOutputStream("D:\\Idea\\Codeing\\Day01\\src\\get.txt", true);fos.write(bytes);fis.close();fos.close();System.out.println("复制完成");}
}
但是上面这种,文件特别大的话,可能会出错。下面有一个更通用的方法
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;public class Main {public static void main(String[] args) throws IOException {// 1. 首先创建一个输入流,把需要复制的内容用一个字节数组存储起来FileInputStream fis = new FileInputStream("D:\\Idea\\Codeing\\Day01\\src\\test.txt");// 2. 把存起来的字符数组输出到指定的文件里去 这里后面不加true也是追加,因为同一个流不会覆盖FileOutputStream fos = new FileOutputStream("D:\\Idea\\Codeing\\Day01\\src\\get.txt", true);// 3. 创建一个字节数组,负责转移字节数据byte[] bytes = new byte[1024]; // 先给个1kb// 4. 然后开始循环写入int len; // 记录每次读取了多少个字节while ((len = fis.read(bytes)) != -1) {fos.write(bytes,0,len);}fis.close();fos.close();System.out.println("复制完成");}
}
字符输出流
- 用
Writer
抽象类表示,比较常用的实现类是FileWriter
- 字符输出流输出字符后,必须输出流,或者关闭流,写出去的数据才能生效
作用:
- 以内存为基准,可以把内存中的数据以字符的形式输出到磁盘中去
首先要创建管道,链接磁盘和内存
构造器 | 说明 |
---|---|
public FileWriter(File file) | 创建字符输出流管道与源文件对象接通 |
public FileWriter(String pathName) | 创建字符输出流管道与源文件路径接通 |
public FileWriter(File file,Boolean append) | 创建字节输出流管道与源文件对象接通,可追加数据 |
public FileWriter(String fillpath,boolean append) | 创建字节输出流管道与源文件路径接通,可追加数据 |
然后就是方法进行输出
方法名 | 说明 |
---|---|
void write(int c) | 每次写入一个字符,如果发现没有数据可写会返回-1 |
void write(String str) | 写一个字符串 |
void write(String str, int off, int len) | 写一个字符串的一部分 |
void write(char[] cbuf) | 写入一个字符数组 |
void write(char[] cbuf, int off, int len) | 写入字符数组的一部分 |
写入磁盘一个字符
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;public class Main {public static void main(String[] args) {File f = new File("D:\\Idea\\Codeing\\Day01\\src\\test.txt");try(// 创建链接管道Writer fw = new FileWriter(f);) {// 一次写入磁盘一个字符fw.write(97);fw.write('b');fw.write('中');// 或者写一个字符串fw.write("国");// 或者写入字符串的一部分fw.write("人123",0,1);} catch (IOException e) {throw new RuntimeException(e);}}
}
写入多个字符
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;public class Main {public static void main(String[] args) {File f = new File("D:\\Idea\\Codeing\\Day01\\src\\test.txt");try(// 创建链接管道Writer fw = new FileWriter(f);) {// 写入一个字符数组char[] chars = "1a中".toCharArray();fw.write(chars);// 直接写入一个字符串fw.write("几点开始");} catch (IOException e) {throw new RuntimeException(e);}}
}
关闭流
- 调用流的
close
方法即可关闭流的通道。但是有的时候,可能代码会出现一些问题,造成没法办法正常走到close
方法,所以就需要错误捕获
tryCatch
try { // 可能会出现错误的代码 } catch (异常类名 变量名) { // 错误处理 } finally { // 不管成功还是失败都一定会执行的 }
- 除非
JVM
终止(System.exit()
),不然finally
里的代码一定会执行的 - 作用:一般用在程序执行完成后进行资源的释放操作
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Objects;public class Main {public static void main(String[] args) {// 快捷键:选中代码 ctrl + alt + tFileInputStream fis = null;FileOutputStream fos = null;try {// 1. 首先创建一个输入流,把需要复制的内容用一个字节数组存储起来fis = new FileInputStream("D:\\Idea\\Codeing\\Day01\\src\\test.txt");// 2. 把存起来的字符数组输出到指定的文件里去 这里后面不加true也是追加,因为同一个流不会覆盖fos = new FileOutputStream("D:\\Idea\\Codeing\\Day01\\src\\get.txt", true);// 3. 创建一个字节数组,负责转移字节数据byte[] bytes = new byte[1024]; // 先给个1kb// 4. 然后开始循环写入int len; // 记录每次读取了多少个字节while ((len = fis.read(bytes)) != -1) {fos.write(bytes,0,len);}System.out.println("复制完成");} catch (IOException e) {throw new RuntimeException(e);} finally {try {if(Objects.isNull(fis)) fis.close();if(Objects.isNull(fos)) fos.close();} catch (IOException e) {throw new RuntimeException(e);}}}
}
tryWithResource
- 比
tryCatch
更简单 - 括号里面只能放资源对象,例如流对象,并且会自动关闭流
- 资源都会实现一个
AutoCloseable
接口,并且资源都会有一个close
方法,并且会自动调用
try(定义资源1; 定义资源2; …) { // 可能出现异常的代码; } carch(异常类名 变量名) { // 异常的处理代码; }
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;public class Main {public static void main(String[] args) {try(// 1. 首先创建一个输入流,把需要复制的内容用一个字节数组存储起来FileInputStream fis = new FileInputStream("D:\\Idea\\Codeing\\Day01\\src\\test.txt");// 2. 把存起来的字符数组输出到指定的文件里去 这里后面不加true也是追加,因为同一个流不会覆盖FileOutputStream fos = new FileOutputStream("D:\\Idea\\Codeing\\Day01\\src\\get.txt", true);) {// 3. 创建一个字节数组,负责转移字节数据byte[] bytes = new byte[1024]; // 先给个1kb// 4. 然后开始循环写入int len; // 记录每次读取了多少个字节while ((len = fis.read(bytes)) != -1) {fos.write(bytes,0,len);}System.out.println("复制完成");} catch (IOException e) {throw new RuntimeException(e);}}
}
缓冲流
- 对原始流进行包装,以提高原始流读写数据的性能
字节缓冲输入流
测试数据
abcd
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;public class Main {public static void main(String[] args) {File f = new File("D:\\IDEA\\code\\hello\\src\\test.txt");try(FileInputStream fis = new FileInputStream(f);InputStream bis = new BufferedInputStream(fis);) {byte[] bytes = new byte[3];int len;while ((len = bis.read(bytes)) != -1) { // 不为-1说明就有值System.out.print(new String(bytes, 0, len)); // abcd}} catch (Exception e){e.printStackTrace(); //打印错误信息}}
}
字节缓冲输出流
import java.io.*;public class Main {public static void main(String[] args) {File f = new File("D:\\IDEA\\code\\hello\\src\\test.txt");try(// 建立管道链接OutputStream os = new FileOutputStream(f,true);OutputStream bos = new BufferedOutputStream(os);) {// 一次写入磁盘一个字节bos.write(97); // 97 ASCII中是abos.write('b');// os.write('中'); // 添加中文是不行的,因为在utf8编码中,中文是3个字节,这里只添加一个,肯定不行// 一次写入磁盘多个字节byte[] bytes = "中国".getBytes();bos.write(bytes);// 一次写入指定个数的byte[] bytes1 = "abc".getBytes();bos.write(bytes1, 0, 2);} catch (Exception e){e.printStackTrace(); //打印错误信息}}
}
字符缓冲输入流
import java.io.*;public class Main {public static void main(String[] args) {File f = new File("D:\\IDEA\\code\\hello\\src\\test.txt");try(// 建立管道链接Reader fr = new FileReader(f);Reader br = new BufferedReader(fr);) {// 1. 一次读取一个字符int r1 = br.read();System.out.println(r1); // 99 ASCII中表示cSystem.out.println((char) r1); // c// 2. 一次读取指定次数的字符char[] chars = new char[4];int len;while ((len = br.read(chars)) != -1) { // 只要不为-1,就说明还有值String s = new String(chars, 0, len);System.out.print(s); // eshishuju}// 3. 一次读取多个字符,并且指定位置和个数int r2 = br.read(chars, 0, 3);System.out.println(r2); // -1 因为上面读完了} catch (Exception e){e.printStackTrace(); // 打印错误信息}}
}
字符缓冲输出流
import java.io.*;public class Main {public static void main(String[] args) {File f = new File("D:\\IDEA\\code\\hello\\src\\test.txt");try(// 建立管道链接Writer fw = new FileWriter(f);Writer bw = new BufferedWriter(fw);) {// 1. 一次写入磁盘一个字符bw.write(97);bw.write('b');bw.write('中');// 2. 一次写入一个字符数组char[] charArray = "你好呀".toCharArray();bw.write(charArray);// 3. 还可以直接写入字符串,这个就很方便呀bw.write("Java");// 4. 还可以指定起始位置和个数bw.write("Web",0,3);} catch (Exception e){e.printStackTrace(); // 打印错误信息}}
}
转换流
字符输入转换流
InputStreamReader
- 解决不同编码时,字符读取文本内容乱码的问题
- 解决思路:先获取文件的原始字节流,再按其真实的字符集编码转成字符输入流,这样字符输入流中的字符就不乱码了
构造器 | 说明 |
---|---|
public inputStreamReader(InputStream is) | 把原始的字节输入流,按照代码默认编码转成字符输入流(与直接用FileReader的效果一样) |
public InputStreamReader(InputStream is,String charset) | 把原始的字节输入流,按照指定字符集编码转成字符输入流 |
文件A GBK编码格式
中几点开始
import java.io.*;public class Main {public static void main(String[] args) {File f = new File("D:\\Idea\\Codeing\\Day01\\src\\test.txt");try(Reader br = new BufferedReader(new FileReader(f));) {// � 因为编译器默认编码是utf8,但是文件里面的编码是gbk 所以乱码了System.out.println((char) br.read());} catch (IOException e) {throw new RuntimeException(e);}}
}
解决办法就是字符输入转换流
import java.io.*;public class Main {public static void main(String[] args) {File f = new File("D:\\Idea\\Codeing\\Day01\\src\\test.txt");try(InputStream is = new FileInputStream(f);// 转成对应编码的字节输入流Reader isr = new InputStreamReader(is, "GBK");// 这样再操作就不会有乱码问题了Reader br = new BufferedReader(isr);) {int c;while ((c = br.read()) != -1) {System.out.print((char) c);}} catch (IOException e) {throw new RuntimeException(e);}}
}
字符输出转换流
OutputStreamWrite
- 可以控制写出去的字符使用什么字符集编码
- 解决思路:获取字节输出流,再按照指定的字符集编码将其转换为字符输出流,以后写出去的字符就会用该字符集编码了
构造器 | 说明 |
---|---|
public OutputStreamWriter(OutStream os) | 可以把原始的字节输出流,按照代码默认编码转换成字符输出流 |
public OutputStreamWriter(OutputStream os,String charset) | 可以把原始的字节输出流,按照指定字符集编码转成字符输出流 |
文件A GBK编码格式
啊
import java.io.*;public class Main {public static void main(String[] args) {File f = new File("D:\\Idea\\Codeing\\Day01\\src\\test.txt");try(Writer bw = new BufferedWriter(new FileWriter(f));) {bw.write("你好呀"); // 啊浣犲ソ鍛� 乱码了,因为写入的是utf8编码的字符} catch (IOException e) {throw new RuntimeException(e);}}
}
解决办法就是字符输出转换流
import java.io.*;public class Main {public static void main(String[] args) {File f = new File("D:\\Idea\\Codeing\\Day01\\src\\test.txt");try(OutputStream fos = new FileOutputStream(f, true);// 把原始的字节输入流转成固定格式的输出流Writer psw = new OutputStreamWriter(fos, "GBK");Writer bw = new BufferedWriter(psw);) {bw.write("你好呀"); // 啊你好呀} catch (IOException e) {throw new RuntimeException(e);}}
}
控制写的字符使用的字符集
有两种实现方法:
- 调用
String
提供的getBytes
方法
String d = “你好呀”; byte[] bytes = d.getBytes(“GBK”);
- 使用字符输出转换流实现
打印流
- 打印流可以实现更方便,更高效的打印数据出去,能实现打印啥出去就是啥
printStream
- 属于字节输出流
构造器 | 说明 |
---|---|
public PrintStream(OutputStream/File/String) | 打印流直接通向字节输出流/文件/文件路径 |
public PrintStream(String fileName,Charset charset) | 可以指定写出去的字符编码 |
public PrintStream(OutputStream out, boolean autoFlush) | 可以指定实现自动刷新 |
public PrintStream(OutputStream out, bollean autoFlush, String encoding) | 可以指定实现自动刷新,并可指定字符的编码 |
写数据的方法
方法名 | 说明 |
---|---|
public void println(Xxx xx) | 打印任意类型的数据出去,自带换行 |
public void write(int/byte[]/byte[]的一部分) | 可以支持写字节数据进去 |
基本使用
import java.io.*;public class Main {public static void main(String[] args) {File f = new File("D:\\Idea\\Codeing\\Day01\\src\\test.txt");try(PrintStream ps = new PrintStream(f);) {ps.println(97);ps.println('b');ps.println("你好呀"); // 97 \n b \n 你好呀} catch (IOException e) {throw new RuntimeException(e);}}
}
指定字符集
import java.io.*;
import java.nio.charset.Charset;public class Main {public static void main(String[] args) {File f = new File("D:\\Idea\\Codeing\\Day01\\src\\test.txt");try(// 指定写入的编码格式PrintStream ps = new PrintStream(f, Charset.forName("GBK"));) {ps.println(97);ps.println('b');ps.println("你好呀"); // 97 \n b \n 你好呀} catch (IOException e) {throw new RuntimeException(e);}}
}
PrintWriter
- 属于字符输出流
构造器 | 说明 |
---|---|
public PrintWriter(OutputStream/Writer/File/String) | 打印流直接通向字节输出流/字符输出流/文件/文件路径 |
public PrintWriter(String fileName,Charset charset) | 可以指定写出去的字符编码 |
public PrintWriter(OutputStream out/Writer, boolean autoFlush) | 可以指定实现自动刷新 |
public PrintWriter(OutputStream out, bollean autoFlush, String encoding) | 可以指定实现自动刷新,并可指定字符的编码 |
写数据的方法
方法名 | 说明 |
---|---|
public void println(Xxx xx) | 打印任意类型的数据出去,自带换行 |
public void write(int/String/char[]) | 可以支持写字符数据出去 |
基本使用
import java.io.*;public class Main {public static void main(String[] args) {File f = new File("D:\\Idea\\Codeing\\Day01\\src\\test.txt");try(PrintWriter pw = new PrintWriter(f);) {pw.println(97);pw.println('a');pw.println("你好呀"); // 97 \n b \n 你好呀} catch (IOException e) {throw new RuntimeException(e); }}
}
指定字符集
import java.io.*;public class Main {public static void main(String[] args) {File f = new File("D:\\Idea\\Codeing\\Day01\\src\\test.txt");try(PrintWriter pw = new PrintWriter(f,"GBK");) {pw.println(97);pw.println('a');pw.println("你好呀");} catch (IOException e) {throw new RuntimeException(e);}}
}
追加数据
- 因为
PrintStream
和PrintWriter
是高级流,所以不能直接追加数据,但是我们在调用构造器的时候,可以传入一个低级输出流,在低级输出流中可以指定追加
import java.io.*;public class Main {public static void main(String[] args) {File f = new File("D:\\Idea\\Codeing\\Day01\\src\\test.txt");try(PrintWriter pw = new PrintWriter(new FileOutputStream(f, true));) {pw.println(97);pw.println('a');pw.println("你好呀");} catch (IOException e) {throw new RuntimeException(e);}}
}
区别
- 打印数据的功能上一摸一样:都是使用方便,性能高效
PrintStream
继承字节输出流OutputStream
,因此支持字节数据的方法PrintWriter
继承字符输出流Writer
,因此支持字符数据的方法
应用
输出语句的重定向,可以把输出语句的打印位置改到某个文件中去
import java.io.*;public class Main {public static void main(String[] args) {System.out.println("会打印文件外");File f = new File("D:\\Idea\\Codeing\\Day01\\src\\test.txt");try(// PrintWriter pw = new PrintWriter(new FileOutputStream(f));PrintStream ps = new PrintStream(f);) {// 把系统默认的打印流对象改成自己设置的打印流System.setOut(ps);System.out.println("会打印在文件里");} catch (IOException e) {throw new RuntimeException(e);}}
}
数据流
- 操作的都是字节的
DataOutputStream
- 属于字节输出流,允许把数据和其类型一并写出去
构造器 | 说明 |
---|---|
public DataOutputStream(OutputStream out) | 创建新数据输出流包装基本的字节输出流 |
方法
方法 | 说明 |
---|---|
public final void writeByte(int v) throws IOException | 将byte类型的数据写入基本的字节输出流 |
public final void writeInt(int v) throws IOException | 将Int类型的数据写入基本的字节输出流 |
public final void writeDouble(Double v) throws IOException | 将Double类型的数据写入基本的字节输出流 |
public final void writeUtf(String str) throws IOException | 将字符串数据以UTF-8编码字节写入基本的字节输出流 |
public void write(int/byte[]/byte[]的一部分) | 支持写字节数据出去 |
案例
import java.io.*;public class Main {public static void main(String[] args) {File f = new File("D:\\Idea\\Codeing\\Day01\\src\\test.txt");try(OutputStream fps = new FileOutputStream(f);// 写入数据和其类型,就需要用到数据流DataOutputStream dos = new DataOutputStream(fps);) {// 写入一个字节dos.writeByte(97); // a// 写入一个数字dos.writeInt(97); // 97// 写入一个布尔dos.writeBoolean(true);// 写入一个小数dos.writeDouble(99.99);// 写入一个字符串dos.writeUTF("你好呀"); // a a@X�\(� 你好呀 这不是乱码,是有类型就这样} catch (IOException e) {throw new RuntimeException(e);}}
}
DataInputStream
- 属于字节输入流,用于读取数据输出流写出去的数据
构造器 | 说明 |
---|---|
public DataInputStream(InputStream is) | 创建新数据输入流包装基本的字节输出流 |
方法
方法 | 说明 |
---|---|
public final void readByte() throws IOException | 读取字节数据返回 |
public final int readInt() throws IOException | 读取int类型的数据返回 |
public final double readDouble() throws IOException | 读取double类型的数据返回 |
public final String readUtf() throws IOException | 读取字符串数据返回(UTF-8) |
public int readInt() / public int read(byte[]) | 支持读字节数据进来 |
案例:读的顺序要跟写的顺序一样
import java.io.*;public class Main {public static void main(String[] args) {File f = new File("D:\\Idea\\Codeing\\Day01\\src\\test.txt");try(InputStream fis = new FileInputStream(f);// 我们需要读取带有值和类型的,所以就需要用到数据输入流DataInputStream dis = new DataInputStream(fis);) {// System.out.println(dis.read()); // 97System.out.println(dis.readByte()); // 97System.out.println(dis.readInt()); // 97System.out.println(dis.readBoolean()); // trueSystem.out.println(dis.readDouble()); // 99.99System.out.println(dis.readUTF()); // 你好呀} catch (IOException e) {throw new RuntimeException(e);}}
}
序列化流
- 我们想把
Java
对象存进文件去,就需要用到对象序列化流 - 则反序列化就是把存进去的对象序列化读取出来
- 属于字节流
ObjectOutputStream
- 可以把
Java
对象进行序列化:把Java
对象存入到文件中去 transient
修饰的成员可以不参与对象序列化
构造器 | 说明 |
---|---|
public ObjectOutputStream(OutputStream out) | 创建对象字节输出流,包装基础的字节输出流 |
方法
方法名 | 说明 |
---|---|
public final void writeObject(Object o) throws IOException | 把对象写出去 |
案例
Student.java
package Demo;
import java.io.Serializable;// 注意:对象如果需要序列化,必须实现序列化接口
public class Student implements Serializable {private String name;private int age;// private double score;// transient 修饰,则这个成员变量将不参与序列化(因为有的时候,其实不想要某个属性展示的,例如密码)private transient double score;public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public double getScore() {return score;}public void setScore(double score) {this.score = score;}public Student() {}public Student(String name, int age, double score) {this.name = name;this.age = age;this.score = score;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +", score=" + score +'}';}
}
Main.java
import Demo.Student;
import java.io.*;public class Main {public static void main(String[] args) {Student zs = new Student("张三", 25, 100.00);File f = new File("D:\\Idea\\Codeing\\Day01\\src\\test.txt");try(OutputStream fos = new FileOutputStream(f);// 我们要写入对象,就需要用到对象序列化流ObjectOutputStream ois = new ObjectOutputStream(fos);) {ois.writeObject(zs);} catch (IOException e) {throw new RuntimeException(e);}}
}
ObjectInputStream
- 可以把
Java
对象进行反序列化:把存储在文件中的Java
对象读入到内存中来
构造器 | 说明 |
---|---|
public ObjectInputStream(InputStream is) | 创建对象字节输入流,包装基础的字节输入流 |
方法
方法名 | 说明 |
---|---|
public final Object readObject() | 把存储在文件中的Java对象读出来 |
案例
import Demo.Student;
import java.io.*;public class Main {public static void main(String[] args) {File f = new File("D:\\Idea\\Codeing\\Day01\\src\\test.txt");try(InputStream fis = new FileInputStream(f);// 我们想要读取存储在文件中的对象,就需要对象反序列化ObjectInputStream ois = new ObjectInputStream(fis);) {Student s1 = (Student) ois.readObject();System.out.println(s1);//Student{name='张三', age=25, score=0.0} 这里score并不参与序列化,所以为初始值} catch (Exception e) {e.printStackTrace();}}
}
实现一次多个对象序列化
- 用一个
ArrayList
集合存储多个对象,然后直接对集合进行序列化即可 ArrayList
集合已经实现了序列化接口
Student.java
package Demo;
import java.io.Serializable;// 注意:对象如果需要序列化,必须实现序列化接口
public class Student implements Serializable {private String name;private int age;// private double score;// transient 修饰,则这个成员变量将不参与序列化(因为有的时候,其实不想要某个属性展示的,例如密码)private transient double score;public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public double getScore() {return score;}public void setScore(double score) {this.score = score;}public Student() {}public Student(String name, int age, double score) {this.name = name;this.age = age;this.score = score;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +", score=" + score +'}';}
}
写入到磁盘
import Demo.Student;
import java.io.*;
import java.util.ArrayList;public class Main {public static void main(String[] args) {Student zs = new Student("张三", 25, 100.00);Student ls = new Student("李四", 26, 100.00);ArrayList<Student> students = new ArrayList<>();students.add(zs);students.add(ls);File f = new File("D:\\Idea\\Codeing\\Day01\\src\\test.txt");try(OutputStream fos = new FileOutputStream(f);// 我们要写入对象,就需要用到对象序列化流ObjectOutputStream ois = new ObjectOutputStream(fos);) {// 把整个ArrayList集合对象写进去,方便我们遍历集合去读ois.writeObject(students);} catch (IOException e) {throw new RuntimeException(e);}}
}
读取磁盘
import Demo.Student;
import java.io.*;
import java.util.ArrayList;public class Main {public static void main(String[] args) {File f = new File("D:\\Idea\\Codeing\\Day01\\src\\test.txt");try(InputStream fis = new FileInputStream(f);// 我们想要读取存储在文件中的对象,就需要对象反序列化ObjectInputStream ois = new ObjectInputStream(fis);) {ArrayList<Student> students = (ArrayList<Student>) ois.readObject();System.out.println(students); // [Student{name='张三', age=25, score=0.0}, Student{name='李四', age=26, score=0.0}]} catch (Exception e) {e.printStackTrace();}}
}
IO框架
- 框架就是解决某类问题,编写的一套类,接口等,可以理解成一个半成品,大多数框架都是第三方研发的
形式:
一般都是把类,接口等编译成class形式,再压缩成一个.jar结尾的文件发行出去
IO
框架封装了Java
提供的对文件,数据进行操作的代码,对外提供了更简单的方式来对文件进行操作,对数据进行读写等
Commons-io
- 是
apache
开源基金组织提供的一组有关IO
操作的小框架,目的是提高IO
流的开发效率
FileUtils类
FileUtils类提供的部分方法展示 | 说明 |
---|---|
public static void copyFile(File srcFile,File destFile) | 复制文件 |
public static void copyDirectory(File srcDir,File destDir) | 复制文件夹 |
public static void deleteDirectory(File directory) | 删除文件夹 |
public static String readFileToString(File file,String encoding) | 读数据 |
public static void writeStringToFile(File file,String data,String charname,boolean append) | 写数据 |
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.nio.charset.Charset;public class Main {public static void main(String[] args) {// FileUtilstry {// 拷贝文件FileUtils.copyFile(new File("D:\\Idea\\Codeing\\Day01\\src\\in.txt"),new File("D:\\Idea\\Codeing\\Day01\\src\\out.txt"));// 拷贝文件夹FileUtils.copyDirectory(new File("C:\\Users\\huihui\\Desktop\\in"),new File("C:\\Users\\huihui\\Desktop\\out"));// 删除文件夹(非空的也可以)FileUtils.deleteDirectory(new File("C:\\Users\\huihui\\Desktop\\out"));// 读数据String s = FileUtils.readFileToString(new File("D:\\Idea\\Codeing\\Day01\\src\\in.txt"));System.out.println(s); // 111 不推荐使用这个了// 写数据 不推荐使用这个了FileUtils.writeStringToFile(new File("D:\\Idea\\Codeing\\Day01\\src\\in.txt"), "添加进去");// 追加数据FileUtils.writeStringToFile(new File("D:\\Idea\\Codeing\\Day01\\src\\in.txt"),"追加的数据", Charset.forName("UTF-8"),true);} catch (Exception e) {e.printStackTrace();}}
}
IOUtils类
IOUtils类提供的部分方法展示 | 说明 |
---|---|
public static int copy(InputStream inputStream,outputStream outputStream) | 复制文件 |
public static int copy(Reader reader,Writer writer) | 复制文件 |
public static void write(String data,OutputStream output,String charsetName) | 写数据 |
其实Java
原生也提供了一些一行代码操作文件的处理(但是都没有成功,不知道为什么)
import java.nio.file.Files;
import java.nio.file.Path;public class Main {public static void main(String[] args) {try {// 拷贝文件// Files.copy(Path.of("Day01\\src\\in.txt"),Path.of("Day01\\src\\out.txt"));// 读文件// System.out.println(Files.readString(Path.of("Day01\\\\src\\\\in.txt"))); //} catch (Exception e) {e.printStackTrace();}}
}
相关文章:

Java File与IO流学习笔记
内存中存放的都是临时数据,但是在断电或者程序终止时都会丢失 而硬盘则可以长久存储数据,即使断电,程序终止,也不会丢失 File File是java.io.包下的类,File类的对象,用于代表当前操作系统的文件(可以是文…...

LabVIEW中PID控制的的高级功能
LabVIEW中PID控制的的高级功能 比例-积分-微分(PID)控制占当今控制和自动化应用的90%以上,主要是因为它是一种有效且简单的解决方案。虽然PID算法最初用于线性、时不变系统,但现在已经发展到控制具有复杂动力学的系统。在现实世界…...

STM32基于HAL库RT-Thread Demo测试
STM32基于HAL库RT-Thread Demo测试 🎈源码地址:https://github.com/RT-Thread/rt-thread/tree/master📌基于STM32CUBEMX中间件安装《基于 CubeMX 移植 RT-Thread Nano》📍环境搭建《使用 Env 创建 RT-Thread 项目工程》ǵ…...
萌新小白必做题(2)找素数
一.思路分析 先来看看素数的性质: 素数又称质数,是指除了1和本身外没有其它因数的自然数。素数有许多有趣的性质和应用,例如可以用于加密算法和数学证明等。比如2、3、5、7等都是素数,而4、6、8、9等则不是素数。素数的研究是数…...
《基于 Vue 组件库 的 Webpack5 配置》8.在生成打包文件之前清空 output(dist) 目录(两种方式)
方式一 如果 webpack 是 v5.20.0,直接使用属性 output.clean,配置如下: module.exports {//...output: {clean: true}, };方式二 如果使用较低版本,可以使用插件 clean-webpack-plugin: 先安装:npm…...

3、Kafka Broker
4.1 Kafka Broker 工作流程 4.1.1 Zookeeper 存储的 Kafka 信息 (1)启动 Zookeeper 客户端。 [hadoop102 zookeeper-3.5.7]$ bin/zkCli.sh(2)通过 ls 命令可以查看 kafka 相关信息。 [zk: localhost:2181(CONNECTED) 2] ls /kaf…...

数字孪生智慧建筑可视化系统,提高施工效率和建造质量
随着科技的不断进步和数字化的快速发展,数字孪生成为了建筑行业的一个重要的概念,被广泛应用于智能化建筑的开发与管理中。数字孪生是将现实世界的实体与数字世界的虚拟模型进行连接和同步,从而实现实时的数据交互和模拟仿真。数字孪生在建筑…...

SpringCloud: feign整合sentinel实现降级
一、加依赖: <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache…...
List<LinkedHashMap<String, String>>类型的数据转换为Map<String, List<String>>类型数据
import java.util.*;public class Main {public static void main(String[] args) {// 示例数据:List<LinkedHashMap>List<LinkedHashMap<String, String>> keyParamList new ArrayList<>();LinkedHashMap<String, String> map1 ne…...

react 学习 —— 16、使用 ref 操作 DOM
什么时候使用 ref 操作 DOM? 有时你可能需要访问由 React 管理的 DOM 元素 —— 例如,让一个节点获得焦点、滚动到它或测量它的尺寸和位置。在 React 中没有内置的方法来做这些事情,所以你需要一个指向 DOM 节点的 ref 来实现。 怎么使用 r…...

Qt planeGame day10
Qt planeGame day10 Game基本框架 qt中没有现成的游戏框架可以用,我们需要自己搭框架首先创建一个QGame类作为框架,这个基本框架里面应该有如下功能:游戏初始化 void init(const QSize& siez,const QString& title);游戏反初始化(…...

贪吃蛇项目实践
游戏背景: 贪吃蛇是久负盛名的游戏,它也和俄罗斯⽅块,扫雷等游戏位列经典游戏的⾏列。 实现基本的功能: 贪吃蛇地图绘制 蛇吃⻝物的功能 (上、下、左、右⽅向键控制蛇的动作) 蛇撞墙死亡 蛇撞⾃⾝死亡 计…...

【C++】哈希应用——海量数据面试题
哈希应用——海量数据面试题 一、位图应用1、给定100亿个整数,设计算法找到只出现一次的整数?2、给两个文件,分别有100亿个整数,我们只有1G内存,如何找到两个文件交集?(1)用一个位图…...

CUDA学习笔记(五)GPU架构
本篇博文转载于https://www.cnblogs.com/1024incn/tag/CUDA/,仅用于学习。 GPU架构 SM(Streaming Multiprocessors)是GPU架构中非常重要的部分,GPU硬件的并行性就是由SM决定的。 以Fermi架构为例,其包含以下主要组成…...

逻辑漏洞详解
原理: 没有固定的概念,一般都是不符合常识的情况。比如任意用户注册,短信炸弹,占用资源,交易支付、密码修改、密码找回、越权修改、越权查询、突破限制。 根据实际业务逻辑进行比对,购物的可以根据数量&a…...

MySQL——八、MySQL索引视图
MySQL 一、视图1、什么是视图2、为什么需要视图3、视图的作用和优点4、创建视图5、视图使用规则6、修改视图7、删除视图 二、索引1、什么是索引2、索引优缺点3、索引分类4、索引的设计原则5、创建索引5.1 创建表是创建索引5.2 create index5.3 ALTER TABLE 6、删除索引7、MySQL…...
力扣100097. 合法分组的最少组数(哈希+贪心)
题目描述: 给你一个长度为 n 下标从 0 开始的整数数组 nums 。 我们想将下标进行分组,使得 [0, n - 1] 内所有下标 i 都 恰好 被分到其中一组。 如果以下条件成立,我们说这个分组方案是合法的: 对于每个组 g ,同一…...

uniapp map地图实现marker聚合点,并点击marker触发事件
1.uniapp官方文档说明 2.关键代码片段 // 仅调用初始化,才会触发 on.("markerClusterCreate", (e) > {})this._mapContext.initMarkerCluster({enableDefaultStyle: false, // 是否使用默认样式zoomOnClick: true, // 点击聚合的点,是否…...

【Mysql】Mysql中的B+树索引(六)
概述 从上一章节我们了解到InnoDB 的数据页都是由7个部分组成,然后各个数据页之间可以组成一个双向链表 ,而每个数据页中的记录会按照主键值从小到大的顺序组成一个单向链表 ,每个数据页都会为存储在它里边儿的记录生成一个页目录 ÿ…...

【Dockerfile镜像实战】构建LNMP环境并运行Wordpress网站平台
这里写目录标题 一、项目背景和要求二、项目环境三、部署过程1)创建自定义网络2)部署NginxStep1 创建工作目录并上传相关软件包Step2 编写Dockerfile文件Step3 编写配置文件nginx.confStep4 创建nginx镜像Step5 运行容器 3)部署MysqlStep1 创…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...

CTF show Web 红包题第六弹
提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框,很难让人不联想到SQL注入,但提示都说了不是SQL注入,所以就不往这方面想了 先查看一下网页源码,发现一段JavaScript代码,有一个关键类ctfs…...

使用分级同态加密防御梯度泄漏
抽象 联邦学习 (FL) 支持跨分布式客户端进行协作模型训练,而无需共享原始数据,这使其成为在互联和自动驾驶汽车 (CAV) 等领域保护隐私的机器学习的一种很有前途的方法。然而,最近的研究表明&…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...
蓝桥杯 2024 15届国赛 A组 儿童节快乐
P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡,轻快的音乐在耳边持续回荡,小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下,六一来了。 今天是六一儿童节,小蓝老师为了让大家在节…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序
一、开发准备 环境搭建: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 项目创建: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1
每日一言 生活的美好,总是藏在那些你咬牙坚持的日子里。 硬件:OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写,"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...
土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等
🔍 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术,可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势,还能有效评价重大生态工程…...

Spring数据访问模块设计
前面我们已经完成了IoC和web模块的设计,聪明的码友立马就知道了,该到数据访问模块了,要不就这俩玩个6啊,查库势在必行,至此,它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据(数据库、No…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)
Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败,具体原因是客户端发送了密码认证请求,但Redis服务器未设置密码 1.为Redis设置密码(匹配客户端配置) 步骤: 1).修…...