资讯 小学 初中 高中 语言 会计职称 学历提升 法考 计算机考试 医护考试 建工考试 教育百科
栏目分类:
子分类:
返回
空麓网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
空麓网 > 计算机考试 > 软件开发 > 后端开发 > Java

Java基础笔记-07

Java 更新时间: 发布时间: 计算机考试归档 最新发布

Java基础笔记-07

五十七、IO流

1、IO流概述

IO流,用于读写文件中的数据,IO流是以程序(内存)为参照,在读取数据,或者写入数据

Java中I/O操作主要是指使用java.io包下的内容,进行输入、输出操作,输入也叫做读取数据,输出也叫做作写出数据

2、IO的分类

根据流的方向分为:输入流和输出流

  • 输入流 :把数据从其他设备上读取到内存中的流
  • 输出流 :把数据从内存 中写出到其他设备上的流

根据操作的文件类型分为:字节流和字符流

  • 字节流 :以字节为单位,读写数据的流,可以操作所有类型的文件
  • 字符流 :以字符为单位,读写数据的流,只能操作纯文本文件

3、IO流体系


蓝色框中的为抽象类

4、顶级父类

输入流输出流
字节流字节输入流
InputStream
字节输出流
OutputStream
字符流字符输入流
Reader
字符输出流
Writer

五十八、字节流

1、一切皆为字节

一切文件数据(文本、图片、视频等)在存储时,都是以二进制数字的形式保存,都一个一个的字节,那么传输时一样如此。所以,字节流可以传输任意文件数据。在操作流的时候,我们要时刻明确,无论使用什么样的流对象,底层传输的始终为二进制数据

2、字节输出流 OutputStream 抽象类

java.io.OutputStream 抽象类是表示字节输出流的所有类的超(父)类,将指定的字节信息写出到目的地,它定义了字节输出流的基本共性功能方法

  • public void close() 关闭此输出流并释放与此流相关联的任何系统资源
  • public void flush() 刷新此输出流并强制任何缓冲的输出字节被写出
  • public void write(byte[] b) 将 b.length 字节从指定的字节数组写入此输出流
  • public void write(byte[] b, int off, int len) 从指定的字节数组写入 len 字节,从偏移量 off 开始输出到此输出流
  • public abstract void write(int b) 将指定的字节输出流

close方法,当完成流的操作时,必须调用此方法,释放系统资源

3、FileOutputStream 类

OutputStream有很多子类,我们从最简单的一个子类开始,java.io.FileOutputStream类是文件输出流,用于将数据写出到文件

3.1、构造方法

  • public FileOutputStream(File file) 以指定的 File 对象表示路径,默认清空原有数据
  • public FileOutputStream(String name) 以指定的字符串表示路径,默认清空原有数据
  • public FileOutputStream(File file, boolean append) 以指定的 File 对象表示路径,第二个参数,true 表示追加数据,false 表示清空原有数据
  • public FileOutputStream(String name, boolean append) 以指定的字符串表示路径,第二个参数,true 表示追加数据,false 表示清空原有数据

当创建一个流对象时,必须传入一个文件路径。该路径下,如果没有这个文件,会创建该文件,但要保证父级路径存在

示例

import java.io.File;import java.io.FileOutputStream;import java.io.IOException;// FileOutputStream把程序中的数据写到本地文件中// 步骤:创建对象、写出数据、释放资源// 创建对象时可以给出第二个参数值,不写默认为false,会清空文件中原有的数据// 设置为true,表示在原有数据后追加写入数据public class ByteStreamOut1 {    public static void main(String[] args) throws IOException {        // 创建对象fos        File f = new File("bb.txt"); // 路径在当前项目下        FileOutputStream fos = new FileOutputStream(f, true); // 不会清空文件,而是以追加的方式写入                // 用write方法写入数据        // write方法的参数是整数,但实际写到文件中的是对应的ASCII码字符        fos.write(97); // 写入的是a                // 释放资源        fos.close();    }}

3.2、写出字节数据的三种方式

  • void write(int b) 一个写一个字节数据
  • void write(byte[] b) 一次写一个字节数组数据
  • void write(byte[] b, int off, int len) 一次写入一个字节数组的部分数据

