个人简介:Java领域新星创作者;阿里云技术博主、星级博主、专家博主;正在Java学习的路上摸爬滚打,记录学习的过程~
个人主页:.29.的博客
学习社区:进去逛一逛~
IO流
- [Java IO](#Java IO)
-
- [1. 认识IO](#1. 认识IO)
- [2. FileOutputStream(写)](#2. FileOutputStream(写))
- [3. FileInputStream(读)](#3. FileInputStream(读))
- [4. Java编码和解码](#4. Java编码和解码)
- [5. 字符流](#5. 字符流)
-
- 1) FileReader FileReader)
- 2)FileWriter
- [6. 缓冲流](#6. 缓冲流)
- [7. 转换流(字符流的一种)](#7. 转换流(字符流的一种))
- [8. 序列化流 / 反序列化流](#8. 序列化流 / 反序列化流)
- [9. 打印流](#9. 打印流)
- [10. 压缩流 / 解压缩流](#10. 压缩流 / 解压缩流)
Java IO
1. 认识IO
IO流
:
- 流的方向划分:
-
- 输入流:读取
- 输出流:写出
- 流操作的文件类型划分:
-
- 字节流:可读取所有文件类型
-
- InputStream:字节输入流
- OutputStream:字节输出流
- 字符流:可读取纯文本文件
-
- Reader:字符输入流
- Writer:字符输出流
2. FileOutputStream(写)
使用步骤
:
-
① 创建字节输出流对象
-
- 参数:字符串表示的路径/File对象
- 文件不存在,或自动创建一个新的,但需要保证父级路径存在
- 如果文件已经存在,会被覆盖
-
②写数据
-
- writer()中的参数是int类型,实际写出到文件内容是整数对应的ASCII码值
- 三种方式:
-
void write(int b)
:一次写一个字节数据void write(byte[] b)
:一次写一个字节数组的数据void write(byte[] b,int off,int len)
:一次写一个数组的部分数据(参数:数组、起始索引、个数)
-
③释放资源
-
- 每次使用完流之后都需要进行资源释放
-
初识案例:
-
java
public class FileOutputStreamDemo { public static void main(String[] args) throws IOException { //获取输出流对象 FileOutputStream fos = new FileOutputStream("D:\\JavaData\\myIO\\a.txt"); //写操作 fos.write(97); //关闭资源 fos.close(); } }
-
换行符:
-
- Windows:
\r\n
- Linux:
\n
- Mac:
\r
- Windows:
-
续写:
-
-
当写出的文件存在时,一般情况会对内容进行覆盖,若想续写,需要在创建文件输出流对象时设置参数。
java//参数一:路径 //参数二:是否续写:true续写 false:覆盖 FileOutputStream fos = new FileOutputStream("D:\\JavaData\\myIO\\a.txt",true);
-
3. FileInputStream(读)
使用步骤
:
- ①创建字节输入流对象
-
- 如果读取文件不存在,直接报错FileNotFoundException
- ②读取数据
-
- 一次读一个字节,读出内容是数据在ASCII码对应的int数字
- 读到文件末尾,read()返回 -1
public int read()
:一次读取一个字节数据public int read(byte[] buffer)
:一次读取一个字节数组数据
- ③释放资源
-
- 每次使用完流必须进行资源释放
- 避免乱码:
-
-
- 不使用字节流读取文本文件
- 编码、解码时使用同一个码表,同一个编码方式
-
循环读取
:
-
示例:
-
- 一次读取一个字节
-
java
public class FileInputStreamDemo { public static void main(String[] args) throws IOException { //创建文件输入流对象 FileInputStream fis = new FileInputStream("D:\\JavaData\\myIO\\a.txt"); //循环读取(一次读取一个字节) int b; while((b = fis.read()) != -1){ System.out.print((char)b); } //释放资源 fis.close(); } }
4. Java编码和解码
Java中的编码和解码方式
:
- 编码:
public byte[] getBytes()
:使用默认方式编码public byte[] getBytes(String charsetName)
:使用指定的方式进行编码- 解码:
String(byte[] bytes)
:只用默认方式进行解码String(byte[] bytes,String charsetName)
:使用指定的方式进行解码
5. 字符流
字符流
:
- 字符流 : 字节流 + 字符集
特点
-
- 输入流:一次读一个字节,遇到中文,一次读多个字节
- 输出流:底层会把数据按照指定的编码方式进行编码,变成字节再写入文件
- 适用于:对纯文本文件进行读写操作。
1) FileReader
使用步骤
:
- ①创建字符输入流对象
-
public FileReader(File file)
:创建字符输入流关联本地文件publlic FileReader(String pathname)
:创建字符输入流关联本地文件-
- 若文件不存在,报错
- ②读取数据
-
public int read()
:读取数据,都到末尾返回 -1public int read(char[] buffer)
:一次读取数组长度的数据,读取到末尾返回 -1-
- 空参方法,按照字节进行读取,读取中文时一次读取多个字节,读取后解码,返回一个整数。
- 读取到文件末尾,read()返回 -1。
- ③释放资源
-
public int close()
:释放/关闭资源
原理
-
- 创建字符流对象时:底层关联文件,并创建缓冲区(长度为8192的数组)
- 读取数据时:
-
-
- 判断缓冲区是否有数据可以读取、
- 缓冲区没数据,从文件中获取数据并写入缓冲区,每次尽可能装满缓冲区,若文件也没有数据,返回 -1
- 缓冲区有数据,直接读取缓冲区
- 空参read() ------ 一次读取一个字节,中文则一次读取多个字节,把字节解码并转换成十进制
- 带参read() ------ 把读取字节、解码、强转三步合并,转换后的字符存入字符数组中
-
2)FileWriter
使用
- ①创建字符输出流对象
-
public FileWriter(File file)
:创建字符输出流关联本地文件public FileWriter(String pathname)
:创建字符输出流关联本地文件public FileWriter(File file,boolean append)
:续写方式,创建字符输出流关联本地文件public FileWriter(String pathname,boolean append)
:续写方式,创建字符输出流关联本地文件-
- 如果文件不存,自动创建新文件,但需要保证父级路径存在。
- 如果文件存在,会进行覆盖,需要传入参数,若无需覆盖可以打开续写开关(true)。
- ②写出数据:
-
void write(int c)
:写出一个字符(输出整数对应ASCII码)void write(String s)
:写出一个字符串void write(String str,int off,int len)
写出一个字符串,指定起始索引和输出长度void write(char[] cbuf)
:写出一个字符数组的数据void write(char[] cbuf,int off,int len)
:写出一个字符数组的数据,指定起始索引和输出长度
- ③关闭资源
-
- 关闭前将缓冲区数据写入文件
- 缓冲区可以手动刷新flush() ------ 缓冲区数据写入文件、并清空缓冲区
6. 缓冲流
缓冲流
:
- 缓冲流
-
- ①字节缓冲流
-
- 1)BufferedInputStream ------ 字节缓冲输入流
- 2)BufferedOutputStream ------ 字节缓冲输出流
- ②字符缓冲流
-
- 1)BufferedReader ------ 字符缓冲输入流
- 2)BufferedWriter ------ 字符缓冲输出流
1)字节缓冲流
字节缓冲流
:
- 使用:
-
public BufferedInputStream(InputStream is)
:把基本流包装成高级流,提高读取数据的效率public BufferedOutoutStream(OutputStream os)
:把基本流包装成高级流,提高写出数据的效率
- 原理:
-
- 底层自带长度为8192长度字节数组的缓冲区(8KB)提高性能。
- 字节流自身不带缓冲区,缓冲流能够显著提高性能
2)字符缓冲流
字符缓冲流
:
- 使用
-
public BufferedReader(Reader r)
:把基本流包装成高级流,提高读取数据的效率(字符缓冲输入流对象)public BufferedWriter(Writer r)
:把基本流包装成高级流,提高写出数据的效率(字符缓冲输出流对象)-
- 底层自带一个长度为8192字符数组的缓冲区(16KB)提升性能(缓冲区数据在内存中使用,速度快)
- 字符流自带缓冲区,缓冲流对字符流效率提升不明显,但字符缓冲流对字符流的主要意义在于:readLine() 和 newLine()
- 字符缓冲输入流 特有方法:
-
public String readLine()
:读取一行数据,读至末尾没有数据就返回null
- 字符缓冲输出流 特有方法:
-
public void newLine()
:换行操作,可跨平台
7. 转换流(字符流的一种)
转换流
:
- 转换流:是字符流和字节流之间的桥梁。
-
- InputStreamReader ------ 字节转换输入流
-
public InputStreamReader(InputStream in)
:将字节输入流转换为字符输入流。
- OutputStreamWriter ------ 字节转换输出流
-
public OutputStreamWriter(OutputStream out)
:将字符输出流转换为字节输出流。
- 作用:当字节流想要使用字符流中的方法时,可使用转换流。
8. 序列化流 / 反序列化流
序列化流(对象操作输出流)
:
-
作用:可以将Java对象写入到本地文件中。
-
使用:
-
- 构造方法 ------
public ObjectOutputStream(OutputStream out)
:把基本字节输出流,包装成序列化流(获取序列化流对象) - 成员方法 ------
public final void writeObject(Object obj)
:把对象序列化(写出)到本地文件中去 -
- 若直接使用对象输出流将对象保存到文件中时,会报错
NotSerializableException
,需要让JavaBean类实现Serializable接口,表示此类对象是可序列化的。
- 若直接使用对象输出流将对象保存到文件中时,会报错
- 构造方法 ------
反序列化流(对象操作输入流)
:
-
作用:可以把序列化到本地文件中的对象,读取到程序中来。
-
使用:
-
- 构造方法 ------
public ObjectInputStream(InputStream in)
:把基本字节输入流,包装成反序列化流(获取反序列化流对象) - 成员方法 ------
public Object readObject()
:把序列化到本地文件中的对象,读取到程序中来
- 构造方法 ------
-
需要让JavaBean类实现Serializable接口,表示此类对象是可序列化的。同时防止Java版本号的改变,使得序列化版本号不一致进而反序列化失败的问题,我们应该为JavaBean中手动设置一个序列化版本号:
-
java
private static final long serialVersionUID = -6357601841666449654L;
9. 打印流
打印流
:
-
打印流
-
- 字节打印流
PrintStream
- 字符打印流
PrintWriter
- 字节打印流
-
字节打印流-PrintStream
-
-
构造方法(获取字节打印流对象):
-
public PrintStream(OutputStream/File/String)
:关联字节输出流/文件/文件路径 -
public PrintStream(String fileName,Charset charset)
:指定字符编码 -
public PrintStream(OutputStream out,boolean autoFlush)
:设置自动刷新 -
public PrintStream(OutputStream put,boolean aytoFlush,Charset charset)
:指定字符编码并自动刷新 -
成员方法:
-
public void write(int b)
:将指定字节写出 -
public void println(Xxx xxx)
:特有方法:打印任意数据,自动刷新,自动换行 -
public void print(Xxx xxx)
:特有方法:打印任意数据,不换行 -
public void printf(String format,Object... args)
:特有方法:带有占位符地打印语句,不换行 -
- 字节流底层没有缓冲区,是否开启自动刷新都没有任何变化。
-
-
字符打印流-PrintWriter
-
- 方法使用参考上述地字节打印流(构造方法名PrintStream 换成 PrintWriter即可、成员方法名及使用方法一致)
-
特点:
-
- 打印流仅操作文件目的地,不操作数据源,故而只能作为输出流。
- 存在特有的写出方法,可以实现数据原样写出。
- 存在特有的写出方法,可以实现自动刷新,自动换行(写出+刷新+换行)
10. 压缩流 / 解压缩流
解压缩流
:
-
**解压本质:**把压缩包中地每一个ZipEntry对象按照层级拷贝到本地的另一个文件夹中去。
-
使用:
-
public ZipInputStream(InputStream in)
:构造方法,将普通字节输入流包装成解压缩流。ZipInputStream.getNextEntry()
:获取压缩包中的entry对象,读到末尾返回null
-
案例:
-
java
public class ZipStreamDemo { public static void main(String[] args) throws IOException { //解压缩流 示例 //File对象,表示需要解压缩的文件 File src = new File("D:\\JavaData\\myIO\\aa.zip"); //File对象,表示解压后的路径 File dest = new File("D:\\JavaData\\myIO"); unZip(src,dest);//解压缩 } //创建一个方法,用于解压 public static void unZip(File src,File dest) throws IOException { //创建解压缩流对象 ZipInputStream zip = new ZipInputStream(new FileInputStream(src)); //读取解压后的每一个entry对象 ZipEntry entry; while((entry = zip.getNextEntry()) != null){ //如果是文件夹,解压目录下创建新的文件夹 if(entry.isDirectory()){ File file = new File(dest,entry.toString()); file.mkdirs(); }else{ //如果是文件,输出到指定目录 FileOutputStream fos = new FileOutputStream(new File(dest, entry.toString())); //输出流 int i; while((i = zip.read()) != -1){ //写到目的地 fos.write(i); } fos.close(); //关闭输出流 zip.closeEntry(); //关闭当前entry } } zip.close(); } }
压缩流
:
-
ZipOutputStream
-
-
压缩单个文件:
-
-