【Java基础】10.文件与IO流

10.文件与IO流

10.1 File类

  • 文件和目录路径名的抽象表示。

文件和目录路径名的抽象表示形式。

java把电脑中的文件和文件夹(目录)封装成了一个File类,我们可以使用File类对文件和文件夹进行操作。我们可以使用File类的方法进行:

  1. 创建文件/文件夹
  2. 删除文件/文件夹
  3. 获取文件/文件夹
  4. 判断文件/文件夹是否存在
  5. 对文件夹进行遍历
  6. 获取文件大小

File类是一个与系统无关的类,任何操作系统都可以使用这个类中的方法

重点:三个单词

【file】文件

【directory】文件夹/目录

【path】路径

10.1.1 成员变量

static StringpathSeparator与系统相关的路径分隔符字符,为方便起见,表示为字符串。
static charpathSeparatorChar与系统相关的路径分隔符。
static Stringseparator与系统相关的默认名称 - 分隔符字符,以方便的方式表示为字符串。
static char`separatorChar与系统相关的默认名称分隔符。

【注意】

路径分隔符:

windows:分号; Linux:冒号:

文件名称分隔符:windows:反斜杠‘ \ ’ Linux: 正斜杠’ / ’

因此,路径、文件名称分隔符不能写死了,操作系统不同会存在差异。

10.1.2 路径

【绝对路径】一个完整的路径,以盘符开始的路径

【相对路径】一个简化的路径,相对于当前项目的根目录

注意:

  1. 路径不区分大小写
  2. 路径中文件名称分隔符windows中使用反斜杠,反斜杠是转义字符
  3. 两个反斜杠才表示一个反斜杠

10.1.3 构造方法

Constructor描述
File(File parent, String child)从父抽象路径名和子路径名字符串创建新的 File实例。
File(String pathname)通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例。
File(String parent, String child)从父路径名字符串和子路径名字符串创建新的 File实例。
File(URI uri)通过将给定的 file: URI转换为抽象路径名来创建新的 File实例。

File(File parent, String child) 参数:

把路径分为父类文件对象,可以对父文件对象进行操作

String pahthname 参数:

  1. 路径可以是文件结尾,也可以是文件夹结尾
  2. 可以是相对路径,也可以是绝对路径
  3. 路径可以存在,也可以不存在
  4. 创建File对象,只是把字符串路径封装为File对象,不考虑路径真假

String parent, String child 参数:

把路径分成了两部分

String parent :父路径

String child:子路径

优势:父子路径可以单独书写,使用灵活。

实际效果是会自动把父子字符串拼接成完整路径。

10.1.4 常用方法

获取功能方法
getAbsolutePath方法
public String getAbsolutePath()

返回此File的绝对路径字符串

getPath方法
public String getPath()

返回该File的抽象路径名字符串。可以是绝对也可以是相对路径。

等同于File的toString方法

getName方法
public String getName()

返回由此抽象路径名表示的文件或文件夹的名称。 这只是路径名称序列中的最后一个名字。

length方法
public long length()

返回由此抽象路径名表示的文件的大小,以字节为单位。

【注意】文件夹没有大小概念,不能获取文件夹的大小。如果构造方法中给出的路径不存在该文件,那么返回值是0

判断功能方法
exists方法
public boolean exists()

测试此抽象路径名表示的文件或目录是否客观存在。 存在返回true,不存在返回false

isDirectory方法
public boolean isDirectory()

测试此抽象路径名表示的文件是否为文件夹。

isFile方法
public boolean isFile()

测试此抽象路径名表示的文件是否是一个标准文件。

创建与删除功能方法
createNewFile方法 创建文件
public boolean createNewFile()

如果指定的文件不存在并成功地创建,则返回 true;如果指定的文件已经存在,则返回 false

【注意】

  1. 此方法只创建文件,不能创建文件夹
  2. 创建文件的路径必须存在,否则抛出异常
  3. 创建类型是文件类型,不要被命名所“欺骗”

createNewFile声明抛出了IOException,所以调用这个方法时必须处理这个异常。

mkdir方法 创建文件夹
public boolean mkdir()

创建此抽象路径名指定的单级文件夹。

mkdirs方法 创建多级文件夹
public boolean mkdirs()

创建此抽象路径名指定的目录,包括所有必需但不存在的父目录。

【注意】

  1. 此只能创建文件夹,不能创建文件
  2. mikdir若用来创建多级文件夹会返回false,无法创建成功
  3. 创建类型是文件夹类型,不要被命名所“欺骗”
delete方法 删除文件或文件夹
public boolean delete()

删除此抽象路径名表示的文件或目录。如果此路径名表示一个目录,则该目录必须为空才能删除。

【注意】

delete的方法是直接在硬盘中删除文件/文件夹,不进入回收站

10.1.5 遍历文件夹目录

public String[] list()

返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录。

public File[] listFiles()

返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件。

【注意】

  1. 以上两个方法遍历的是构造方法中给出的抽象目录
  2. 如果构造方法中给出的目录路径不存在,会抛出空指针异常
  3. 若给出路径不是一个目录,也会抛出空指针异常

10.2 递归

【简而言之】自己调用自己就叫递归

10.2.1 概述

分类:

  1. 直接递归和间接递归
  2. 直接递归成为方法自身调用自己
  3. 间接递归可以A调用B,B调用C,C调用A,构成回路

【注意】

  1. 递归一定要有条件限定,最终能停下来。否则会发生栈内存溢出。
  2. 递归中虽然有限定条件,但次数不能太多,否则栈内存溢出。
  3. 构造方法禁止递归

适用前提:

  1. 调用方法时,方法主体不变,每次调用方法的参数不同,才可以递归。否则就是无限循环。
  2. 明确递归的结束条件
  3. 明确递归的目的

10.2.2 练习

1.递归计算1~n之间的和

代码实现:

private static int sum(int n){
    if (n==1){
        return 1;
    }
    return n+sum(n-1);

}

内存原理:

main方法调用sum方法,sum方法反复调用sum方法,导致栈内存中有多个sum方法(频繁进栈,最终大批量出栈,销毁方法)效率低下

结论:如果仅仅是计算1~n之间的和这种简单运算,不建议使用递归,用for循环即可。

2.递归求阶乘

代码实现:

private static int factorial(int n){
    if (n==1){
        return 1;
    }
    return n*factorial(n-1);
}
3.遍历当前路径下所有文件(包含文件夹内的文件)

代码实现

private static void methodFile(File dir) {
    File[] files = dir.listFiles();
    for (File f : files) {
        //判断是不是文件夹
        if (f.isDirectory()) {
            methodFile(f);
        } else {
            System.out.println(f);
        }
    }

10.2.3 递归综合案例

文件搜索

要求:搜索指定路径下的文件

判断后缀名的方法

文件过滤器

java.io 接口 FileFilter

用于抽象路径名的过滤器。

【作用】用来过滤文件(File对象)

【抽象方法】accept,用于过滤文件

boolean accept(File pathname)

其中的参数pathname其实就是使用ListFiles方法遍历目录得到的每一个文件对象

java.io 接口 FilenameFilter

实现此接口的类实例可用于过滤器文件名

【作用】用来过滤文件名称

【抽象方法】accept

boolean accept(File dir,String name)

File dir:构造方法中传递的被遍历的目录

String name 使用ListFiles方法遍历目录得到的每一个文件对象名称

【注意】

以上接口没有实现类,使用时需要自己重写方法,设定过滤条件

过滤规则:

在重写的accept方法中,判断File对象是否以…后缀名结尾,是就返回true, 否则返回false

这样就完成了过滤

在使用匿名内部类重写抽象方法accept时,可以使用Lambda表达式来优化

10.3 IO流

10.3.1 概述

I:input 输入(读取)硬盘到内存

O:output 输出(写入) 内存到硬盘

流:数据(字符,字节) 1个字符=2个字节

10.3.2 字节流

一切文件数据在存储时都是以二进制数字形式保存

字节输出流【OutputStream】

java.io.OutputStream

此抽象类是表示输出字节流的所有类的超类。

定义了一些子类共性方法

public void close()
public void flush() throws IOException
public void write(byte[] b) throws IOException
public abstract void write(int b) throws IOException

10.3.3 FileOutputStream 文件字节输出流

作用:将数据写入硬盘的文件中

构造方法

public FileOutputStream(File file) throws FileNotFoundException

创建一个向指定 File 对象表示的文件中写入数据的文件输出流。

public FileOutputStream(String name)
                 throws FileNotFoundException

创建一个向具有指定名称的文件中写入数据的输出文件流

参数:写入数据的目的地

​ String name :目的地是一个文件路径

​ File file :目的地是一个文件

构造方法的【作用】

  1. 创建一个输出流对象
  2. 根据构造方法中传递的文件/文件路径,创建一个空文件
  3. 会把该输出流对象指向创建好的文件
写入数据的原理(内存—>硬盘)

java程序 —》 JVM —》 OS —》 OS调用写数据的方法,写入数据到文件中

字节流的使用步骤【重点】
  1. 创建一个FileOutputStream对象,构造方法中传递写入数据目的地
  2. 调用对象方法write,写入数据到文件中
  3. 释放资源

写入数据时,数据是以二进制数存储的,所以存入的0~127整数,在打开文件时会被自动根据ASCII码表转化为字符表示。其他值会查询系统默认的码表,中文系统是GBK标

输出多字节的方法
public void write(byte[] b)

将b.length字节从指定的字节数组写入此输出流

【注意】当一次写多个字节时

  1. 如果首字节是0~127正数,那么文件查看显示时,会查询ASCII码表
  2. 如果首字节是负数,那么第一个字节会和第二个字节共同组成一个中文显示(查询系统默认码表GBK表) 【在简体中午的操作系统中】
public void write(byte[] b,int off,int len)

off:数组的开始索引

len:写的字节长度

将字符串写入文件的方法

​ 使用String类中的getBytes()方法将字符串转换成字节数组

再使用write方法写入文件

续写(追加写)

使用两个参数的构造方法

public FileOutputStream(String name,boolean append)
public FileOutputStream(File file,boolean append)

参数:

​ String name ,File file :写入数据的目的地

​ boolean append:追加写开关

​ 若开关为true,创建对象时不会覆盖原文件,在文件末尾追加写

​ 若开关为false,创建文件时覆盖原文件

换行写

windows系统: \r\n

Linux系统: /n

mac系统: /r

10.3.4 FileInputStream 文件字节输入流

InputStream 字节输入流

此抽象类是表示字节输入流的所有类的超类。

共性方法:

read(),close()

FileInputStream文件字节输入流

作用:把硬盘文件中数据,读取到内存中使用

构造方法:

FileInputStream(String name)
FileInputStream(File file)

构造方法的作用:

  1. 创建一个FileInputStream对象
  2. 将对象指向构造方法中读取的文件

读取数据的原理(硬盘到内存)

Java程序—》JVM—》OS—》OS读取文件数据

使用步骤【重点】
  1. 创建一个FileInputStream对象,构造方法中要绑定要读取的数据源
  2. 使用对象中read方法读取文件一个字节(read方法会返回读取的数据,当读取到末尾时再读取会返回整数-1)
  3. 释放资源close

我们发现一个字符逐个读取的方法会产生大量重复代码,

于是考虑循环优化

使用【while】循环读取

布尔表达式:(len = fis.read()) != -1

该表达式同时完成了读取、赋值、判断的三个过程

因此循环体内部不再需要使用read方法再次读取,而是直接可以使用读取到的数据(len)

一次读取多个字节

int read(byte[] b) 从输入流中读取一定数量的字节中,并将存储在缓冲区数组b中

明确两件事:

  1. 参数byte[] b 的作用 【存储读取到的多个字节数据,在工作中尝尝定义为Kb,即1024的整数倍】
  2. 方法返回值int 【有效存储读入缓冲区的字节总数】

【注意】int是有效读取字节数,读取的最大长度为b.length

缓冲区数组b的数据更新方式是【覆盖式】,读取成功就覆盖,不成功就不变。

同样可以使用循环优化【while】

while((len = fis.read(bytes)) != -1){

	String str =  new String(bytes,len); //保证转换成字符串时都是有效的

}

【练习】文件复制

原理:文件的读+写

明确:数据源、数据目的地

10.3.5 字符流

【字符流与字节流的区别】

字节流每次读取一个字节,字符流每次读取一个字符(不管是中文还是英文字符)

java.lang.Object
  java.io.Reader
      java.io.InputStreamReader
          java.io.FileReader

Reader抽象类

共性方法:

int read() 读取单个字符并返回

Int read(char[] cbuf) 一次读取多个字符

FileReader类

文件字符输入流

作用:把硬盘文件中的数据以字符的方式读取到内存中

构造方法:

FileReader(String fileName)

FileReader(File file)

参数:读取文件的数据源

fileName:文件路径

File file:一个文件

构造方法的【作用】:

  1. 创建一个FileReader对象
  2. 会吧FileReader对象指向要读取的文件

【字符输入流的使用步骤】

  1. 创建FileReader对象,构造方法中绑定要读取的数据源
  2. 使用FileReader对象中的方法read读取文件
  3. 释放资源
FileWriter类

抽象类 Writer

共性方法

java.lang.Object
  继承者 java.io.Writer
      继承者 java.io.OutputStreamWriter
          继承者 java.io.FileWriter

FileWriter:文件字符输出流

作用:把内存中的字符数据写入文件中

构造方法:

public FileWriter(File file)
public FileWriter(String fileName)

参数:写入数据目的地

​ fileName:文件路径

​ file:文件

构造方法的作用:

  1. 创建一个FileWriter对象
  2. 会根据构造方法中传递的文件/文件路径,创建文件
  3. 会把FileWriter对象指向创建好的文件

【字符输出流的使用步骤】【重点】

  1. 创建一个FileWriter对象,构造方法中绑定写入数据目的地
  2. 使用对象方法write,把数据写入到内存缓冲区中(字符转换为字节的过程)【若文件存在,会重新创建并覆盖】
  3. 使用FileWriter中的方法flush,把内存缓冲区的数据,刷新到硬盘文件中【这是与字节流输出的重要区别】
  4. 释放资源(释放前会自动将内存缓冲区数据刷新到硬盘文件中)
flush与close方法的区别

flush:刷新缓冲区,流对象可以使用

close:刷新缓冲区,删除流对象

简而言之,完成一次刷新之后,可以继续写入下一次数据

写数据

字符输出流写数据的其他方法
public void write(char[] cbuf)//写入字符数组
public abstract void write(char[] cbuf,int off, int len)
    //写入字符数组的一部分,off是开始索引,len是长度
public void write(String str)//写入字符串
public void write(String str,int off,int len)
    //写入字符串的一部分,off是开始索引,len是长度
续写和换行

续写:使用两个参数的构造方法

public FileWriter(File file,boolean append)
public FileWriter(String fileName,boolean append)

append参数若为true,不会覆盖原文件,而是续写。

换行

【换行符号】 windows:\r\n

10.3.6 异常处理

使用try…catch…finally来处理异常

JDK 7新特性:在try() 括号中定义流对象,try代码块执行结束后,自动释放流对象

JDK 9新特性:在try的前边可以定义流对象,在try() 括号中直接引入对象名称,在try代码块执行结束后,自动释放流对象。

10.3.7 属性集

Properties集合
java.lang.Object
  java.util.Dictionary<K,V>
      java.util.Hashtable<Object,Object>
          java.util.Properties

Properties 类表示了一个持久的属性集。Properties 可保存在流中或从流中加载

特点:唯一一个与IO流结合的集合

可以使用store方法,把集合中的临时数据,持久化写入硬盘中存储

可以使用load方法,从输入流中读取属性列表(键和元素对)。

【注意】该集合是双列集合,key和Value都是字符串

特有方法
public Object setProperty(String key,String value)

调用Hashtable的方法put

public String getProperty(String key)

用指定的键在此属性列表中搜索属性。

public Set<String> stringPropertyNames()

返回此属性列表中的键集,其中该键及其对应值是字符串

store方法

字节流store方法

public void store(OutputStream out,String comments)

不能传递中文

字符流store方法

public void store(Writer writer,String comments)

可以传递中文

其中:参数out:输出流

​ comments:注释,用来解释保存的文件用途。不能使用中文,一般用空字符串null

使用步骤

  1. 创建Properties集合对象,添加数据
  2. 创建字节流/字符流对象,构造方法中绑定目的地
  3. 使用Proerties集合方法store,把集合中临时数据持久化写入硬盘
  4. 释放资源

【字符流可以写入中文,字节流不能写中文】

load方法

将硬盘中保存的文件(键值对),读取到集合中使用

void load(inputStream inStream)

void load(Reader reader)

参数:inStream 字节输入流,不能读中文键值对

​ reader字符输入流,可以读中文

使用步骤

  1. 创建Properties集合对象
  2. 使用Properties集合对象中的方法load读取保存键值对文件
  3. 遍历Properties集合

【注意】

  • 存储键值对的文件中,键与值默认连接符号是 = 或者 空格(其他符号)
  • 存储键值对的文件中,可以使用#进行注释,被注释的键值对,不会再被load读取
  • 存储键值对的文件中,键与值默认是字符串

10.4 缓冲流

为了实现高效读写,将引入缓冲流

10.4.1 概述

缓冲流也叫高效流,是对4个基本FileXXX流的增强,所有也有4个流

  • 字节缓冲流:BufferedInputStream,BufferedOutputStream
  • 字符缓冲流:BufferedReader,BufferedWriter

基本原理:在创建流对象时,创建一个内置的默认大小的【缓冲区数组】,通过缓冲区读写,减少系统IO次数,从而提高读写效率

10.4.2 BufferedOutputStream字节缓冲输出流

构造方法

BufferedOutputStream

public BufferedOutputStream(OutputStream out)
public BufferedOutputStream(OutputStream out,int size)

size用于指定缓冲区大小,不指定时默认

【使用步骤】【重点】

  1. 创建字节输出流对象,构造方法中绑定目的地
  2. 创建BufferedOutputStream对象,构造方法中传递输出流对象,提高流对象效率
  3. 使用BufferedOutputStream对象方法write,把数据写入缓冲区中
  4. 使用BufferedOutputStream对象方法flush,把缓冲区数据刷新到硬盘文件中
  5. 释放资源(释放前自动刷新一次)

10.4.3 BufferedInputStream字节缓冲输入流

构造方法

public BufferedInputStream(InputStream in)
public BufferedInputStream(InputStream in,int size)

【使用步骤】【重点】

  1. 创建字节输入流对象,构造方法中绑定读取的数据源
  2. 创建BufferedInputStream对象,构造方法中传递输入流对象,提高其读取效率
  3. 使用BufferedInputStream对象方法read,读取文件
  4. 释放资源

通过使用字节缓冲流来完成文件复制(一读一写),发现比原来不使用缓冲流来逐个字节完成复制,效率提高了几百倍

10.4.4 BufferedWriter字符缓冲输出流

与字节缓冲输出流类似的部分不予重复记录

其特有的成员方法:

public void newLine()//换行

写入一个行分隔符。Windows:\r\n Linux:/n mac:/r

使用步骤:

  1. 创建字符缓冲输出流对象,构造方法中传递字符输出流
  2. 调用字符缓冲输出流中方法write,把数据写入到内存缓冲区中
  3. 调用字符缓冲输出流中方法flush,把内存缓冲区中的数据,刷新到文件中
  4. 释放资源

10.4.5 BufferedReader字符缓冲输入流

特有成员方法:

public String readLine()

读取一个文本行,当如果到达末尾,返回null

使用步骤:

  1. 创建字符缓冲输入流对象,构造方法中传递字符输入流
  2. 调用对象方法read/readLine 读取文本
  3. 释放输入流对象

循环优化时布尔表达式为:

(line = br.readLine) != null

10.5 转换流

10.5.1 字符编码与字符集

字符编码:就是一套自然语言的字符与二进制数之间的对应规则

字符集:也叫编码表,是一个系统支持的所有字符的集合。

常见字符集有:ASCII字符集、GBK字符集、Unicode字符集

  • ASCII字符集:美国信息交换标准代码
  • ISO-8859-1字符集:方便支持欧洲常用字符
  • GB字符集
    • GB就是国标
    • GB2312:简体中文码表
    • GBK:最常用的中文码表
    • GB18030:最新中文码表,支持少数民族文字,支持繁体汉字,日韩汉字等
  • Unicode字符集
    • Unicode字符集又称为【万国码】
    • 最多用4个字节的数字来表达每个字母、符号或者文字。
    • 有3种编码方案:UTF-8、UTF-16、UTF-32
    • 我们开发Web应用,也需要使用UTF-8编码

10.5.2 编码引出的问题

在IDEA中,使用的默认是UTF-8编码,若读取Windows系统创建的文本文件时,由于Windows系统默认编码格式是GBK。于是在读取时会出现乱码。

那么如何读取GBK编码的文件呢?

10.5.3 InputStreamReader类

InputStreamReader 是字节流通向字符流的桥梁

它使用指定的 charset(编码表) 读取字节并将其解码为字符。

【注意】

GBK 中文码表 使用两个字节存储一个中文字符

Unicode 万国码表,使用三个字节存储一个中文字符

【本质】该类与FileReader的差异就在于,可以指定编码表完成解码

构造方法:

public InputStreamReader(InputStream in)
public InputStreamReader(InputStream in, Charset cs)

10.5.4 OutputStreamWriter类

OutputStreamWriter 是字符流通向字节流的桥梁

可使用指定的 charset要写入流中的字符编码成字节

【本质】该类与FileWriter的差异在于可以指定编码方式完成编码

构造方法:

public OutputStreamWriter(OutputStream out)
public OutputStreamWriter(OutputStream out, Charset cs)

不指定编码表名称时,默认UTF-8

使用步骤:

  1. 创建OutputStreamWriter对象,构造方法中传递字节输出流和制定编码方式
  2. 使用对象方法write,完成编码
  3. 使用flush方法,把内存缓冲区中字节刷新到硬盘中
  4. 释放资源

10.5.5 案例练习-转换文件的编码方式

要求:将GBK编码的文本文件,转换为UTF-8编码的文本文件

分析:

  1. 创建ISR对象,构造方法中传递字节输入流和指定编码表名称
  2. 创建OSW对象,构造方法传递字节输出流和指定编码表
  3. 使用ISR对象方法read读取文件
  4. 使用OSW对象write方法写入文件
  5. 释放资源

10.6 序列化流

把对象以流的方式(ObjectOutputStream),写入到文件中保存,叫写对象,也叫对象的序列化

把文件中保存的对象,以流的方式(ObjectInputStream)读取出来,叫读对象,也叫对象的反序列化

10.6.1 对象的序列化

类 ObjectOutputStream
java.lang.Object
  java.io.OutputStream
      java.io.ObjectOutputStream

作用:把对象以流方式写入到文件中保存

构造方法:

public ObjectOutputStream(OutputStream out)

特有成员方法:

public final void writeObject(Object obj)

将指定的对象写入 ObjectOutputStream

【使用步骤】

  1. 创建 ObjectOutputStream 对象,构造方法中传递字节输出流
  2. 使用对象方法writeObject,将对象写入文件
  3. 释放资源

注意:

在进行序列化和反序列化时,会抛出NotSerializableException没有序列化异常

对象所在类通过实现java.io.Serializable接口以启用该序列化功能

该接口是一个【标记型接口】:无实质内容,但有没有却很重要。

类比:猪肉上盖的检疫合格的蓝色章。没有这个章的是不合法销售的猪肉。

10.6.2 对象的反序列化

类 ObjectInputStream
java.lang.Object
  java.io.InputStream
      java.io.ObjectInputStream

作用:把文件中保存的对象,以流的方式读取出来使用

构造方法:

public ObjectInputStream(InputStream in)

特有成员方法:

public final Object readObject()

从 ObjectInputStream 读取对象。

【使用步骤】

  1. 创建ObjectInputStream对象,构造方法中传递字节输入流
  2. 使用ObjectInputStream对象中方法readObject读取保存对象的文件
  3. 释放资源
  4. 使用读取到的对象

10.6.3 瞬态关键字transient

static 关键字:静态关键字

静态优先于非静态加载到内存中(静态优先于对象进入内存)

被static修饰的成员变量不能被序列化,序列化的都是对象

transient关键字

若在对象序列化过程中希望某个成员变量不被序列化,可以在该成员变量前加transient关键字修饰。会造成跟static近似的效果。

10.6.4 InvalidClassException异常

当完成了序列化操作后,对原本的类的定义进行了修改,序列号发生变化。在反序列化过程总就会抛出InvalidClassException异常。

解决方案:

手动声明一个序列号,必须用static + final 关键字进行修饰serialVersionUID 变量,给定一个指定的序列号,永久不变。

在这之后无论怎么对原本的类的定义进行修改,都能实现正常的反序列化操作。

10.6.5 练习

序列化集合:当我们想再文件中保存多个对象时,可以把多个对象存储到一个集合中,对集合进行序列化和反序列化。

分析:

  1. 定义一个存储Person对象的ArrayList集合
  2. 在集合中存储Person对象
  3. 创建一个序列化流ObjectOutputStream对象
  4. 使用ObjectOutputStream对象方法writeObject,对集合进行序列化
  5. 创建一个反序列化ObjectInputStream对象
  6. 使用ObjectInputStream对象方法readObject读取文件中保存的集合
  7. 把Object类型的集合转换回ArrayList集合类型
  8. 遍历ArrayList
  9. 释放资源

代码实现

10.7 打印流

java.io.PrintStream类

PrintStream特点:

  1. 只负责数据的输出,不负责数据读取
  2. 不抛出IO异常
  3. 特有方法:print、println

构造方法

  1. 文件
  2. 字节输出流
  3. 文件路径

【注意】

  • 如果使用继承自父类的write方法写数据,查看数据的时候回查询编码表
  • 如果使用特有方法print/println写数据,数据原样输出

可以改变输出语句的目的地(打印流的流向)

输出语句:默认在控制台输出

使用System.setOut方法改变目的地

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值