java自学之路-day16
JAVA16
IO流
转换流
引入
l 中文系统默认编码表GBK
l FileWriter的构造方法假定默认编码GBK
l 但是一些文本文件有可能是其他编码方式
l 所以引入转换流 可以对编码表进行设定
l 对之后开发互联网程序很重要
概述
l 字符流的一种
l 字符与字节的桥梁
l 继承Writer类
OutputStreamWriter
l Java.io. OutputStreamWriter
l 继承Writer类
l 字符输出流 向文本文件写入数据
l 字符流转为字节流
l 图解
OutputStreamWriter将文本转换为设定的码表的字节表示形式,再由FileOutputStream写入
l 示例
- GBK
- UTF-8
l 使用默认编码表多一点
InputStreamReader
l 字节流转为字符流
l 继承Reader类
l 图解
- FileInputStream读取文件 一次读一个字节
- 一个字节不能查码表
- 因此转换流让FileInputStream继续读取 直到可以查询码表
- 转换流查询完毕返回字符到程序
l 示例
- GBK
- UTF-8
??表示没查到 gbk的字节表现形式 即负数 在UTF-8中没有存在
转换流和子类区别
l OutputStreamWrite和InputStreamReader字符和字节之间的桥梁 当要求的和默认编码表不同时 就需要用这两个父类进行转换为规定的编码中的字符或者字符的表现形式 然后进行输入或输出 原理是 字节流+编码表 然后用字节流将其输入或输出 通过编码表找出对应的字符或负数
l 子类没有转换功能 方便操作 不需要编码表 直接写一个文件路径 默认编码表就可以
l 一旦需要制定其他编码时 需要使用父类
字节缓冲流
引入
l 流对象读取文件
l 读取大量数据时 需要使用数组
l Sun公司也有解决办法
l 提供了一套缓冲流 提高效率
l Buffered开头
字节缓冲流
BufferedOutputStream
l 实现缓冲的输出流 应用程序可以将各个字节写入底层输出流中 不必针对每次字节写入调用底层系统
l 图解
- 写一串数据 一个一个写太慢 因为流本身不处理 每次交给系统处理 这样会太消耗资源
l 示例
- java.io.BufferedOutputStream
- 提高原有输出流的写入效率
- 继承OutputStream
- 方法可以写入字节 和字节数组
- 构造方法 参数是字节输出流
BufferedOUtputStream(OutputStream out)
- 可以传递任意的字节输出流
- 传递的是哪个字节流 就对哪个字节字节流提高效率
BufferedInputStream
l 继承InputStream
l 可以读取字节 和 数组
l 和键盘输入有关
l System.in中的in是InputStream类型
l 输出为
子类对象就是BufferedInputStream
l System.out子类对象时PrintStream
l 示例
四种文件复制方式的比较
l 字节流读写单个字节进行复制
l 字节流读写字节数组进行复制
l 字节流缓冲区读取单个字节
l 字节缓冲区读写字节数组
字符输出缓冲流
BufferedWriter
l Java.io.BufferedWriter
l 继承Writer
l 字符的高效写入
l 写入方法write() 可以是单个字符 字符数组 字符串
l 构造方法 BufferedWriter(Writer w)传递任意字符输出流
l FileWriter OutputStreamWriter
l 示例
l 具有一个特有的方法
- void newLine();
\r\n
newline()方法
- 选择newLine()
- 因为方法具有平台无关性 可跨平台
- Windows \r\n
Linux \n
- System.out.println();中的换行println就是用的newLine()方法
BufferedReader
l 继承Reader
l 子类 LineNumReader
l 从字符输入流中读取文本 缓冲各个字符 从而实现字符 数组 和行的高效读取
l 有独特的功能 读取文本中的一行 String readLine()
l 可以读一个字符 和 字符数组
l String readLine()
- 遇到\r \n则一行结束
- 返回该内容的字符串 不包含终止符
- 读到末尾就返回null
l LineNumberReader子类 读取行号
l 示例
- 构造方法 参数可以是任意字符输入流
- FileReader inputStreamReader
- 独有的功能 String readLine()
- 获取内容方法一般都有返回值
Int 如果没有返回的都是负数
引用类型 找不到 返回null
Bollean 找不到返回的都是false
- 循环读取
- readLine()返回的字符串包括换行符号 如果打印去掉ln会
- 行号
- 有一个子类LineNumberReader可以实现行号
字符缓冲区流复制文本文件
多了两个字节
复制过去多了一个空行
因为循环到最后执行了一个readLine()
流的操作规律
l 怎么选择流对象
l 操作的是数据源还是数据目的 即使向程序输入数据 还是从程序写入数据
l 要操作的是文本还是字节
l 明确数据所在的具体设备
内存
网络
Socket 网络中的套接字 两台机器都有 就能互连成功 用字节流
l 是否需要额外功能
所有流对象
字节流 输入流 从指定文件读取 高效流 设置缓冲区高效读取 输出流 将数据写入指定文件 高效流 设置缓冲区高效写入
字符流 输出字节转换流 输出需要写入文件的字符在规定编码中的负数表示形式 输出流 将数据写入指定文件 高效流 设置缓冲区高效写入 输入字节转换流 输入程序需要读取的字符在规定编码中的负数表示形式 输入流 从指定文件读取 高效流 设置缓冲区高效读取
|
inputStream
Properties类
介绍
l Hashtable集合中的一个子类
l Hashtable 是Map接口的实现类
l Hashtable 子类
l 没有泛型
l Map集合中的方法都能用
l 是一个可以持久化的属性集
l 键和值可以存储到集合中 也可以存储到持久化设备中 键值的来源也可以是持久化设备
l 有和流技术相结合的方法
load 和store
l java.util
l 可以和IO对象结合使用 实现数据的持久存储
方法
- setProperty(String key,String value) 等同于 put
- getProperty(String key)等同于 get
- StringPropertyNames 将集合中的键存储到set集合 相当于 keyset
- 特有功能 load
- load(InputStream in)load(Reader r) 流对象读取文件中的键值对 保存在集合中
文件
示例
#注释
- store(OutputStream out)store(Write w)store(Write w ,String comment)
comment说明
- 接收所有字节或者字符的输出流 将集合中的键值对存储到文件中
示例
Comment(写入文件的原因)不建议写中文 因为会被写为UTF-8的字节码
可以写英文或者不写
之后开发可以写类名 非常实用
对象序列化和反序列化
序列化
l 对象中的数据 以流的形式写入文件中保存
l 过程称为写出对象 对象的序列化
l 写对象是字节流
l ObjectOutputStream 对象输出字节流
反序列化
l 在文件中以流的形式将对象从文件读取出来
l 过程称为对象的反序列化
l ObjectInputStream
ObjectOutputStream流写对象
l Java.io.ObjectOutputStream
l 将java基本数据类型和图形写入OutputStream
l 构造方法 需要有一个字节输出流 OutputStream
l 传递任意的字节输出流
l void writeObject(Object obj)写出对象的方法
l 示例
出现了异常
serializable是个空接口 没有方法
实现接口后没有异常成功写入
ObjectInputStream流读取对象
l 先创建字节输入流对象
l 然后创建反序列化流对象 传入字节输入流对象
l 构造方法
ObjectInputStream(InputStream in)
l 方法 readObject()
写入对象时是object对象,读取的也是object对象 所以 需要强转一下
l 示例
readObject抛出了两个异常 io异常 和 类找不到异常
如果把class文件删除就会报类找不到异常
静态不能序列化
l 如果把对象中的成员变量改为静态
l 示例
先写入
再读取
a ge为零
普通输出不会为零
因为静态变量不属于对象,属于类 是共享数据 因为成员变量有默认值所以是0
transient关键字
l 瞬态关键字
l 修改时的成员变量不能被序列化
l 只有这一种用法
Serializable
l 标识接口
l 用于标识序列化
l 不具备任何功能
l Cloneable 也是标识接口 克隆接口
序列化中的序列号冲突问题
l 先写入对象序列化
l 修改源码
l 再进行读取
l 出现了异常
- …UID不一样
编译的类文件流的UID和本地的类文件UID不一样 序列号冲突
l 原理
- 源文件 .java
- Jvm编译成为 .class文件
- 编译器会根据类的定义 会给class文件中计算一个序列号
- Class文件包括源代码和序列号
- ObjectOutputStream 写对象 将序列号和变量写入文件中
- 改动源码 序列号改变
- ObjectInputStream 读取对象将序列号读取出来和本地类的序列号比较 相同就读取成功 否则失败
- 所以就出现了序列号冲突异常
l 冲突解决
- 即使修改源代码也不会重新计算序列号
- 需要做一个终身不变的序列号
- 复制 粘贴
- 从
复制粘贴
一旦确定不能修改 否则等于无效
打印流
特性
l PrintStream字节打印流 PrintWriter 字符打印流
l 继承OutputStream
l 永远不会抛出IOException 但可能会抛出其他异常
l 为其他输出流添加了功能
l 常用PrintWriter
l 两个类方法都一样
l 但是构造器不一样
构造方法就是打印流的输出目的端
PrintStream
接收File类型 OutputStream 字符串文件名
PrintWriter
接收File类型 字符串文件名 OutputStream 字符输出流Writer
方法
l print println
l 示例
println原样输出 write 查询码表
输出语句是char数组
只有char数组能打印出来元素
方法里做了数组的遍历
其他数组只把引用对象是变为了字符串
l 为什么
因为
如果不遍历 字符串“abc”就打印不出来
打印流输出目的是String和流对象
构造方法里是String
构造方法里是流对象
- 字节流
- 字符流
打印流开启自动刷新
l 输出目的必须是流对象
l 必须调用println printf format中的其中一个方法才可以使用
l
l 示例
不需要flush 但是必须要close
l 扩展
可以将其他对象转换为流对象 再自动刷新也可以
打印流复制文本
l 读取数据源不能用打印流
l 写入数据目的可以使用打印流加自动刷新
l 示例
Commons io工具类
介绍
l 下载 apache官网下载
l 目录介绍
- 使用的jar包
- 帮助文档
- 源码
- 测试源码
使用
l 导入jar包
l 导入源码
FilenameUtils
l 方法都是静态的
getExtension
l 获取文件名的扩展名 返回String类型的扩展名
l 示例
源码
getName
l 获取文件名
l 示例
isExtension
l 判断文件名后缀是否为指定后缀
l 返回 true 和false
l 示例
源码
区分大小写
FileUtils
l 功能很多
l 静态方法
l 直接使用
static String readFileToString(File file)
l 接收File对象
l 将文件直接读取 返回一个字符串
l 示例
static void writeStringToFile(File file, String data)
l 将字符串直接写到文件中
static long copyFile(File src,File desc)
l 复制文件
l 示例
static void copyDirectoryToDirectory(File srcDir, File destDir)
l 复制文件夹
l 示例