6.异常和IO流
异常
=======================================
* 封装错误信息的对象
错误信息:
*) 类型
*) 提示消息
*) 行号
* 继承结构
Throwable
|- Error 系统级错误
|- Exception 可以编写代码进行修复的错误
|- 其他Exception
|- RuntimeException
|- NullPointerException
|- ArrayIndexOutOfBoundsException
|- NumberFormatException
|- ArithmeticException
|- ClassCastExction
|- ...
* try-catch-finall
try {
} catch(AException e) {
} catch(BException e) {
} catch(父类型Exception e) {
} finally {
}
* throws
*) 在方法上添加异常的抛出管道
void f() throws AException,BException {
}
*) RuntimeException 抛出管道,默认存在
RuntimeException及其子类型异常,
都可以从默认管道抛出
*) 其他类型异常, 必须二选一:
1) throws 添加管道
2) try-catch 捕获
* throw
*) 手动抛出一个异常
* 异常包装
将捕获的异常对象,
包装在其他异常对象中,再抛出
*) 无法抛出的异常,包装成能抛出的异常,再抛出
*) 多种类型异常,包装成同一种类型,再抛出
* 自定义异常
*)自定义异常类型,
来表示具体业务中的错误情况
ZhuanZhangShiBaiException
UsernameNotFoundException
WrongPaasswordException
io
=======================================
* I/O
Input / Output
* java.io 包
File
RandomAccessFile
InputStream / OutputStream 字节流抽象父类
FileInputStream / FileOutputStream 直接接文件
BufferedInputStream / BufferedOutputStream 缓冲区,提高单字节读写效率
DataInputStream / DataOutputStream 固定字节格式 writeInt(),writeDouble(),writeUTF()
PrintStream 任何数据转成字符串输出 print() println()
ByteArrayInputStream / ByteArrayOutputStream 接内存数组 toByteArray()
ObjectInputStream / ObjectOutputStream 序列化 writeObject() readObject()
Reader / Writer 字符流抽象父类
InputStreamReader / OutputStreamWriter 转换流
FileReader / FileWriter 内部是文件流接转换流
BufferedReader / BufferedWriter 字符缓冲 readLine()
PrintWriter 同 PrintSream
java.io.File
==========================================
* 封装字符串路径
* 路径:
*)可以是文件路径
*)可以是目录路径
*)可以是不存在的路径
创建对象
-------------------------------------
1.File f = new File("d:/abc/a.txt");
2.File f = new File("d:/abc", "a.txt");
方法
------------------------------------
*) 文件或目录的属性
canRead()
canWrite()
canExecute()
是否可读可写可执行
isHidden() 是否隐藏文件
exists() 表示的路径是否存在
getAbsolutePath() 完整路径
getName() 文件名
getParent() 父目录
lastModified() 最后修改时间,毫秒值
length() 文件字节量,对目录无效
isDirectory() 是否文件夹
isFile() 是否文件
getTotalSpace() 空间总大小
getFreeSpace() 可用空间
*) 文件或目录操作
createNewFile() 创建文件
delete() 删除文件或“空目录”
mkdir() 创建单层目录
mkdirs() 创建多层目录
renameTo() 改名、移动
*) 创建删除重命名方法返回 boolean,表示操作是否成功
File.createTempFile(前缀, 后缀) 在系统临时目录创建临时文件
*) 文件列表
list() 返回 String[],包含子文件、子目录名称
listFiles() 返回 File[],包含子文件、子目录的 File 对象
list(FilenameFilter)
listFiles(FilenameFilter)
listFiles(FileFilter)
只列出符合过滤条件的文件、目录,
参数: 外接的过滤器
java.io.RandomAccessFile
========================================
* 读写文件的工具
* 将文件看做是字节数组,
用下标访问指定位置的字节值
创建对象
-----------------------------------
1.RandomAccessFile raf =
new RandomAccessFile(文件, "r");
2.RandomAccessFile raf =
new RandomAccessFile(文件, "rw");
*) 如果文件不存在,会新建文件
*) 如果所在的目录不存在,会出现异常
方法
-----------------------------------
write(int b)
int 四个字节中,只输出末尾的一个字节值
[1][2][3][4] --> [4]
write(byte[] buf)
输出数组中全部字节值
write(byte[] buf, int from, int length)
输出数组中从 from 开始的 length 个字节值
read()
读取一个字节值,
并补三个0字节转成 int 类型
[4] --> [1][2][3][4]
读取结束,再读取,返回 -1
read(byte[] buf)
批量读取数据,
根据数组长度,读取一批字节值,
放入数组,并返回这一批的数量
读取结束,再读取,返回 -1
seek(int position)
定位下标到指定位置
getFilePointer()
获得当前下标所在的位置
流 Stream
=======================================
* 将数据读写,抽象成数据在管道中流动
* 流是单向的,分为输入流和输出流
* 从头到尾顺序流动
java.io.InputStream / OutputStream
=============================================
* 字节流的抽象父类
方法
----------------------------------
OutputStream
----------------------------
write(int b)
write(byte[] buf)
write(byte[] buf, from, length)
flush() 刷出缓存数据
InputStream
----------------------------
read()
read(byte[] buf)
available() 获得剩余的可读取字节数量
java.io.FileInputStream / FileOutputStream
==============================================
* 直接与文件相接,读写文件中的数据
创建对象
---------------------------------------
1.FileOutputStream out =
new FileOutputStream(文件);
不论文件是否存在,都会新建一个空文件;
如果所在的目录不存在,会出现异常
2.
FileOutputStream out =
new FileOutputStream(文件, true);
如果文件不存在,新建文件;
如果文件已经存在,在文件末尾追加数据
高级流、操作流
==========================================
* 与其他流相接,提供特定的数据处理功能
java.io.BufferedInputStream / BufferedOutputStream
===================================================
* 提供数据缓冲区,
提高单字节读写效率
创建对象
--------------------------------------
1.BufferedOutputStream out =
new BufferedOutputStream(相接的流);
默认缓存数组容量 8192
2.BufferedOutputStream out =
new BufferedOutputStream(相接的流, 16*1024);
指定缓存数组容量
java.io.DataInputStream / DataOutputStream
==============================================
* 读写固定字节格式的数据
创建对象
---------------------------------
DataOutputStream out =
new DataOutputStream(相接的流);
方法
---------------------------------
DataOutputStream
-----------------------------
writeInt(int i)
输出 int 类型全部四个字节
[1][2][3][4] --> [1][2][3][4]
writeDouble(double d)
输出 double 类型全部八个字节
...
writeUTF(String s)
先输出两个字节来表示字符串的字节长度,
再输出字符串的字节值
DataInputStream
--------------------------------
readInt()
连续读取四个字节,转成int
readDouble()
连续读取八个字节,转成double
...
readUTF()
先读取两个字节来确定字符串的字节长度,
再读取这些字节值,转成String
*) 读取结束,再读取,
会出现 EOFException
EOF - End Of File
java.io.PrintStream
============================================
* 将任何数据,转成字符串输出
out.write(97)
00 00 00 61 --> 61
out.writeInt(97)
00 00 00 61 --> 00 00 00 61
out.print(97)
00 00 00 61 --> '9' '7' --> 39 37
创建对象
---------------------------------------
1. PrintStream out =
new PrintStream(相接的流);
2. PrintStream out =
new PrintStream(文件);
3. PrintStream out =
new PrintStream(文件, 字符编码);
方法
---------------------------------------
print()
println()
字符编码 encoding
字符集 charset
===========================================
* ASC-II
0 - 127
* ISO-8859-1
Latin-1
160 - 255
* GB2312
7k+ 喆 镕
* GBK
20902 个中文
* BIG5
* JP...
* KR...
* AL...
* Unicode 统一码、万国码
*) 包换全球所有文字, 70万+
*) 常用字符表,双字节
*) 生僻字符,三字节或以上
*) java 的 char 类型字符,采用 Unicode 编码
'a' 00 61
'中' 4e 2d
*) Unicode 传输格式
UTF-8
英文 单字节
某些字符 双字节
中文 三字节
UTF-16Be
双字节,
Be: 大字接续
UTF-16Le
Le: 小字节序
*) java 字符编码转换
*) Unicode --> 其他编码
String s = "abc中文";
//转成系统默认编码
byte[] a = s.getBytes();
//转成指定的编码
byte[] a = s.getBytes("UTF-8");
*) 其他编码 --> Unicode
//从默认编码字节值转换成 Unicode
String s = new String(a);
//从指定的编码字节值转换成 Unicode
String s = new String(a, "UTF-8");
java.io.Reader / Writer
=============================================
* 字符流的抽象父类
* 字符流,读写字符数据
方法
------------------------------------
Writer
--------------------------------
write(int c)
只取末尾两个字节,作为一个 char 字符输出
write(char[] buf)
write(char[] buf, from, length)
write(String s)
Reader
--------------------------------
read()
读取一个 char 字符,补两个0字节,转成int
read(char[] buf)
java.io.InputStreamReader / OutputStreamWriter
=================================================
* 字符编码转换流
* OutputStreamWriter
Unicode 转成其他编码输出
* InputStreamReader
读取其他编码的字节值,
转成 Unicode 字符
创建对象
---------------------------------
1. OutputStreamWriter out =
new OutputStreamWriter(相接的字节流);
默认编码
2. OutputStreamWriter out =
new OutputStreamWriter(
相接的字节流, 字符编码);
指定的编码
java.io.FileReader / FileWriter
================================================
* 内部是 FileOutputStream 接 OutputStreamWriter
* 不能指定字符编码
创建对象
---------------------------------------
FileWriter out = new FileWriter(文件);
等价于:
OutputStreamWriter out =
new OutputStreamWriter(
new FileOutputStream(文件));
java.io.BufferedReader / BufferedWriter
================================================
* 字符缓冲区,提高单个字符读写效率
* BufferedReader 提供按行读取数据的方法
in.readLine()
创建对象
---------------------------------------------
BufferedWriter out =
new BufferedWriter(相接的字符流);
方法
---------------------------------------------
BufferedReader
---------------------------------
readLine()
读取一行文本,不包含末尾换行符
读取结束,再读取,返回 null
java.io.PrintWriter
================================================
* 作用、用法与 PrintStream 相同
* 区别:
*) PrintStream 只能接字节流
*) PrintWriter 能接字节流,也能接字符流
java.io.ObjectInputStream / ObjectOutputStream
======================================================
* 对象序列化、反序列化
* 序列化头部数据
*)新建 ObjectOutputStream 时,
会先自动输出 4 个头部字节值
*)新建 ObjectInputStream 时,
会先自动读取 4 个头部字节值,
来确认,后面是对象序列化数据,
如果头部字节值不正确,会出现异常
* 不序列化的成员变量
static 属于类,不随对象一起序列化输出
transient 临时,程序运行期间临时在内存中存在,
不会序列化持久保存
* 序列化版本号
旧版本的数据,
不能恢复成新版本的类型
创建对象
--------------------------------------
ObjectOutputStream out =
new ObjectOutputStream(相接的流);
方法
--------------------------------------
ObjectOutputStream
---------------------------------
writeObject(Object obj)
序列化
对象变成字节序列输出
ObjectInputStream
---------------------------------
readObject()
反序列化
读取序列化字节数据,恢复对象
java.io.ByteArrayInputStream / ByteArrayOutputStream
===============================================================
* 低级流
* 与 byte[] 数组相接,读写数组中的数据
创建对象
--------------------------------------
ByteArrayInputStream in =
new ByteArrayInputStream(byte[]数组);
插在事先存在的数组上,从指定的数组读取
ByteArrayOutputStream out =
new ByteArrayOutputStream();
内部维护一个 byte[] 数组,
输出的字节值,放入它的内部数组中,
取出内部数组:
byte[] a = out.toByteArray();
方法
-------------------------------------
ByteArrayOutputStream
------------------------------
toByteArray()