Java基础学习
- 一、IO流进阶
- 1.1 缓冲流
- 1.1.1字节缓冲流
- 1.1.2 字符缓冲流
- 1.2 转换流
- 1.3 序列流
- 1.4 反序列化流 /对象操作输入流
- 1.4.1 序列化流/反序列化流的细节汇总
- 1.5 打印流
- 1.5.1 字节打印流
- 1.5.2 字符打印流
- 1.6 解压流、压缩流
- 1.7 Commons-io
- 1.8 hutool工具包
一、IO流进阶
1.1 缓冲流
体系图:
原理:底层自带了长度为8192的缓冲区提高性能
1.1.1字节缓冲流
方法名称 | 说明 |
---|---|
public BufferedInputStream(InputStream is) | 把基本流包装成高级流提高读取数据的性能 |
public BufferedOutputStream(Outputstream os) | 把基本流包装成高级流,提高写出数据的性能 |
import java.io.*;
//通过字节缓冲流来拷贝文件
public class Exercise5 {
public static void main(String[] args) throws IOException {
//创建读取的字节缓冲对象
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("E:\\Java文件夹\\words\\IOExrecise\\src\\sad\\a.txt"));
//创建书写的字节缓冲流
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("E:\\Java文件夹\\words\\IOExrecise\\src\\sad\\b.txt"));
//循环续写
int len;
while ((len = bis.read()) != -1){
bos.write((char)len);
}
//回收资源
bos.close();
bis.close();
}
}
在写的时候要注意:清理资源时,只需要清理字节缓冲流,里面的字节流在源码已经清理
提高效率的原理图:
主要是节约了读写的时间,在内存当中来回交换数据的时间可以忽略不计
1.1.2 字符缓冲流
方法名称 | 说明 |
---|---|
public BufferedReader(Reader r) | 把基本流变成高级流 |
public Bufferedwriter(writer r) | 把基本流变成高级流 |
字符缓冲流特有方法
package IO.IO_BufferedStream;
import java.io.*;
public class Dome2 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("src\\IO_Test\\aaaa.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("src\\IO_Test\\aaab.txt"));
//一次性输入一行
//String s = br.readLine();
//System.out.println(s);
String s ;
while ((s = br.readLine())!=null){
//输出的时候需要打印换行
bw.write(s);
bw.newLine();
}
bw.close();
br.close();
}
}
1.2 转换流
是字符流和字节流之间的桥梁
作用1: 指定字符集读写
(淘汰)
作用2:字节流想要使用字符流中的方法
InputStreamReader isr = new InputStreamReader(fis); BufferedReader br = new BufferedReader(isr);
package IO.IO_ConverStream;
import java.io.*;
import java.nio.charset.Charset;
public class Dome1 {
public static void main(String[] args) throws IOException {
/*
JDK11之后就淘汰了
把GBK编码规则的文件在UTF-8的环境中打印出来
//"C:\Users\20265\Desktop\ConverDome1.txt"
InputStreamReader isr =new InputStreamReader(new FileInputStream("C:\\Users\\20265\\Desktop\\ConverDome1.txt"),"GBK");
//得到里面的数据
int len;
while ((len = isr.read())!=-1){
System.out.print((char) len);
}
isr.close();
*/
//JDK11之后使用的方式
FileReader fr = new FileReader(new File("C:\\\\Users\\\\20265\\\\Desktop\\\\ConverDome1.txt"), Charset.forName("GBK"));
//得到里面的数据
int len;
while ((len = fr.read())!=-1){
System.out.print((char) len);
}
fr.close();
}
}
1.3 序列流
可以把java中的对象写到本地文件中
但是我们是看不懂的,但是可以通过反序列流来翻译
构造方法 | 说明 |
---|---|
public ObjectOutputstream(OutputStream out) | 把基本流包装成高级流 |
成员方法 | 说明 |
---|---|
public final void writeobject(object obi) | 把对象序列化(写出)到文件中去 |
序列化流的小细节:
使用对象输出流将对象保存到文件时会出现NotserializableException异常
解决方案: 需要让Javabean类实现Serializable接口
public class Student implements Serializable
package ObjectOutputstreams;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
//初识ObjectOutputstream
public class Dom1 {
public static void main(String[] args) throws IOException {
//创建Student对象
Student stu = new Student("华盛顿", 55);
//创建序列化流对象
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("E:\\Java文件夹\\words\\IOExrecise\\src\\sad\\ab\\e.txt"));
//写入数据
oos.writeObject(stu);
//清理资源
oos.close();
}
}
1.4 反序列化流 /对象操作输入流
可以把序列化到本地文件中的对象,读取到程序中来
构造方法 | 说明 |
---|---|
public ObjectInputstream(Inputstream out) | 把基本流变成高级流 |
成员方法 | 说明 |
---|---|
public object readobject() | 把序列化到本地文件中的对象,读取到程序中来 |
package ObjectOutputstreams;
import java.io.*;
//初识反序列化流
public class Dom2 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//创建反序列化流对象
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("E:\\Java文件夹\\words\\IOExrecise\\src\\sad\\ab\\e.txt"));
//读取数据
Object o = ois.readObject();
System.out.println(o);
//清理资源
ois.close();
}
}
1.4.1 序列化流/反序列化流的细节汇总
- 使用序列化流将对象写到文件时,需要让lavabean类实现Serializable接口。否则,会出现
NotSerializableException异常
- 序列化流写到文件中的
数据
是不能修改
的,一旦修改就无法再次读回来了 - 序列化对象后,修改了Javabean类,再次反序列化,会不会有问题?
会出问题,会抛出InvalidclassException异常 -
- 解决方案:
给Javabean类添加serialVersionUID (序列号、版本号)
- 解决方案:
- 如果一个对象中的某个成员变量的值不想被序列化,又该如何实现呢?
-
- 解决方案:
给该成员变量加transient关键字修饰,该关键字标记的成员变量不参与序列化过程
- 解决方案:
package IO.ObjectStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class Dome1 {
public static void main(String[] args) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("src\\IO\\ObjectStream\\Dome.txt"));
oos.writeObject(new Student());
oos.close();
}
}
package IO.ObjectStream;
import java.io.Serializable;
public class Student implements Serializable {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
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 String toString() {
return "Student{name = " + name + ", age = " + age + "}";
}
}
1.5 打印流
基本位置展现
分类:打印流一般是指: PrintStream,PrintWriter
两个类
特点
特点1:
打印流只操作文件目的地,不操作数据源
特点2:特有的写出方法可以实现,数据原样写出
例如:打印:97文件中:97 文件中:true打印: true
特点3:特有的写出方法可以实现自动刷新,自动换行打印一次数据 = 写出 + 行 + 刷新
1.5.1 字节打印流
字节流底层没有缓冲区,开不开自动刷新都一样
package MyPrintStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.nio.charset.Charset;
//创建
public class Dom1 {
public static void main(String[] args) throws FileNotFoundException {
//创建字节打印流
PrintStream ps = new PrintStream(new FileOutputStream("a.txt"), true, Charset.forName("UTF-8"));
//利用特殊方法写入数据
ps.println(97);
ps.printf("%s嘲笑了%s","张三","李四");
ps.println();
ps.print('c');
//清理资源
ps.close();
}
}
1.5.2 字符打印流
字符流底层有缓冲区,想要自动刷新需要开启
package MyPrintStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintStream;
import java.io.PrintWriter;
//创建字符打印流
public class Dom2 {
public static void main(String[] args) throws IOException {
//创建字符打印流
PrintWriter pw = new PrintWriter(new FileWriter("a.txt"), true);
//添加数据
pw.println(97);
pw.printf("%s嘲笑了%s","张三","李四");
pw.println();
pw.print('c');
//清理资源
pw.close();
}
}
总结:
1.打印流有几种?各有什么特点?
- 有字节打印流和字符打印流两种
- 打印流不操作数据源,只能操作目的地
- 字节打印流:默认自动刷新,特有的println自动换行
- 字符打印流:自动刷新需要开启,特有的println自动换行
1.6 解压流、压缩流
结构图:
解压本质: 把每一个
ZipEntry按照层级拷贝到本地另一个文件夹中
解压代码 :
package MyzipStream;
import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
//解压zip文件
public class MyZipStream {
public static void main(String[] args) throws IOException {
//创建一个需要解压的zip文件地址
File start = new File("E:\\Java文件夹\\words\\IOExrecise\\src\\sad.zip");
File dest = new File("E:\\");
//定义一个方法去实现压缩
Creat(start,dest);
}
private static void Creat(File start, File dest) throws IOException {
//创建zip对象压缩
ZipInputStream zip = new ZipInputStream(new FileInputStream(start));
//创建第三方变量来接收获取到的文件(夹)名称
ZipEntry entrys;
while ((entrys = zip.getNextEntry()) != null){
System.out.println(entrys);
//判断当前是文件还是文件夹
if (entrys.isDirectory()){
//是文件夹,就创建一个同名下的文件夹,接收数据
File file = new File(dest, entrys.toString());
file.mkdirs();
}else {
//是文件,就创建一个同名下的文件,接收数据
FileOutputStream fos = new FileOutputStream(new File(dest, entrys.toString()));
int len;
while ((len = zip.read()) != -1){
fos.write(len);
}
fos.close();
//表示当前文件夹已经处理完,开启下一个文件夹
zip.closeEntry();
}
}
zip.close();
}
}
压缩文件夹代码:
package MyzipStream;
import java.io.*;
import java.lang.annotation.Target;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
//压缩文件夹
public class MyZipOutStram2 {
public static void main(String[] args) throws IOException {
//需要压缩文件的位置
File start = new File("E:\\Java文件夹\\words\\IOExrecise\\src\\sad");
//压缩完存放zip的地址
File destParent = new File("E:\\Java文件夹\\words\\IOExrecise\\src\\");
File dest = new File(destParent, start.getName()+".zip");
//创建压缩流
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(dest));
//获取到上一级名称
String name = start.getName();
toZip(start,zos,name);
zos.close();
}
//创建一个方法去压缩文件夹
private static void toZip(File start, ZipOutputStream zos, String name) throws IOException {
//遍历源文件
File[] files = start.listFiles();
for (File file : files) {
//进行判断是文件还是文件夹
if (file.isFile()){
//是文件,进行下列操作
//创建ZipEntry对象在里面
ZipEntry entry = new ZipEntry(name +"\\"+ file.getName());
//将创建的ZipEntry放入到压缩包当中
zos.putNextEntry(entry);
//将数据读取加入到里面
FileInputStream fis = new FileInputStream(file);
int len;
while ((len = fis.read()) != -1){
zos.write(len);
}
//清理资源
fis.close();
zos.closeEntry();
}else {
//是文件夹,进行下列操作
//递归
toZip(file,zos,name+"\\"+file.getName());
}
}
zos.close();
}
}
1.7 Commons-io
Commons-io是apache开源基金组织提供的一组有关IO操作的
开源工具包作用:提高IO流的开发效率。
"食用"步骤:
- 在项目中创建一个文件夹: lib
- 将jar包复制粘贴到lib文件夹
- 右键点击jar包,选择Addas Library -> 点击OK
- 在类中导包使用
FileUtils类(文件/文件夹相关) | 说明 |
---|---|
static void copyFile(File srcFile,File destFile) | 复制文件 |
static void copyDirectory(File srcDir,File destDir)static void | 复制文件夹 |
copyDirectoryToDirectory(File srcDir,File destDir) | 复制文件夹 |
static void cleanDirectory(File directorv) | 清空文件 |
static String readFileToString(File file,Charset encoding) | 夹读取文件中的数据变成成字符串 |
static void write(File file,CharSequence data,String encoding) | 写出数据 |
static void deleteDirectory(File directory) | 删除文件夹 |
package commonsIOs;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
public class commonsIOsDom1 {
public static void main(String[] args) throws IOException {
//源数据地点
File start = new File("E:\\Java文件夹\\words\\IOExrecise\\src\\sad\\a.txt");
//拷贝到的地点
File dest = new File("E:\\Java文件夹\\words\\IOExrecise\\src\\sad\\copy.txt");
//复制文件
FileUtils.copyFile(start,dest);
//复制文件夹(将内容复制)
File dest1 = new File("E:\\Java文件夹\\words\\IOExrecise\\src\\sad\\copydir");
File start1 = new File("E:\\Java文件夹\\words\\IOExrecise\\src\\sad\\ab");
FileUtils.copyDirectory(start1,dest1);
//复制文件夹(将文件夹打包全部放到目的文件夹当中)
FileUtils.copyDirectoryToDirectory(start1,dest1);
//清空文件夹
FileUtils.cleanDirectory(dest1);
//删除文件夹
FileUtils.deleteDirectory(dest1);
}
}
1.8 hutool工具包
相关类 | 说明 |
---|---|
IoUtil | 流操作工具类 |
FileUtil | 文件读写和操作的工具类 |
FileTypeUtil | 文件类型判断工具类 |
WatchMonitor | 目录、文件监听 |
ClassPathResource | 针对ClassPath中资源的访问封装 |
FileReader | 封装文件读取 |
Filewriter | 封装文件写入 |
官网:https://hutool.cn/
API文档:https://apidoc.gitee.com/dromara/hutool/
中文使用文档: https://hutool.cn/docs/#/
相关方法
file: 根据参数创建一个file对象touch: 根据参数创建文件
writeLines: 把集合中的数据写出到文件中,覆盖模式。
appendLines: 把集合中的数据写出到文件中,续写模式。
readLines: 指定字符编码,把文件中的数据,读到集合中。
readutf8Lines: 按照UTF-8的形式,把文件中的数据,读到集合中
copy: 拷贝文件或者文件夹
package Myhutool;
import cn.hutool.core.io.FileUtil;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class Dom1 {
public static void main(String[] args) {
//添加File对象E:\Java文件夹\words\IOExrecise\a.txt
File file1 = FileUtil.file("E:\\", "Java文件夹\\words\\", "IOExrecise\\b.txt");
System.out.println(file1);//E:\Java文件夹\words\IOExrecise\a.txt
//根据参数来创建文件,文件的若不存在就会自动创建(无父级路径也可以)
File touch = FileUtil.touch(file1);
System.out.println(touch);
//将一个集合导入到文件当中
ArrayList<String> list = new ArrayList<>();
list.add("aaa");
list.add("aaa");
list.add("aaa");
FileUtil.writeLines(list,file1,"UTF-8");
//续写添加集合
FileUtil.appendLines(list,file1,"UTF-8");
//读数据,放到一个集合当中存储起来
List<String> list1 = FileUtil.readLines("E:\\Java文件夹\\words\\IOExrecise\\b.txt", "UTF-8");
System.out.println(list1);
}
}