写出字节 write(int b) 方法,每次可以写出一个字节数据

public class FOSWrite {    public static void main(String[] args) throws IOException {        // 使用文件名称创建流对象        FileOutputStream fos = new FileOutputStream("fos.txt");                   // 写出数据        fos.write(97); // 写出第1个字节        fos.write(98); // 写出第2个字节        fos.write(99); // 写出第3个字节                // 关闭资源        fos.close();    }}
  1. 虽然参数为int类型四个字节,但是只会保留一个字节的信息写出
  2. 流操作完毕后,必须释放系统资源,调用close方法,千万记得

写出字节数组 write(byte[] b),每次可以写出数组中的数据

public class FOSWrite {    public static void main(String[] args) throws IOException {        // 使用文件名称创建流对象        FileOutputStream fos = new FileOutputStream("fos.txt");                  // 字符串转换为字节数组        byte[] b = "泰酷辣".getBytes();        // 写出字节数组数据        fos.write(b);                // 关闭资源        fos.close();    }}

写出指定长度字节数组 write(byte[] b, int off, int len) ,每次写出从off索引开始,len个字节

public class FOSWrite {    public static void main(String[] args) throws IOException {        // 使用文件名称创建流对象        FileOutputStream fos = new FileOutputStream("fos.txt");                  // 字符串转换为字节数组        byte[] b = "abcde".getBytes();        // 写出从索引2开始,2个字节。索引2是c,两个字节,也就是cd        fos.write(b, 2, 2);                // 关闭资源        fos.close();    }}

3.3、写出换行

写出换行
写出一个换行符就可以实现换行
Windows系统,换行符号是rn
Linux系统,换行符号是n
Mac系统,换行符号是r

回车符r和换行符n:

  • 回车符:回到一行的开头(return)
  • 换行符:下一行(newline)

系统中的换行:

  • Windows系统里,每行结尾是 回车+换行 ,即rn;
  • Linux系统里,每行结尾只有 换行 ,即n;
  • Mac系统里,每行结尾是 回车 ,即r。从 Mac OS X开始与Linux统一

4、字节输入流 InputStream 抽象类

java.io.InputStream 抽象类是表示字节输入流的所有类的超(父)类,可以读取字节信息到内存中。它定义了字节输入流的基本共性功能方法

  • public void close() 关闭此输入流并释放与此流相关联的任何系统资源
  • public int read() 从输入流读取数据的下一个字节
  • public int read(byte[] b) 从输入流中读取一些字节数,并将它们存储到字节数组 b 中

5、FileInputStream 类

java.io.FileInputStream 类是文件输入流,从文件中读取字节

5.1、构造方法

