IO流
1.IO流:存储和读取数据的解决方案
I:input O:output
2.IO流的作用
用于读写数据(本地文件,网络)
3.IO流按照流向可以分类那两种流
输出流:程序->文件
输入流:文件->程序
4.IO流按照操作文件的类型可以分类那两种流?
字节流:可以操作所有类型的文件
字符流:只能操作纯文本文件
5.什么是纯文本文件?
用windows系统自带的记事本打开并且能读懂的文件?
用windows系统自带的记事本打开并且能读懂的文件
txt文件,md文件,xml文件,lrc文件等等
IO流的体系
IO流分为:字节流和字符流
字节流分为:inputStream:字节输入流
outputStream:字节输出流
字符类分为:Reader:字符类输入
Writer:字符输出流
FileOutputStream
FileOutputStream:操作本地文件的字节输出流,可以把程序中的数据写到本地文件中,是字节流的基本流
书写步骤:1.创建字节流对象
2.写数据
3.释放资源
packagecom.cjj.mybytestream;
importjava.io.FileNotFoundException;
importjava.io.FileOutputStream;
importjava.io.IOException;
publicclassByteStreamDemo01 {
publicstaticvoidmain(String[] args) throwsIOException {
/*
FileOutputStream:操作本地文件的字节输出流,可以把程序中的数据写道本地文件中
书写步骤:
1.创建字节流对象
细节1:参数是字符串表示的路径或者是File对象都是可以的
细节2:如果文件不存在会创建一个新的文件,但是要保证父级路径
细节3:如果文件已经存在,则会清空文件
2.写数据
细节1:write方法的是参数,但是实际上写到本地文件夹中的是整数ASCII上的字符
3.释放资源
每次使用完流之后都有释放资源
要求:写出一段文字到本地文件中
*/
//1.创建对象
//写出:输出流OutputStream
//本地文件 File
FileOutputStreamfos=newFileOutputStream("D:\\workplace\\hema\\myio\\src\\com\\cjj\\mybytestream\\a.txt");
//2.写出数据
fos.write(97);
//3.释放资源
fos.close();
}
}
FileOutputStream写数据的三种方法
方法名称 | 说明 |
void write(int b) | 一次写一个字节数据 |
void write(byte[] b) | 一次性写一个字节的数组 |
void write(byte[] b,int off,int len) | 一次写一个字节数组的部分数据 |
packagecom.cjj.mybytestream;
importjava.io.FileNotFoundException;
importjava.io.FileOutputStream;
importjava.io.IOException;
publicclassByteStreamDemo03 {
publicstaticvoidmain(String[] args) throwsIOException {
/*
换行写:
再写出一个换行符就可以了
Windows:\r\n
Linux: \n
Mac: \r
细节:
在windows操作系统中,Java对回车换行进行了优化
虽然完整的是\n\r,但是我们写其中一个\r或者\n
Java也可以实现换行,因为java会在底层补全
不过建议写全
续写:
如果想要续写,打开续写开关即可
开关位置,创建对象的第二个参数
默认false:表示关闭续写,此时创建对象会清空文件
手动传递true:表示打开续写,此时创建对象不会清空文件
*/
//1.创建对象
FileOutputStreamfos=newFileOutputStream("D:\\workplace\\hema\\myio\\src\\com\\cjj\\mybytestream\\a.txt",true);
//2.写出数据
Stringstr="cjjzuishuai";
byte[] bytes1=str.getBytes();
fos.write(bytes1);
//换行符
Stringwrap="\r\n";
byte[] bytes3=wrap.getBytes();
fos.write(bytes3);
//写出第二个数据
Stringstr2="666";
byte[] bytes2=str2.getBytes();
fos.write(bytes2);
//释放资源
fos.close();
}
}
FileInputStream
FileInputStream:操作本地文件输入流,可以把本地文件中的数据读取到程序中
书写步骤:
1.创建字节流输入对象
2.读取数据
3.释放资源
packagecom.cjj.mybytestream2;
importjava.io.FileInputStream;
importjava.io.FileNotFoundException;
importjava.io.IOException;
publicclassByteStreamDemo02 {
publicstaticvoidmain(String[] args) throwsIOException {
/*
字节输入流循环读取
*/
//1.创建对象
FileInputStreamfis=newFileInputStream("D:\\workplace\\hema\\myio\\src\\com\\cjj\\mybytestream\\a.txt");
//2.循环读取
intb;
while ((b=fis.read()) !=-1) {
System.out.print((char)b);
}
//3.释放资源
fis.close();
}
}
拷贝文件
packagecom.cjj.mybytestream2;
importjava.io.FileInputStream;
importjava.io.FileNotFoundException;
importjava.io.FileOutputStream;
importjava.io.IOException;
publicclassByteStreamDemo03 {
publicstaticvoidmain(String[] args) throwsIOException {
/*
/*
文件拷贝
*/
//1。创建对象
FileInputStreamfis=newFileInputStream("D:\\workplace\\hema\\myio\\src\\com\\cjj\\mybytestream\\a.txt");
FileOutputStreamfos=newFileOutputStream("D:\\workplace\\hema\\myio\\src\\com\\cjj\\mybytestream\\b.txt");
//2.拷贝文件
intb;
while (((b=fis.read()) !=-1)) {
fos.write(b);
}
//3.释放资源
fos.close();
fis.close();
}
}
FileInputStream一次读多个字节
方法名称 | 说明 |
public int read() | 一次度一个字节数据 |
public int read(byte[] buffer) | 一次度一个字节数组数据 |
一次读一个字节数组的数据,每次读取会尽可能把数组装满
字符集
在计算机中,任意数据都是以二进制的形式存储的
计算机中最小的存储单元是一个字节
ASCII字符集中,一个英文占一个字节
简体中文版Windows,默认使用GBK字符集
GBK字符集完全兼容ASCII字符集
一个英文占一个字节,二进制第一位是0
一个中文占两个字节,二进制高位字节的第一位是1
UTF-8是字符集的一种编码方式
Unicode字符集的UTF-8编码格式
一个英文占一个字节,二进制第一位是0,转成十进制是正数
一个中文占三个字节,二进制第一位是1,第一个字节转成十进制是负数
如何不产生乱码?
1.不要用字节流读取文本文件
2.编码解码时使用同一个码表,同一个编码方式
Java中编码的方式
String类中的方法 | 说明 |
public byte[] getBytes() | 使用默认方法进行编码 |
public byte][] getBytes(String charsetName) | 使用指定方式进行编码 |
Java中的解码的方法
String类中的方法 | 说明 |
String(byte[] bytes) | 使用默认方式进行解码 |
String(byte[] bytes,String charsetName) | 使用指定方式进行解码 |
为什么会有乱码?
1.读取数据时未读完整整个汉字
2.编码和解码时的方式不统一
字符流:字符类的底层就是字节流
字符流=字节流+字符集
特点:输入流:一次读一个字节,遇到中文时,一次读多个字节
输出流:底层会把数据按照指定的编码方式进行编码,变成字节在写到文件中
使用场景:对于纯文本进行读写操作
FileReader
FileReader
1.创建字符输入流对象
构造方法 | 说明 |
public FileReader(File file) | 创建字符输入流关联本地文件 |
public FileReader(String pathname) | 创建字符输入流关联本地文件 |
2.读取数据
成员方法 | 说明 |
public int read() | 读取数据,读到末尾返回-1 |
public int read(char[] buffer) | 读取多个数据,读到末尾返回-1 |
细节1:按字节进行读取,遇到中文,一次读取多个字节,读取后解码,返回一个整数
细节2:读到文件末尾了,read方法返回-1
3.释放资源
关流:close
packagecom.cjj.mycharstream1;
importjava.io.FileNotFoundException;
importjava.io.FileReader;
importjava.io.IOException;
publicclassCharStreamDemo01 {
publicstaticvoidmain(String[] args) throwsIOException {
/*
第一步:创建对象
public FileReader(File file) 创建字符输入流关联本地文件
public FileReader(String pathname)创建字符输入流关联本地文件
第二步:读取数据
public int read() 读取数据,读到末尾返回-1
public int read(char[] buffer)读取多个数据,读到末尾返回-1
第三步:释放资源
close
*/
//1.创建对象并关联本地文件
FileReaderfr=newFileReader("D:\\workplace\\hema\\myio\\src\\com\\cjj\\mybytestream\\a.txt");
char[] len=newchar[2];
/*int b;
while ((b=fr.read(len))!=-1) {
//read(len):读取数据,解码,强转三步合并了,并强转之后的字符放到数组当中
//空参read+强转类型转换
System.out.print(new String(len,0,b));
}*/
intb;
while ((b=fr.read())!=-1) {
//2.读取数据
//字符流的底层也是字节流,默认也是一个字节一个字节的读取的
//如果遇到一个中文就会一次读取多个,GBK一次读两个字节,UTF-8一次读三个字节
//read()细节
//1.read():默认也是一个字节一个字节读取的,如果遇到中文就会一次读取多个
//2.在读取之后,方法的底层还会进行解码并转成十进制
// 最终把这个十进制作为返回值
// 这个十进制的数据也表示在字符集上的数字
System.out.print((char)b);
}
//3.释放资源
fr.close();
}
}
FileWriter
FileWriter构造方法
构造方法 | 说明 |
public FileWriter(File file) | 创建字符输出流关联本地文件 |
public FileWriter(String pathname) | 创建字符输出流关联本地文件 |
public FileWriter(File file,boolean append) | 创建字符输出流关联本地文件,续写 |
public FileWriter(String pathname,boolean append) | 创建字符输出流关联本地文件,续写 |
FileWriter成员方法
成员方法 | 说明 |
void write(int c) | 写出一个字符 |
void write(String str) | 写出一个字符串 |
void write(String str,int off,int len) | 写出一个字符串的一部分 |
void write(char[] cbuf) | 写出一个字符数组 |
void write(char[] cbuf,int off,int len) | 写出字符数组的一部分 |
FileWriter书写细节
1。创建字符输出流对象
细节1:参数是字符串表示的路径或者File对象都是可以的
细节2:如果文件不存在会创建一个新的文件,但是要保证父级路径是存在的
细节3:如果文件已经存在,则会清空文件,如果不像清空可以打开续写开关
2.写数据
细节:如果write方法的参数是整数,但是实际上写到本地文件中的整数在字符集上对应的字符
3.释放资源
细节:每次使用完流之后都要释放资源
字符流原理解析
1.创建字符输入流对象
底层:关联文件,并创建缓冲区(长度为8192的字节数组)
2.读取数据
底层:1.判断缓冲区中是否有数据可以领取
2.缓冲区没有数据:就从文件中获取数据,装到缓冲区中,每次尽可能装满缓冲区
如果文件中也没有数据了,返回-1
3.缓冲区:就从缓冲区中读取
空参的read方法:一次读取一个字节,遇到中文一次读取多个字节,把字节解码并转成十进制返回
有参的read方法:把读取字节,解码,强转三步合并了,强转之后的字符放到数组中
字节缓冲流
方法名称 | 说明 |
public BufferedInputStream(InputStream is) | 把基本流包装成高级流,提高读取数据的性能 |
public BufferedOutPutStream(OutputStream) | 把基本流包装成高级流,提高写出数据的性能 |
原理:底层自带了长度为8192的缓冲区提高性能
字符缓冲流构造方法
方法名称 | 说明 |
public BufferedReader(Reader r) | 把基本流变成高级流 |
public BufferedWriter(writer r) | 把基本流变成高级流 |
字符缓冲流特有的方法
字符缓冲输入流特有方法 | 说明 |
public String readLine() | 读取一行数据,如果没有数据可读了,会返回null |
字符缓冲输出流特有方法 | 说明 |
public void newLine() | 跨平台的换行 |
总结:
缓冲流有几种
字节缓冲输入流:BufferedInputStream
字节缓冲输出流:BufferedOutputStream
字符缓冲输入流:BufferedReader
字符缓冲输出流:BufferedWriter
缓冲流为什么能提高性能?
缓冲流自带长度为8192的缓冲区
可以显著提高字节流的读写性能
对于字符流提升不明显,对于字符缓冲流而言关键点是两个特有的方法
字符缓冲流两个特有方法是什么?
字符缓冲输入流:BufferedReader:readLine()
字符缓冲输出流:BufferWriter:newLine()
转换流
转换流:是字符流和字节流之间的桥梁
作用:字节流想要使用字符流中的方法
packagecom.cjj.myconvertstream;
importjava.io.*;
importjava.nio.charset.Charset;
publicclassConverStreamDemo01 {
publicstaticvoidmain(String[] args) throwsIOException {
/*
利用转换流按照字符编码读取(了解)
*/
/*//1.创建对象并指定字符编码
InputStreamReader isr = new InputStreamReader(new FileInputStream("D:\\workplace\\hema\\myio\\src\\com\\cjj\\myconvertstream\\gbkfile.txt"), "UTF-8");
//2.读取数据
int ch;
while ((ch = isr.read()) != -1) {
System.out.print((char) ch);
}
isr.close();*/
FileReaderfr=newFileReader("D:\\workplace\\hema\\myio\\src\\com\\cjj\\myconvertstream\\gbkfile.txt", Charset.forName("UTF-8"));
//2.读取数据
intb;
while((b=fr.read())!=-1){
System.out.print((char)b);
}
}
}
packagecom.cjj.myconvertstream;
importjava.io.FileOutputStream;
importjava.io.FileWriter;
importjava.io.IOException;
importjava.io.OutputStreamWriter;
importjava.nio.charset.Charset;
publicclassConverStreamDemo02 {
publicstaticvoidmain(String[] args) throwsIOException {
/*
利用转换流按照指定字符编码写出
*/
/*//1.创建转换流的对象
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("D:\\workplace\\hema\\myio\\src\\com\\cjj\\myconvertstream\\gbkfile.txt"),"UTF-8");
//2.写出数据
osw.write("岳飞");
//3.释放资源
osw.close();*/
FileWriterfw=newFileWriter("D:\\workplace\\hema\\myio\\src\\com\\cjj\\myconvertstream\\gbkfile.txt", Charset.forName("UTF-8"));
fw.write("满江红\n"+
"怒发冲冠,凭阑处、潇潇雨歇。\n"+
"抬望眼,仰天长啸,壮怀激烈。\n"+
"三十功名尘与土,八千里路云和月。\n"+
"莫等闲、白了少年头,空悲切。\n"+
"靖康耻,犹未雪。\n"+
"臣子恨,何时灭。\n"+
"驾长车,踏破贺兰山缺。\n"+
"壮志饥餐胡虏肉,笑谈渴饮匈奴血。\n"+
"待从头、收拾旧山河,朝天阙。");
fw.close();
}
}
packagecom.cjj.myconvertstream;
importjava.io.FileReader;
importjava.io.FileWriter;
importjava.io.IOException;
importjava.nio.charset.Charset;
publicclassConverStreamDemo03 {
publicstaticvoidmain(String[] args) throwsIOException {
/*
*/
//1.创建转换流对象
FileReaderfr=newFileReader("D:\\workplace\\hema\\myio\\src\\com\\cjj\\myconvertstream\\gbkfile.txt", Charset.forName("UTF-8"));
FileWriterfw=newFileWriter("D:\\workplace\\hema\\myio\\src\\com\\cjj\\myconvertstream\\gbkfile.txt",Charset.forName("UTF-8"));
intb;
while((b=fr.read())!=-1){
fw.write(b);
}
fw.close();
fr.close();
}
}
package com.cjj.myconvertstream;
import java.io.*;
public class ConverStreamDemo04 {
public static void main(String[] args) throws IOException {
/*
利用字节流读取文件中的数据,每次读取一整行,而且不能出现乱码
//1.字节流在读取中文的时候,是会出现乱码的,但是字符流可以搞定
//2.字节流里面是没有读取一整行的方法的,只有字符缓冲流才能搞定
*/
/*FileInputStream fis = new FileInputStream("D:\\workplace\\hema\\myio\\src\\com\\cjj\\myconvertstream\\gbkfile.txt");
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr);
String str = br.readLine();
System.out.println(str);
br.close();*/
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("D:\\workplace\\hema\\myio\\src\\com\\cjj\\myconvertstream\\gbkfile.txt")));
String str = br.readLine();
System.out.println(str);
br.close();
}
}
总结:
1.转换流的名字是什么?
字符转换输入流:InputStreamReader
字符转换输出流:OutputStreamWriter
2.转换流的作用是什么?
指定字符集读写数据(JDK11之后以淘汰)
字节流想要使用字符流中的方法
序列化流/对象操作输出流
可以把java中的对象写到本地文件中
构造方法 | 说明 |
public ObjectOutputStream(OutputStream out) | 把基本流包装成高级流 |
成员方法 | 说明 |
public final void writeObject(Object obj) | 把对象序列化(写出)到文件中去 |
使用对象输出流将对象保存到文件时会出现NotSerializableException异常
解决方案:需要让Javabean类实现Serializable接口
packagecom.cjj.myobjectstream;
importjava.io.FileOutputStream;
importjava.io.IOException;
importjava.io.ObjectOutputStream;
publicclassObjectStreamDemo01 {
publicstaticvoidmain(String[] args) throwsIOException {
/*
需求:
利用序列化流/对象操作输出流,把一个对象写道本地文件中
构造方法
public ObjectOutputStream(OutputStream out)把基本流包装成高级流
成员方法
public final void writeObject(Object obj)把对象序列化(写出)到文件中去
*/
//1.创建对象
Students1=newStudent("zhangsan",15);
//2.创建序列号流对象
ObjectOutputStreamos=newObjectOutputStream(newFileOutputStream("D:\\workplace\\hema\\myio\\src\\com\\cjj\\myobjectstream\\c.txt"));
//3.写出数据
os.writeObject(s1);
//4.释放资源
os.close();
}
}
package com.cjj.myobjectstream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
public class ObjectStreamDemo02 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
/*
反序列化流读取对象
*/
//1.创建反序列流对象
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\workplace\\hema\\myio\\src\\com\\cjj\\myobjectstream\\c.txt"));
Object o = ois.readObject();
System.out.println(o);
ois.close();
}
}
private static final long serialVersionUID = -1398385231815634338L;//添加版本号
//transient:瞬态关键字
//作用:不会把当前属性序列号到本地文件当中
private transient String address;
序列化细节汇总
1.使用序列化流将对象写到文件时,需要让javabean类实现Serializable接口
否则,会出现NotSerializableException异常
2.序列化流写道文件中的数据是不能修改的,一旦修改就无法再次读回来了
3.序列化对象后,修改了Javabean类,再次反序列化,会不会有问题?
会出现问题,会抛出InvalidClassException异常
解决方法:给javabean类添加serialVersionUID(序列号,版本号)
4.如果一个对象中的某个成员变量的值不想被序列化,又该如何实现?
解决方法:给该成员变量加transient关键字修饰,该关键字标记的成员变量不参与序列化过程
packagecom.cjj.myobjectstream;
importjava.io.*;
importjava.util.ArrayList;
importjava.util.Collections;
publicclassTest01 {
publicstaticvoidmain(String[] args) throwsIOException, ClassNotFoundException {
/*
需求:
将多个自定义对象序列化到文件中,但是对象个数不确定,该如何操作呢
*/
//1.序列化多个对象
Student s1=newStudent("zhangsan",19,"南京");
Student s2=newStudent("lisi",18,"上海");
Student s3=newStudent("wangwu",18,"北京");
ArrayList<Student>list=newArrayList<>();
Collections.addAll(list,s1,s2,s3);
//2.创建序列化对象
ObjectOutputStreamoos=newObjectOutputStream(newFileOutputStream("D:\\workplace\\hema\\myio\\src\\com\\cjj\\myobjectstream\\c.txt"));
oos.writeObject(list);
oos.close();
//3.读取
ObjectInputStreamois=newObjectInputStream(newFileInputStream("D:\\workplace\\hema\\myio\\src\\com\\cjj\\myobjectstream\\c.txt"));
Objecto=ois.readObject();
System.out.println(o);
ois.close();
}
}
打印流
分类:打印流一般是指:PrintStream,PrintWrite两个类
特点1:打印流只操作文件的目的地
特点2:特有的写出方法可以实现,数据原样写出
特点3:特有是的写出方法,可以实现自动刷新,自动换行
打印一次数据=写出+换行+刷新
字节打印流
构造方法 | 说明 |
public PrintStream(OutputStream/File/String) | 关联字节输出流/文件/文件路径 |
public PrintStream(String fileName,Charset charset) | 指定字符编码 |
public PrintStream(OutputStream out,boolean autoFlush) | 自动刷新 |
public PrintStream(OutputStream out,boolean autoFlush,String enconding) | 指定字符编码且自动刷新 |
字节流底层没有缓冲区,开不开自动刷新都一样
成员方法 | 说明 |
public void write(int b) | 常规方法:规则跟之前的一样,将指定的字节写出 |
public void println(Xxx xx) | 特有方法:打印任意数据,自动刷新,自动换行 |
public void print(Xxx xx) | 特有方法:打印任意数据,不换行 |
public void printf(String format,Object...args) | 特有方法:带有占位符的打印语句,不换行 |
packagecom.cjj.myprintstream;
importjava.io.FileNotFoundException;
importjava.io.FileOutputStream;
importjava.io.PrintStream;
importjava.io.UnsupportedEncodingException;
publicclassPrintStreamDemo01 {
publicstaticvoidmain(String[] args) throwsFileNotFoundException, UnsupportedEncodingException {
/*
字节打印流
构造方法
public PrintStream(OutputStream/File/String)关联字节输出流/文件/文件路径
public PrintStream(String fileName,Charset charset)指定字符编码
public PrintStream(OutputStream out,boolean autoFlush)自动刷新
public PrintStream(OutputStream out,boolean autoFlush,String enconding)指定字符编码且自动刷新
成员方法
public void write(int b)常规方法:规则跟之前的一样,将指定的字节写出
public void println(Xxx xx)特有方法:打印任意数据,自动刷新,自动换行
public void print(Xxx xx)特有方法:打印任意数据,不换行
public void printf(String format,Object...args)特有方法:带有占位符的打印语句,不换行
*/
//1.创建字节打印流对象
PrintStreamps=newPrintStream(newFileOutputStream("D:\\workplace\\hema\\myio\\src\\com\\cjj\\myprintstream\\a.txt"),true,"UTF-8");
//2.写出数据
ps.println(97);
ps.println(true);
ps.printf("%s爱上了%s","阿珍","阿强");
//3.释放资源
ps.close();
}
}
字符打印流
字符流底层有缓冲区,想要自动刷新需要开启
构造方法 | 说明 |
public PrintWriter(Write/File/String) | 关联字节输出流 |
public PrintWriter(String filename,Charset charset) | 指定字符编码 |
public PrintWriter(Write w,boolean autoFlush) | 自动刷新 |
public PrintWriter(OutputStream out,boolean autoFlush,Charset charset) | 指定字符编码且自动刷新 |
成员方法 | 说明 |
public void write(...) | 常规方法:规则跟之前的一样,写出字节或字符串 |
public void println(Xxx xx) | 特有方法:打印任意类型的数据并且不换行 |
public void print(Xxx xx) | 特有方法:打印任意类型的数据,不换行 |
public void printf(String format,Object...args) | 特有方法:带有占位符的打印语句 |
package com.cjj.myprintstream;
import java.io.PrintStream;
public class PrintStreamDemo02 {
public static void main(String[] args) {
/*
打印流的应用场景
*/
System.out.println("123");
//获取打印流的对象,此打印流在虚拟机启动的时候,由虚拟机创建,默认指向控制台
//特殊的打印流。系统中的标准输出流,是不能关闭的,在系统中是唯一的
PrintStream ps = System.out;
//调用打印流中的方法println
//写出数据,自动换行,自动刷新
ps.println("123");
}
}
总结:
1.打印流有几种?各有什么特点?
有字节打印流和字符打印流两种
打印流不操作数据源,只能操作目的地
字节打印流:默认自动刷新,特有的println自动换行
字符打印流:自动刷新需要开启,特有的println自动换行
解压缩流/压缩流
解压本质:把每一个ZipEntry按照层级拷贝到本地另一个文件夹中
解压
packagecom.cjj.myzipstream;
importjava.io.*;
importjava.util.zip.ZipEntry;
importjava.util.zip.ZipInputStream;
publicclassZipStreamDemo01 {
publicstaticvoidmain(String[] args) {
//1.创建一个File表示要解压的压缩包
Filesrc=newFile("D:\\aaa.zip");
//2.创建一个File表示解压的目的地
Filedest=newFile("D:\\");
}
//定义一个方法用来解压
publicstaticvoidunzip(Filesrc, Filedest) throwsIOException {
//解压的本质:把压缩包里面的每一个文件或者文件夹读取出来,按照层级拷贝到目的地当中
//创建一个解压缩流用来读取压缩包中的数据
ZipInputStreamzip=newZipInputStream(newFileInputStream(src));
//要先获取到压缩包里面的每一个zipentry对象
ZipEntryentry;
while ((entry=zip.getNextEntry()) !=null) {
System.out.println(entry);
//文件夹:需要在目的地dest处创建一个同样的文件夹
//文件:需要读取到压缩包中的文件,并把它存放到目的地dest文件夹中(按照层级目录进行存放)
if (entry.isDirectory()) {
//文件夹,需要在目的地dest处创建一个同样的文件夹
Filefile=newFile(dest, entry.toString());
file.mkdirs();
} else {
//文件:需要读取到压缩包中的文件,并把它存放到目的地dest文件夹中(按照层级目录进行存放)
FileOutputStreamfos=newFileOutputStream(newFile(dest, entry.toString()));
intb;
while ((b=zip.read()) !=-1) {
//写到目的地
fos.write(b);
fos.close();
}
}
zip.closeEntry();
}
zip.close();
}
}
压缩
压缩本质:把每一个(文件/文件夹)看成ZipEntry对象放到压缩包中
//压缩文件
packagecom.cjj.myzipstream;
importjava.io.*;
importjava.util.zip.ZipEntry;
importjava.util.zip.ZipInputStream;
importjava.util.zip.ZipOutputStream;
publicclassZipStreamDemo02 {
publicstaticvoidmain(String[] args) throwsIOException {
/*
压缩流
需求:把D:\\a.txt打包成一个压缩包
*/
//1.创建File对象表示要压缩的文件
Filefile=newFile("D:\\workplace\\hema\\myio\\src\\com\\cjj\\myzipstream\\a.txt");
//2.创建对象来表示压缩包的位置
Filedest=newFile("D:\\workplace\\hema\\myio\\src\\com\\cjj\\myzipstream\\");
//3.调用方法来压缩
toZip(file,dest);
}
publicstaticvoidtoZip(Filefile,Filedest) throwsIOException {
/*
作用:压缩
参数1:表示要压缩的文件
参数2:表示压缩包的位置
*/
//1.创建压缩流关联压缩包
ZipOutputStreamzos=newZipOutputStream(newFileOutputStream(newFile(dest,"a.zip")));
//2.创建ZipEntry对象,表示压缩包里面的每一个文件和文件夹
ZipEntryentry=newZipEntry("a.txt");
//3.把entry对象放到压缩包
zos.putNextEntry(entry);
//4.把file文件中的数据写入压缩包
FileInputStreamfis=newFileInputStream(file);
intb;
while((b=fis.read())!=-1){
zos.write(b);
}
fis.close();
zos.closeEntry();
zos.close();
}
}
//压缩文件夹
packagecom.cjj.myzipstream;
importjava.io.*;
importjava.util.zip.ZipEntry;
importjava.util.zip.ZipOutputStream;
publicclassZipStreamDemo03 {
publicstaticvoidmain(String[] args) throwsIOException {
/*
压缩流
需求:把D:\\aaa文件夹压缩成一个压缩包
*/
//1.创建File对象表示要压缩的文件夹
Filesrc=newFile("D:\\aaa");
//2.创建File对象表示压缩包放在哪里(压缩包的父级路径)
FiledestParent=src.getParentFile();
//3.创建一个File对象表示压缩包路径
Filedest=newFile(destParent, src.getName() +".zip");
//4.创建压缩流关联压缩包
ZipOutputStreamzos=newZipOutputStream(newFileOutputStream(dest));
//5.获取src里面的每一个文件夹,变成zipEntry对象,放入到压缩包中
toZip(src, zos, src.getName());
//6.释放资源
zos.close();
}
publicstaticvoidtoZip(Filesrc, ZipOutputStreamzos, Stringname) throwsIOException {
/*
作用:获取src里面的每一个文件,变成ZipEntry对象,放入到压缩包中
参数1:数据源
参数2:压缩流
参数3:压缩包内部的路径
*/
//1.进入src文件夹
File[] files=src.listFiles();
//2.遍历数组
for (Filefile : files) {
if (file.isFile()) {
//3.判断-文件,变成ZipEntry对象,放入到压缩包中
ZipEntryentry=newZipEntry(name+"\\"+file.getName());
zos.putNextEntry(entry);
//读取文件中的数据,写到压缩包
FileInputStreamfis=newFileInputStream(file);
intb;
while ((b=fis.read()) !=-1) {
zos.write(b);
}
fis.close();
zos.closeEntry();
} else {
//4.判断-文件夹,递归
toZip(file, zos, name+"\\"+file.getName());
}
}
}
}
Commons-io
Commons-io是apache开源基金组织提供的一组有关IO操作的开源工具包
作用:提高IO流的开发效率
Apache:专门为支持开源软件项目而办的一个非盈利性组织
使用步骤:
1.在项目中创建一个文件夹:lib
2.将jar包复制粘贴到lib文件夹
3.右键点击jar包,选择Add as Library->点击OK
4.在类中导包使用
FileUtils类(文件/文件夹相关) | 说明 |
static void copyFile(File srcFile,File destFile) | 复制文件 |
static void copyDirectory(File srcDir,File destDir) | 复制文件夹 |
static void copyDirectoryToDirectory(File srcDir,File destDir) | 复制文件夹 |
static void deleteDirectory(File directory) | 删除文件夹 |
static void cleanDirectory(File directory) | 清空文件夹 |
static String readFileToString(File file,Charset encoding) | 读取文件中的数据变成字符串 |
static void write(File file,CharSequence data,String encoding) | 写出数据 |
IOUtils类(流相关相关) | 说明 |
public static int copy(InputStream input,OutputStream output) | 复制文件 |
public static int copyLarge(Reader input,Writer output) | 复制大文件夹 |
public static String readLines(Reader input) | 读取数据 |
public static void write(String data,OutputStream output) | 写出数据 |
Hutool工具包
相关类 | 说明 |
IOUtil | 流操作工具类 |
FileUtil | 文件读写和操作的工具类 |
FileTypeUtil | 文件类型判断工具类 |
WatchMonitor | 目录,文件监听 |
ClassPathResource | 针对ClassPath中资源的访问封装 |
FileReader | 封装文件读取 |
FileWriter | 封装文件写入 |