10.文件与IO流
10.1 File类
- 文件和目录路径名的抽象表示。
文件和目录路径名的抽象表示形式。
java把电脑中的文件和文件夹(目录)封装成了一个File类,我们可以使用File类对文件和文件夹进行操作。我们可以使用File类的方法进行:
- 创建文件/文件夹
- 删除文件/文件夹
- 获取文件/文件夹
- 判断文件/文件夹是否存在
- 对文件夹进行遍历
- 获取文件大小
File类是一个与系统无关的类,任何操作系统都可以使用这个类中的方法
重点:三个单词
【file】文件
【directory】文件夹/目录
【path】路径
10.1.1 成员变量
static String | pathSeparator | 与系统相关的路径分隔符字符,为方便起见,表示为字符串。 |
---|---|---|
static char | pathSeparatorChar | 与系统相关的路径分隔符。 |
static String | separator | 与系统相关的默认名称 - 分隔符字符,以方便的方式表示为字符串。 |
static char` | separatorChar | 与系统相关的默认名称分隔符。 |
【注意】
路径分隔符:
windows:分号; Linux:冒号:
文件名称分隔符:windows:反斜杠‘ \ ’ Linux: 正斜杠’ / ’
因此,路径、文件名称分隔符不能写死了,操作系统不同会存在差异。
10.1.2 路径
【绝对路径】一个完整的路径,以盘符开始的路径
【相对路径】一个简化的路径,相对于当前项目的根目录
注意:
- 路径不区分大小写
- 路径中文件名称分隔符windows中使用反斜杠,反斜杠是转义字符
- 两个反斜杠才表示一个反斜杠
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 参数:
- 路径可以是文件结尾,也可以是文件夹结尾
- 可以是相对路径,也可以是绝对路径
- 路径可以存在,也可以不存在
- 创建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
【注意】
- 此方法只创建文件,不能创建文件夹
- 创建文件的路径必须存在,否则抛出异常
- 创建类型是文件类型,不要被命名所“欺骗”
createNewFile声明抛出了IOException,所以调用这个方法时必须处理这个异常。
mkdir方法 创建文件夹
public boolean mkdir()
创建此抽象路径名指定的单级文件夹。
mkdirs方法 创建多级文件夹
public boolean mkdirs()
创建此抽象路径名指定的目录,包括所有必需但不存在的父目录。
【注意】
- 此只能创建文件夹,不能创建文件
- mikdir若用来创建多级文件夹会返回false,无法创建成功
- 创建类型是文件夹类型,不要被命名所“欺骗”
delete方法 删除文件或文件夹
public boolean delete()
删除此抽象路径名表示的文件或目录。如果此路径名表示一个目录,则该目录必须为空才能删除。
【注意】
delete的方法是直接在硬盘中删除文件/文件夹,不进入回收站
10.1.5 遍历文件夹目录
public String[] list()
返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录。
public File[] listFiles()
返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件。
【注意】
- 以上两个方法遍历的是构造方法中给出的抽象目录
- 如果构造方法中给出的目录路径不存在,会抛出空指针异常
- 若给出路径不是一个目录,也会抛出空指针异常
10.2 递归
【简而言之】自己调用自己就叫递归
10.2.1 概述
分类:
- 直接递归和间接递归
- 直接递归成为方法自身调用自己
- 间接递归可以A调用B,B调用C,C调用A,构成回路
【注意】
- 递归一定要有条件限定,最终能停下来。否则会发生栈内存溢出。
- 递归中虽然有限定条件,但次数不能太多,否则栈内存溢出。
- 构造方法禁止递归
适用前提:
- 调用方法时,方法主体不变,每次调用方法的参数不同,才可以递归。否则就是无限循环。
- 明确递归的结束条件
- 明确递归的目的
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 :目的地是一个文件
构造方法的【作用】
- 创建一个输出流对象
- 根据构造方法中传递的文件/文件路径,创建一个空文件
- 会把该输出流对象指向创建好的文件
写入数据的原理(内存—>硬盘)
java程序 —》 JVM —》 OS —》 OS调用写数据的方法,写入数据到文件中
字节流的使用步骤【重点】
- 创建一个FileOutputStream对象,构造方法中传递写入数据目的地
- 调用对象方法write,写入数据到文件中
- 释放资源
写入数据时,数据是以二进制数存储的,所以存入的0~127整数,在打开文件时会被自动根据ASCII码表转化为字符表示。其他值会查询系统默认的码表,中文系统是GBK标
输出多字节的方法
public void write(byte[] b)
将b.length字节从指定的字节数组写入此输出流
【注意】当一次写多个字节时
- 如果首字节是0~127正数,那么文件查看显示时,会查询ASCII码表
- 如果首字节是负数,那么第一个字节会和第二个字节共同组成一个中文显示(查询系统默认码表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)
构造方法的作用:
- 创建一个FileInputStream对象
- 将对象指向构造方法中读取的文件
读取数据的原理(硬盘到内存)
Java程序—》JVM—》OS—》OS读取文件数据
使用步骤【重点】
- 创建一个FileInputStream对象,构造方法中要绑定要读取的数据源
- 使用对象中read方法读取文件一个字节(read方法会返回读取的数据,当读取到末尾时再读取会返回整数-1)
- 释放资源close
我们发现一个字符逐个读取的方法会产生大量重复代码,
于是考虑循环优化
使用【while】循环读取
布尔表达式:(len = fis.read()) != -1
该表达式同时完成了读取、赋值、判断的三个过程
因此循环体内部不再需要使用read方法再次读取,而是直接可以使用读取到的数据(len)
一次读取多个字节
int read(byte[] b) 从输入流中读取一定数量的字节中,并将存储在缓冲区数组b中
明确两件事:
- 参数byte[] b 的作用 【存储读取到的多个字节数据,在工作中尝尝定义为Kb,即1024的整数倍】
- 方法返回值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:一个文件
构造方法的【作用】:
- 创建一个FileReader对象
- 会吧FileReader对象指向要读取的文件
【字符输入流的使用步骤】
- 创建FileReader对象,构造方法中绑定要读取的数据源
- 使用FileReader对象中的方法read读取文件
- 释放资源
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:文件
构造方法的作用:
- 创建一个FileWriter对象
- 会根据构造方法中传递的文件/文件路径,创建文件
- 会把FileWriter对象指向创建好的文件
【字符输出流的使用步骤】【重点】
- 创建一个FileWriter对象,构造方法中绑定写入数据目的地
- 使用对象方法write,把数据写入到内存缓冲区中(字符转换为字节的过程)【若文件存在,会重新创建并覆盖】
- 使用FileWriter中的方法flush,把内存缓冲区的数据,刷新到硬盘文件中【这是与字节流输出的重要区别】
- 释放资源(释放前会自动将内存缓冲区数据刷新到硬盘文件中)
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
使用步骤
- 创建Properties集合对象,添加数据
- 创建字节流/字符流对象,构造方法中绑定目的地
- 使用Proerties集合方法store,把集合中临时数据持久化写入硬盘
- 释放资源
【字符流可以写入中文,字节流不能写中文】
load方法
将硬盘中保存的文件(键值对),读取到集合中使用
void load(inputStream inStream)
void load(Reader reader)
参数:inStream 字节输入流,不能读中文键值对
reader字符输入流,可以读中文
使用步骤
- 创建Properties集合对象
- 使用Properties集合对象中的方法load读取保存键值对文件
- 遍历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用于指定缓冲区大小,不指定时默认
【使用步骤】【重点】
- 创建字节输出流对象,构造方法中绑定目的地
- 创建BufferedOutputStream对象,构造方法中传递输出流对象,提高流对象效率
- 使用BufferedOutputStream对象方法write,把数据写入缓冲区中
- 使用BufferedOutputStream对象方法flush,把缓冲区数据刷新到硬盘文件中
- 释放资源(释放前自动刷新一次)
10.4.3 BufferedInputStream字节缓冲输入流
构造方法
public BufferedInputStream(InputStream in)
public BufferedInputStream(InputStream in,int size)
【使用步骤】【重点】
- 创建字节输入流对象,构造方法中绑定读取的数据源
- 创建BufferedInputStream对象,构造方法中传递输入流对象,提高其读取效率
- 使用BufferedInputStream对象方法read,读取文件
- 释放资源
通过使用字节缓冲流来完成文件复制(一读一写),发现比原来不使用缓冲流来逐个字节完成复制,效率提高了几百倍。
10.4.4 BufferedWriter字符缓冲输出流
与字节缓冲输出流类似的部分不予重复记录
其特有的成员方法:
public void newLine()//换行
写入一个行分隔符。Windows:\r\n Linux:/n mac:/r
使用步骤:
- 创建字符缓冲输出流对象,构造方法中传递字符输出流
- 调用字符缓冲输出流中方法write,把数据写入到内存缓冲区中
- 调用字符缓冲输出流中方法flush,把内存缓冲区中的数据,刷新到文件中
- 释放资源
10.4.5 BufferedReader字符缓冲输入流
特有成员方法:
public String readLine()
读取一个文本行,当如果到达末尾,返回null
使用步骤:
- 创建字符缓冲输入流对象,构造方法中传递字符输入流
- 调用对象方法read/readLine 读取文本
- 释放输入流对象
循环优化时布尔表达式为:
(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
使用步骤:
- 创建OutputStreamWriter对象,构造方法中传递字节输出流和制定编码方式
- 使用对象方法write,完成编码
- 使用flush方法,把内存缓冲区中字节刷新到硬盘中
- 释放资源
10.5.5 案例练习-转换文件的编码方式
要求:将GBK编码的文本文件,转换为UTF-8编码的文本文件
分析:
- 创建ISR对象,构造方法中传递字节输入流和指定编码表名称
- 创建OSW对象,构造方法传递字节输出流和指定编码表
- 使用ISR对象方法read读取文件
- 使用OSW对象write方法写入文件
- 释放资源
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
【使用步骤】
- 创建 ObjectOutputStream 对象,构造方法中传递字节输出流
- 使用对象方法writeObject,将对象写入文件
- 释放资源
注意:
在进行序列化和反序列化时,会抛出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 读取对象。
【使用步骤】
- 创建ObjectInputStream对象,构造方法中传递字节输入流
- 使用ObjectInputStream对象中方法readObject读取保存对象的文件
- 释放资源
- 使用读取到的对象
10.6.3 瞬态关键字transient
static 关键字:静态关键字
静态优先于非静态加载到内存中(静态优先于对象进入内存)
被static修饰的成员变量不能被序列化,序列化的都是对象
transient关键字
若在对象序列化过程中希望某个成员变量不被序列化,可以在该成员变量前加transient关键字修饰。会造成跟static近似的效果。
10.6.4 InvalidClassException异常
当完成了序列化操作后,对原本的类的定义进行了修改,序列号发生变化。在反序列化过程总就会抛出InvalidClassException异常。
解决方案:
手动声明一个序列号,必须用static + final 关键字进行修饰serialVersionUID 变量,给定一个指定的序列号,永久不变。
在这之后无论怎么对原本的类的定义进行修改,都能实现正常的反序列化操作。
10.6.5 练习
序列化集合:当我们想再文件中保存多个对象时,可以把多个对象存储到一个集合中,对集合进行序列化和反序列化。
分析:
- 定义一个存储Person对象的ArrayList集合
- 在集合中存储Person对象
- 创建一个序列化流ObjectOutputStream对象
- 使用ObjectOutputStream对象方法writeObject,对集合进行序列化
- 创建一个反序列化ObjectInputStream对象
- 使用ObjectInputStream对象方法readObject读取文件中保存的集合
- 把Object类型的集合转换回ArrayList集合类型
- 遍历ArrayList
- 释放资源
代码实现
10.7 打印流
java.io.PrintStream类
PrintStream特点:
- 只负责数据的输出,不负责数据读取
- 不抛出IO异常
- 特有方法:print、println
构造方法
- 文件
- 字节输出流
- 文件路径
【注意】
- 如果使用继承自父类的write方法写数据,查看数据的时候回查询编码表
- 如果使用特有方法print/println写数据,数据原样输出
可以改变输出语句的目的地(打印流的流向)
输出语句:默认在控制台输出
使用System.setOut方法改变目的地