  • FileInputStream(File file) 通过打开与实际文件的连接来创建一个 FileInputStream,以指定的 File 对象表示路径
  • FileInputStream(String name) 通过打开与实际文件的连接来创建一个 FileInputStream,以指定的字符串表示路径
public class FileInputStreamConstructor throws IOException{    public static void main(String[] args) {        // 使用File对象创建流对象        File file = new File("a.txt");        FileInputStream fos = new FileInputStream(file);               // 使用文件名称创建流对象        FileInputStream fos = new FileInputStream("b.txt");    }}

5.2、读取字节数据

读取字节:read方法,每次可以读取一个字节的数据,返回 int 类型,读取到文件末尾,返回-1

public class FISRead {    public static void main(String[] args) throws IOException{        // 使用文件名称创建流对象        FileInputStream fis = new FileInputStream("read.txt");                // 读取数据,返回一个字节        int read = fis.read();        System.out.println((char)read);        read = fis.read();        System.out.println((char)read);        read = fis.read();        System.out.println((char)read);        read = fis.read();        // ……        // 读取到末尾,返回-1        // 关闭资源        fis.close();    }}

循环改进读取方式

public class FISRead {    public static void main(String[] args) throws IOException{        // 使用文件名称创建流对象        FileInputStream fis = new FileInputStream("read.txt");                // 定义变量,保存数据        int b;        // 循环读取        while ((b = fis.read()) != -1) {            System.out.println((char)b);        }                // 关闭资源        fis.close();    }}

使用字节数组读取:read(byte[] b),每次读取b的长度个字节到数组中,返回读取到的有效字节个数,读取到末尾时,返回-1

public class FISRead {    public static void main(String[] args) throws IOException{        // 使用文件名称创建流对象        FileInputStream fis = new FileInputStream("read.txt"); // 文件中为abcde                // 定义变量,作为有效个数        int len;        // 定义字节数组,作为装字节数据的容器           byte[] b = new byte[2];        // 循环读取        while (( len = fis.read(b)) != -1) {            // 每次读取后,把数组变成字符串打印            System.out.println(new String(b));        }                // 关闭资源        fis.close();    }} 运行结果:abcded

错误数据d,是由于最后一次读取时,只读取一个字节e,数组中,上次读取的数据没有被完全替换,所以要通过len ,获取有效的字节

public class FISRead {    public static void main(String[] args) throws IOException{        // 使用文件名称创建流对象        FileInputStream fis = new FileInputStream("read.txt"); // 文件中为abcde                // 定义变量,作为有效个数        int len;        // 定义字节数组,作为装字节数据的容器           byte[] b = new byte[2];        // 循环读取        while (( len = fis.read(b)) != -1) {            // 每次读取后,把数组的有效字节部分,变成字符串打印            System.out.println(new String(b, 0, len)); // len为每次读取的有效字节个数        }                // 关闭资源        fis.close();    }}运行结果:abcde

使用数组读取,每次读取多个字节,减少了系统间的IO操作次数,从而提高了读写的效率,建议开发中使用

五十九、字符流

1、介绍

当使用字节流读取文本文件时,可能会有一个小问题,就是遇到中文字符时,可能不会显示完整的字符,那是因为一个中文字符可能占用多个字节存储,所以Java提供一些字符流类,以字符为单位读写数据,专门用于处理纯文本文件

为什么会有乱码

  • 读取数据时未读完整个汉字
  • 编码和解码的方式不统一

字符流
字符流的底层其实就是字节流
字符流 = 字节路 + 字符集

特点

  • 输入流:一次读一个字节,遇到中文时,一次读多个字节
  • 输出流:底层会把数据按照指定的编码方式进行编码,变成字节再写到文件中

2、字符输入流 Reader 抽象类

java.io.Reader抽象类是表示用于读取字符流的所有类的超(父)类,可以读取字符信息到内存中,它定义了字符输入流的基本共性功能方法

读取数据
public int read() 从输入流读取一个字符,读到末尾返回-1
public int read(char[] cbuf) 从输入流中读取一些字符,并将它们存储到字符数组 cbuf 中,读到末尾返回-1

释放资源
public void close() 关闭此流并释放与此流相关联的任何系统资源

3、FileReader 类

java.io.FileReader 类是读取字符文件的便利类,构造时使用系统默认的字符编码和默认字节缓冲区

  1. 字符编码:字节与字符的对应规则,Windows系统的中文编码默认是GBK编码表,idea中为UTF-8
  2. 字节缓冲区:一个字节数组,用来临时存储字节数据

3.1、构造方法

  • FileReader(File file) 创建字符输入流关联本地文件
  • FileReader(String fileName) 创建字符输入流关联本地文件

示例

public class FileReaderConstructor throws IOException{    public static void main(String[] args) {        // 使用File对象创建流对象        File file = new File("a.txt");        FileReader fr = new FileReader(file);               // 使用文件名称(路径)创建流对象        FileReader fr = new FileReader("b.txt");    }}

3.2、读取字符数据

读取字符:int read()方法,按字节一个一个的读取,遇到中文,一次读多个字节,读取后解码,并返回一个十进制整数,这个十进制的整数也表示在字符集上的数字,如果想看到中文汉字,需要把这些十进制数据强制转换,当读取到文件末尾,返回-1

import java.io.FileReader;import java.io.IOException;public class CharStreamDemo1 {    public static void main(String[] args) throws IOException {        // 创建对象、读取数据、释放资源        // 创建对象        FileReader fr = new FileReader("aaa.txt");                // 读取数据        System.out.print(fr.read()); // 返回十进制数        int ch;        while ((ch = fr.read()) != -1) {            System.out.print((char)ch); // 强制转换读取的数据才能看到汉字        }                // 释放资源        fr.close();    }}运行结果:20320好,阿里嘎多!

使用字符数组读取:int read(char[] cbuf),每次读取 cbuf.length 个字符到数组中,返回读取到的有效字符个数,读取到末尾时,返回-1

import java.io.FileReader;import java.io.IOException;public class CharStreamDemo2 {    public static void main(String[] args) throws IOException {        // 创建对象        FileReader fr = new FileReader("aaa.txt");                // 读取数据        char[] chars = new char[2];        int len;        while ((len = fr.read(chars)) != -1) {            //把数组中的数据变成字符串再打印            System.out.print(new String(chars, 0, len));        }        // 释放资源        fr.close();    }}运行结果:你好,阿里嘎多!

两个read方法对比
int read():空参的read方法是将读取到的数据解码为十进制就返回了,想把十进制变为对应的字符,需要一个强制转换
int read(char[] cbuf):有参的read方法是将读取数据、解码、和强转三步进行合并了,然后把强换后的字符放进数组中

4、字符输出流 Writer 抽象类

java.io.Writer 抽象类是表示用于写出字符流的所有类的超类,将指定的字符信息写出到目的地,它定义了字节输出流的基本共性功能方法

  • void write(int c) 写入单个字符
  • void write(char[] cbuf) 写入字符数组
  • void write(char[] cbuf, int off, int len) 写入字符数组的某一部分,off表示数组的开始索引,len表示写的字符个数
  • void write(String str) 写入字符串
  • void write(String str, int off, int len) 写入字符串的某一部分,off表示字符串的开始索引,len表示写的字符个数
  • void flush() 刷新该流的缓冲
  • void close() 先刷新缓冲区,然后关闭此流

5、FileWriter 类

java.io.FileWriter 类是写出字符到文件的便利类,构造时使用系统默认的字符编码和默认字节缓冲区

5.1、构造方法

  • FileWriter(File file) 创建一个新的 FileWriter 关联本地文件
  • FileWriter(String fileName) 创建一个新的 FileWriter 关联本地文件
  • FileWriter(File file, boolean append) 创建一个新的 FileWriter 关联本地文件,续写
  • FileWriter(String fileName, boolean append) 创建一个新的 FileWriter 关联本地文件,续写

示例

public class FileWriterConstructor {    public static void main(String[] args) throws IOException {        // 使用File对象创建流对象        File file = new File("a.txt");        FileWriter fw = new FileWriter(file);               // 使用文件名称(路径)创建流对象        FileWriter fw = new FileWriter("b.txt");    }}

5.2、写出字符数据

写出字符:void write(int b) 方法,每次可以写出一个字符数据

public class FWWrite {    public static void main(String[] args) throws IOException {        // 使用文件名称创建流对象        FileWriter fw = new FileWriter("fw.txt");                // 写出数据        fw.write(97); // 写出第1个字符        fw.write('b'); // 写出第2个字符        fw.write('C'); // 写出第3个字符        fw.write(30000); // 写出第4个字符,中文编码表中30000对应一个汉字                               fw.close();    }}写到文件中的数据:abC田
  1. 虽然参数为int类型四个字节,但是只会保留一个字符的信息写出
  2. 若不调用close方法,数据只是保存到了缓冲区,不会写出到文件中

写出字符数组 :void write(char[] cbuf) 和 write(char[] cbuf, int off, int len) ,每次可以写出字符数组中的数据,用法类似FileOutputStream

import java.io.FileWriter;import java.io.IOException;public class CharStreamDemo5 {    public static void main(String[] args) throws IOException {        // 使用文件名称创建流对象        FileWriter fw = new FileWriter("fw2.txt");        // 字符串转换为字节数组        char[] chars = "天气真好".toCharArray();        // 写出完整的字符数组        fw.write(chars);        // char占两个字节,写出从索引2开始,索引2是'真',两个长度,也就是'真好'        fw.write(chars, 2, 2);        // 关闭资源        fw.close();    }}运行后文件中的内容:天气真好真好

写出字符串:write(String str) 和 write(String str, int off, int len) ,每次可以写出字符串中的数据,更为方便,用得最多

import java.io.FileWriter;import java.io.IOException;public class CharStreamDemo6 {    public static void main(String[] args) throws IOException {        // 使用文件名(路径)创建流对象        FileWriter fw = new FileWriter("fw3.txt");        // 写出字符串        String str = "这件事情真的";        fw.write(str);        // 从索引4开始,写5个字符        fw.write("这件事情泰酷la!", 4, 5);        // 刷新缓冲区并关闭资源        fw.close();    }}运行后文件中的内容:这件事情真的泰酷la!

续写和换行:操作类似于FileOutputStream

public class FWWrite {    public static void main(String[] args) throws IOException {        // 使用文件名称创建流对象,可以续写数据        FileWriter fw = new FileWriter("fw.txt",true);             // 写出字符串        fw.write("明天");        // 写出换行        fw.write("rn");        // 写出字符串        fw.write("你好");        // 关闭资源        fw.close();    }}输出结果:明天你好

字符流,只能操作文本文件,不能操作图片,视频等非文本文件
当我们单纯读或者写文本文件时 使用字符流 其他情况使用字节流

5.3、关闭和刷新

因为内置缓冲区的原因,如果不关闭输出流,无法写出字符到文件中,但是关闭的流对象,是无法继续写出数据的,如果我们既想写出数据,又想继续使用流,就需要 flush 方法了

  • flush 刷新缓冲区,流对象可以继续使用
  • close 先刷新缓冲区,然后通知系统释放资源,流对象不可以再被使用了

示例

public class FWWrite {    public static void main(String[] args) throws IOException {        // 使用文件名称创建流对象        FileWriter fw = new FileWriter("fw.txt");                // 写出数据,通过flush        fw.write('刷'); // 写出第1个字符        fw.flush();        fw.write('新'); // 继续写出第2个字符,写出成功        fw.flush();               // 写出数据,通过close        fw.write('关'); // 写出第1个字符        fw.close();        fw.write('闭'); // 继续写出第2个字符,【报错】java.io.IOException: Stream closed        fw.close();    }}

即便是flush方法写出了数据,操作的最后还是要调用close方法,释放系统资源

六十、缓冲流

1、缓冲流介绍

缓冲流是高级流,可以提高读写的效率,字符流的基本流中已经有了缓冲区,所以 BufferedReader 和 BufferedWriter 两个缓冲流提高的效率不是很明显,但它们里面有两个特有的方法,很好用

2、字节缓冲流

字节缓冲流底层自带了长度为 8192 的缓冲区(字节流为byte类型,8k字节),可以显著提高字节流的读写性能

2.1、构造方法

  • public BufferedInputStream(InputStream in) 字节缓冲输入流,把基本流包装成高级流,提高读取数据的性能
  • public BufferedOutputStream(OutputStream out) 字节缓冲输出流,把基本流包装成高级流,提高读取数据的性能

示例

// 创建字节缓冲输入流BufferedInputStream bis = new BufferedInputStream(new FileInputStream("bis.txt"));// 创建字节缓冲输出流BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("bos.txt"));

3、字符缓冲流

字符缓冲流底层自带了长度为 8192 的缓冲区(字符流为char型,16k字节),因为字符流的基本流中已经有了缓冲区,所以字符缓冲流提高的效率不是很明显,但它们里面有两个非常好用的方法

3.1、构造方法

  • public BufferedReader(Reader in) 创建一个缓冲输入流,把基本流变成高级流
  • public BufferedWriter(Writer out) 创建一个缓冲输出流,把基本流变成高级流

示例

// 创建字符缓冲输入流BufferedReader br = new BufferedReader(new FileReader("br.txt"));// 创建字符缓冲输出流BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt"));

3.1、特有方法

  • BufferedReader:public String readLine() 一次读一行数据,遇到回车换行结束,不会把回车换行读到内存中,如果没有数据可读,返回null
  • BufferedWriter:public void newLine() 跨平台的换行,会先判断你的操作系统,再写出相应的换行符

public String readLine()方法示例

import java.io.BufferedReader;import java.io.FileReader;import java.io.IOException;public class BufferedStreamDemo1 {        public static void main(String[] args) throws IOException {            // 创建流对象            BufferedReader br = new BufferedReader(new FileReader("in.txt"));            // 定义字符串,保存读取的一行文字            String line = null;            // 循环读取,读取到最后返回null            while ((line = br.readLine()) != null) {                System.out.println(line);            }            // 释放资源            br.close();        }}

public void newLine()方法示例

import java.io.BufferedWriter;import java.io.FileWriter;import java.io.IOException;public class BufferedStreamDemo2 {    public static void main(String[] args) throws IOException {        // 创建字符缓冲输出流对象        BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt"));        // 写出数据        bw.write("123");        bw.newLine(); // 换行        bw.write("456");        // 刷新缓冲区并关闭文件        bw.close();    }}运行后文件中的内容:123456

六十一、转换流

1、概述

转换流属于字符流,也是高级流,用来包装基本流,是字节流和字符流之间的桥梁

在IO流体系中的位置

转换输入流与转换输出流图示
转换输入流:InputStreamReader把字节流转换成字符流,包装了字节输入流InputStream,包装后就变成字符输入流
转换输出流:OutputStreamWriter把字符流转换成字节流,包装了字节输出流OutputStream,包装后就变成字节输出流

作用

  • 以指定字符集读写数据(JDK11可以被替代)
  • 字节流想使用字符流中的方法,就可以使用转换流转换

2、转换输入流 InputStreamReader 类

转换流 java.io.InputStreamReader,是 Reader 的子类,是从字节流到字符流的桥梁,它读取字节,并使用指定的字符集将其解码为字符,它的字符集可以由名称指定,也可以接受平台的默认字符集

2.1、构造方法

  • InputStreamReader(InputStream in) 创建一个使用默认字符集的字符流
  • InputStreamReader(InputStream in, String charsetName) 创建一个指定字符集的字符流

示例

InputStreamReader isr1 = new InputStreamReader(new FileInputStream("in.txt"));InputStreamReader isr2 = new InputStreamReader(new FileInputStream("in.txt"), "GBK");

2.1、指定编码读取

使用InputStreamReader(InputStream in, String charsetName)方法读取

import java.io.FileInputStream;import java.io.IOException;import java.io.InputStreamReader;public class ConvertStreamDemo1 {    public static void main(String[] args) throws IOException {        // 创建输入转换流对象,指定以GBK编码格式读取        InputStreamReader isr = new InputStreamReader(new FileInputStream("GBK.txt"), "GBK");                // 读取数据        int ch;        while ((ch = isr.read()) != -1) {            System.out.print((char)ch);        }        // 关闭资源        isr.close();    }}运行结果:你厉害,我给你大拇哥!

上面这种方式在JDK11以后被淘汰,替代方案是使用 FileReader 类,它里面添加了一个新的构造,这个构造可以指定字符编码

import java.io.FileReader;import java.io.IOException;import java.nio.charset.Charset;public class ConvertStreamDemo2 {    public static void main(String[] args) throws IOException {        // 创建FileReader对象,指定以GBK编码格式读取,这个构造方法在JDK11后才有        FileReader fr = new FileReader("GBK.txt", Charset.forName("GBK"));                // 读取数据        int ch;        while ((ch = fr.read()) != -1) {            System.out.print((char)ch);        }                // 关闭资源        fr.close();    }}运行结果:你厉害,我给你大拇哥!

3、转换输出流 OutputStreamWriter 类

转换流 java.io.OutputStreamWriter ,是 Writer 的子类,是从字符流到字节流的桥梁,使用指定的字符集将字符编码为字节,它的字符集可以由名称指定,也可以接受平台的默认字符集

3.1、构造方法

  • OutputStreamWriter(OutputStream in) 创建一个使用默认字符集的字符流
  • OutputStreamWriter(OutputStream in, String charsetName) 创建一个指定字符集的字符流

示例

OutputStreamWriter osw1 = new OutputStreamWriter(new FileOutputStream("out.txt"));OutputStreamWriter osw2 = new OutputStreamWriter(new FileOutputStream("out.txt"), "GBK");

3.2、指定编码写出

import java.io.*;public class ConvertStreamDemo3 {    public static void main(String[] args) throws IOException {        // 创建OutputStreamWriter对象,指定以GBK编码格式写出        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("a.txt"), "GBK");        // 写出数据        osw.write("泰酷辣!");        // 释放资源        osw.close();            }}

同样地,上面这种方式在JDK11以后被淘汰,替代方案是使用 FileWriterr 类,它里面添加了一个新的构造,这个构造可以指定字符编码

import java.io.FileWriter;import java.io.IOException;import java.nio.charset.Charset;public class ConvertStreamDemo4 {    public static void main(String[] args) throws IOException {        // 创建FiledWriter对象,指定以GBK编码格式写出        FileWriter fw = new FileWriter("a.txt", Charset.forName("GBK"));                // 写出数据        fw.write("泰酷辣!");        // 释放资源        fw.close();                    }}

六十二、序列化流和反序列化流

1、概述

  • Java 提供了一种对象序列化的机制,用一个字节序列可以表示一个对象,该字节序列包含该对象的数据、对象的类型和对象中存储的属性等信息,字节序列写出到文件之后,相当于文件中持久保存了一个对象的信息;反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化,对象的数据、对象的类型和对象中存储的数据信息,都可以用来在内存中创建对象

  • 序列化流属于字节流,也是高级流,可以把Java中的对象写到本地文件中,写到文件中的数据我们是看不懂的,但可以用反序列化流将数据读取出来

在IO流体系中的位置

序列化流和反序列化流图示

2、序列化流 ObjectOutputStream 类

序列化流也叫对象操作输出流,java.io.ObjectOutputStream 类,将Java对象的原始数据类型写出到文件,实现对象的持久存储

2.1、构造方法

public ObjectOutputStream(OutputStream out) 创建 ObjectOutputStream 对象,把基本流包装成高级流

示例
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("a.txt"));

2.2、序列化操作

一个对象要想序列化,必须满足两个条件

  • 该类必须实现 java.io.Serializable 接口,Serializable 是一个标记接口(里面没有抽象方法),只有实现了这个接口,该类才可以被序列化
  • 该类的所有属性必须是可序列化的,如果有一个属性不需要可序列化的,则该属性必须注明是瞬态的,使用 transient 关键字修饰

写出对象的方法
public final void writeObject (Object obj) 将指定的对象序列化(写出)到文件中

import java.io.*;public class ObjectStreamDemo1 {    public static void main(String[] args) throws IOException {        // 创建Student类对象        Student stu = new Student(18, "西施");        // 创建ObjectOutputStream类对象        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("bb.txt"));        // 写出数据        oos.writeObject(stu);        // 释放资源        oos.close();    }}// Student类实现Serializable接口class Student implements Serializable {    private int age;    private String name;    public Student() {    }    public Student(int age, String name) {        this.age = age;        this.name = name;    }    @Override    public String toString() {        return "Student{" +                "age=" + age +                ", name='" + name + ''' +                '}';    }}

3、反序列化流 ObjectInputStream 类

ObjectInputStream 反序列化流,将之前使用 ObjectOutputStream 序列化的原始数据恢复为对象

3.1、构造方法

public ObjectInputStream(InputStream in) 创建一个 ObjectInputStream 对象

3.2、反序列化操作

读取对象的方法
public final Object readObject ()

import java.io.FileInputStream;import java.io.IOException;import java.io.ObjectInputStream;public class ObjectStreamDemo2 {    public static void main(String[] args) throws IOException, ClassNotFoundException {        // 创建ObjectInputStream对象        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("bb.txt"));        // 读取数据        Object obj = ois.readObject();        // 打印对象        System.out.println(obj);        // 释放资源        ois.close();    }}运行结果:Student{age=18, name='西施'}

3.3、注意事项

**另外,当JVM反序列化对象时,能找到class文件,但是class文件在序列化对象之后发生了修改,那么反序列化操作也会失败,抛出一个InvalidClassException异常。**发生这个异常的原因如下:

  • 该类的序列版本号与从流中读取的类描述符的版本号不匹配
  • 该类包含未知数据类型
  • 该类没有可访问的无参数构造方法

Serializable 接口给需要序列化的类,提供了一个序列版本号。serialVersionUID 该版本号的目的在于验证序列化的对象和对应类是否版本匹配。

六十三、打印流

1、概述

打印流是高级流,也是用来包装基本流的,打印流只能写,不能读,所以只有输出流。平时我们在控制台打印输出,是调用print方法和println方法完成的,这两个方法都来自于java.io.PrintStream类,该类能够方便地打印各种数据类型的值,是一种便捷的输出方式

2、字节打印流 PrintStream 类

构造方法

构造方法说明
public PrintStream(OutputStream/File/String name)关联字节输出流/文件/文件路径
public PrintStream(String fileName, Charset charset)指定字符编码
public PrintStream(OutputStream out, boolean autoFlush)自动刷新(字节流底层没有缓冲区,开不开和自动刷新都一样,下面这个方法同理)
public PrintStream(OutputStream out, boolean autoFlush, String encoding)指定字符编码且自动刷新

成员方法

成员方法说明
public void write(int b)常规方法,将指定的字节写出
public void println(Xxx x)特有方法,打印任意数据,自动刷新,自动换行
public void print(Xxx x)特有方法,打印任意数据,不换行
public void printf(String format, Object… args)特有方法,带有占位符的打印语句,不换行

3、字符打印流 PrintWriter 类

构造方法

构造方法说明
public PrintWriter(Write/File/String)关联输出流/文件/文件路径
public PrintWriter(String fileName, Charset charset)指定字符集编码
public PrintWriter(Writer w, boolean atuoFlush)自动刷新
public PrintWriter(OutputStream out, boolean autoFlush, Charset charset)指定字符编码且自动刷新

成员方法

成员方法说明
public void write(…)常规方法,写出字节或字符串
public void println(Xxx x)特有方法,打印任意数据,自动刷新,自动换行
public void print(Xxx x)特有方法,打印任意数据,不换行
public void printf(String format, Object… args)特有方法,带有占位符的打印语句,不换行

4、打印流的应用场景

System.out.println()

import java.io.PrintStream;public class Demo1 {    public static void main(String[] args) {        // 获取打印流的对象,此打印流在虚拟机启动的时候,由虚拟机创建,默认指向控制台        // 该打印流也叫系统中的标准输出流,这个流不能关闭,在系统中是唯一的        PrintStream ps = System.out;        // 调用方法        ps.println("123");        // 以上代码相当于下面这行代码        System.out.println("123");        // System.out就是在获取一个打印流对象        // 在虚拟机启动时由虚拟机自动创建,默认指向控制台        // .println就是调用方法打印    }}

六十四、解压缩流和压缩流

1、概述

  • 解压缩流
    主要是读取压缩包中的文件,属于输入流
  • 压缩流
    把文件中的数据写到压缩包中,属于输出流

2、解压缩流 ZipInputStream

压缩包里的每一个文件,都是一个ZipyEntry类的对象
Java中,只能识别zip格式的压缩文件

解压本质
把压缩包里每一个文件或文件夹读取出来,按照层级拷贝到另一个文件夹中

3、压缩流 ZipOutputStream

压缩就是把多个文件或多个文件夹变成一个压缩包,压缩包里的每一个文件或文件夹都是一个ZipEntry类的对象

压缩本质
把每一个文件或文件夹看成ZipEntry类的对象并放入到压缩包中


The End

转载请注明:文章转载自 http://www.konglu.com/
本文地址:http://www.konglu.com/it/1096134.html
免责声明:

我们致力于保护作者版权,注重分享,被刊用文章【Java基础笔记-07】因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理,本文部分文字与图片资源来自于网络,转载此文是出于传递更多信息之目的,若有来源标注错误或侵犯了您的合法权益,请立即通知我们,情况属实,我们会第一时间予以删除,并同时向您表示歉意,谢谢!

我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2023 成都空麓科技有限公司

ICP备案号:蜀ICP备2023000828号-2