----------- android培训、java培训、java学习型技术博客、期待与您交流! ---------
IO(Input Output)
(一)破题
IO流用来处理数据设备之间的数据传输;Java对数据的操作是通过流的方式;Java用于操作流的对象都在IO包中;
流按操作数据分为两种:字节流与字符流;
流按流向分为两种: 输入流(读取内存),输出流(写入外设);
数据是以(二进制)字节形式存在的。字节流可以处理所有对象。
字符流其实就是字节流+编码表;如果要操作文字数据,优先考虑字符流。
(二)简述
一、 IO流常用基类:
字节流的抽象基类:InputStream , OutputStream;
字符流的抽象基类:Reader,Writer.
这些体系中大多的子类都以父类名做后缀,子类名的前缀就是该对象的功能
二、 IO字符流常用子类:
Writer (体系)
|——FileWriter
2) FileWriter往一个文件中写入文字数据;如果文件不存在,则会自动创建;如果存在文件则会覆盖
2)FileWriter类中常用方法。
2.11)刷新数据flush( ); 返回值为void
2.12)关闭数据流 close();返回值为void;
此方法在关闭流资源之前会先调用flush方法刷新再关闭;
与flush方法比较:flush可以用多次,但是close方法只能用一次
2.13)写入数据 write();返回值为void
2.14)续写数据 在构造函数中加入true 可以实现续写;
FileWriter(String FileName,boolean true)
异常处理细节:
流对象一般会抛出异常,在try的外面进行对象的创建;在try内进行对象引用。
记着要判断空指针异常。
Reader (体系)
|——FileReader
2.) FileReader:读取字符数据的流对象,在创建读取对象时,必须要明确被读取的文件,一定要确定该文件是存在的。
2.)FileReader类中常用的方法
2.21) 读取数据 read();有重载方法,有多种返回类型
三、
3.)字符流缓冲区:缓冲区的出现提高了对数据的读写效率。缓冲区要结合流才可以使用。
在流的基础上对流的功能进行了增强,(虽然也可以自定义缓冲区)。
这样可以使用字符流缓冲区对外提供的方法。
对应类BufferedWriter BufferedReade
3.1)BufferedWriter (体系)
|——
BufferedWriter类中常用方法
3.11)write( ) 写入数据进缓冲区
3.12)flush()刷新
3.13)newLine( ) 换行(此方法为BufferedWriter类特有,其他类不适用)
使用系统方法实现平台的换行操作:System.getProperty("line.separator")
3.2)BufferedReader (体系)
|—— 3.3) LineNumberReader(子类)
BufferedReader类常用方法
3.21)read( ) 读取数据进缓冲区:可读取 字符型数据;数组数据;换行标记
3.22)readLine()读取一个行;返回值类型String
此方法使用读取缓冲区的read方法,将读取的字符进行缓冲并判断换行标记。将标记前的缓冲数据变成字符串返回。
此方法适用情景:对行的操作,如索引行中关键字;
了解:装饰设计模式——使用情景功能扩展
装修设计模式 与通过 继承实现情景功能扩展 的区别: 只为实现功能扩展而继承使得继承体系变得越来越臃肿庞杂,不够灵活。
将功能进行单独的封装,哪个对象需要扩展功能,就在将哪个对象和功能关联。
装饰比继承灵活 ;特点:装饰类和被装饰类必须属于同一接口或者父类。
3.3)LineNumberReader类常用方法
3.31)getLineNumber() 此方法显示行号
四、IO流字节流
字节流与字符流相比而言,处理的数据单元不同;操作的数据文件格式不同,字符流只能操作文本文件,而字节流可以操作媒体文件。
字节流基类InputStream , OutputStream;
IO字符流常用子类:
InputStream (体系)
|——FileInputStream
4.1)FileInputStream:往一个文件中写入文字数据;如果文件不存在,则会自动创建;如果存在文件则会覆盖
4.1)FileInputStream类中常用方法。
4.11)获取字节的个数available()返回int
4.12)关闭字节流close( ); 返回值为void
为什么用字符流不能复制一个图片格式的文件?
字符流再读取源数据后,又进行匹配编码表操作,其中,可能有一些字符不被识别或替换了原有的字符,导致文件内容的变动,不能完成复制操作。
字符流是处理文本对象的专业对象,不能用来操作媒体文件。
关于编解码:编码——看的懂的转换为看不懂的;解码——把看不懂的转换为看得懂的。
转换流:
字节流与字符流之间的转换;他们转换的关键问题就是编码表;
(字符流实质就是字节流+编码表)
InputStream (体系)
|——InputStreamReader
InputStreamReader 类是字节流同乡字符流的桥梁,他使用 指定的charset读取字节并将其解码为字符。它使用的字符集可以由名称指定或显示给定,或者接受平台默认的字符集。
4.2) InputStreamReader 常用方法
4.21) InputStreamReader( InputStream in) 构造方法
字符流与字节流之间的转换
OutputStream;
|——OutputStreamWriter
OutputStreamWriter 类是字符流通向字节流的桥梁;他使用 指定的charset读取字节并将其编码为字符。它使用的字符集可以由名称指定或显示给定,或者接受平台默认的字符集。
4.3)OutputStreamWriter 常用方法
4.31)OutputStreamWriter( OutputStream out) 构造方法
五、流操作中的规律
转换流: InputStreamReader : 字节到字符的桥梁。——解码
OutputStreamWriter : 字符到字节的桥梁。——编码
规律: (1)明确源和目的(汇)
源 涉及的体系:InputStream Reader
汇 涉及的体系:OutputStream Writer
(2)明确数据是否是纯文本数据
源 是纯文本:Reader
否:InputStream
汇 是纯文本:Writer
否:OutputStream
(3)明确具体的设备
源设备:
硬盘:File
键盘:System,in
内存:数组
网络:Socker流
汇设备:
硬盘:File
控制台:System.out
内存:数组
网络:Socker 流
(4)是否需要额外对象
1.是否需要高效(缓冲区)—— buffer
六、Test 小练习
6.1)
package com.IO;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/**
* 需求:复制一个文本文件
*
* 思路:
* 1.明确源和目的源 InputStream Reader;目的 OutputStream Writer
* 2.是否为纯文本是源:Reader 目的 :Writer
* 3.明确具体设备源:硬盘:File目的:硬盘:File
* 4.扩展额外功能需要 缓冲区
* @author ASUS
*
*/
public class CopyTextTest{
/**
* @throws IOException
*/
public static void main(String[] args) throws IOException {
//1.确定源和目的对象
BufferedReader bufr = new BufferedReader(new FileReader("a.txt"));
BufferedWriter bufw = new BufferedWriter(new FileWriter("b.txt"));
//2.判断条件,循环写入,刷新缓冲
String line;
while((line = bufr.readLine())!= null){
//读行
bufw.write(line);
//换行
bufw.newLine();
//刷新
bufw.flush();
}
//3.缓冲关流
bufr.close();
bufw.close();
}
}
6.2)package com.IO;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* 需求2:读取键盘录入信息,并写入一个文件中
* 思路:
* 1.明确源和目的;源——InputStream Reader 目的——OutputStream Writer
* 2.是否是纯文本:是源——Reader目的——Writer
* 3.明确设备 源——键盘:System.in目的——硬盘:File
* 4.是否需要功能高效——缓冲区;转换——字节流转换为字符流
*/
public class ReadKeyText {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
//创建字节输入源对象,并关联键盘
InputStreamReader isr = new InputStreamReader(System.in);
//创建目标接收字符流对象并关联目标文件
FileWriter fw = new FileWriter("c.txt");
//高效读取缓冲区
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
//高效写入缓冲区
BufferedWriter bufw = new BufferedWriter(new FileWriter("c.txt"));
//变量
int ch = 0;
//循环 判断 写入 刷新
while((ch = bufr.read())!= -1){
bufw.write((char)(ch));
bufw.flush();
}
//关闭流资源
bufw.close();
bufr.close();
}
}
6.3)
package com.IO;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
/**
* 需求:将文本文件数据显示在控制台上
* 1.明确源和目的:源——InputStream Reader 目的——OutputStream Writer
* 2.是否为纯文本:是源——Reader 目的——Writer
* 3.明确具体设备: 源——硬盘 File;目的——控制台
* 4.额外功能:转换
*/
public class ReadKeyText02 {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
//创建读取流对象,并关联文件,缓冲区提高效率
BufferedReader bufr = new BufferedReader(new FileReader("a.txt"));
//创建输出流对象,并关联输出设备,缓冲区提高效率
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));
int ch = 0;
while((ch = bufr.read())!= -1){
bufw.write((char)(ch));
bufw.flush();
}
bufw.close();
bufr.close();
}
}
6.4)package com.IO;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
/**
*需求:读取键盘录入数据,显示在控制台上
*思路:
*1.明确源和目的:源——InputStream Reader 目的——OutputStream Writer
*2.是否为纯文本:是 源——Reader目的——Writer
*3.明确设备:源——键盘目的——控制台
*4.扩充功能: 缓冲转换
*/
public class ReadKey04 {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
//读取字节
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
//输出字符
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));
String line;
while((line = bufr.readLine())!= null){
bufw.write(line);
bufw.newLine();
bufw.flush();
}
bufw.close();
bufr.close();
}
}
FileWriter:其实就是转换流指定了本机默认码表的体现。而且这个转换流的子类对象,可以方便操作文本文件。(操作文件的字节流+本机默认的编码表),这是按照默认编码表来操作文件的便捷类。但是如果,操作文本文件明确了编码表就不行了,需要用字节流
GDK码表中:一个汉字两个字节;UTF-8:一个汉字三个字节;
一般打开文件是一堆中文乱码,那么极可能是用录入时用其他码表,而用GDK来解码的文件。
如果打开文件是一堆符号,那么极可能是用GDK来录入,而用其他码表解码的。
转换流使用的情景:
1.源 或者 汇 的对应设备是字节流,但是操作的却是文本数据,可以使用转换作为桥梁。
2.一旦操作文本涉及到指定编码表时,必须使用转换流。
Properties集合对IO流的操作
Properties集合是Map集合的子类,可记录键值对,多用于配置文件的设置;
方法store()
setProperties方法()
打印流:1.PrintStream:提供打印的方法,可以为多种数据类型提供打印方法
2.不抛IOException
构造函数,接收三种类型的值
1.字符串路径
2.File对象
3.字节流
Out.write();的特点:只写8位
字符打印流:printWriter
序列流:有序的排列 一个流对象关联一个源,我有多个数据,关联多个流;
(集合容器封装多个流)
文件切割
1.确定切割条件(按大小;按切割个数)
2.一个源文件流;多个输出流(有几个目的文件关联几个流)
3.自定义缓冲区
关键:设置配置文件获取文件切割个数,及后缀名;键值对Properties对象,在切割时生成
文件合并
1.获取配置文件对象2.判断配置文件个数3.读取配置文件信息4.把切割后文件匹配配置文件信息 5.将碎片文件和流对象关联并使用集合对象存储 6.合并文件多个流合并成一个序列流
关键:通过过滤器来获取配置文件(配置文件要唯一);来确定需合并的个数和合并后源文件类型
序列化
操作对象的流:对象的序列化,实质:把存入硬盘的对象进行排列
对象的序列化;对象的反序列化
操作情景:
ObjectInputStream与ObjectOutputStream
被操作的对象需要实现Serializable (标记接口);
RandomAccessFile
随机访问文件,自身具备读写的方法。
通过skipBytes(int x),seek(int x)来达到随机访问。
特点:
1.该对象即能读又能写
2.该对象内部维护了一个byte数组,并通过指针可以操作数组中的元素
3.可以通过getFilePointer方法获取指针的位置,和通过seek方法设置指针的位置
4.其实该对象就是将字节输入流和输出流进行了封装。
5.该对象的源或者目的只能是文件,通过构造函数就可以看出。
管道流
PipedInputStream和PipedOutputStream
输入输出可以直接进行连接,通过结合线程使用。
操作基本数据类型
DataInputStream与DataOutputStream
操作字节数组
ByteArrayInputStream与ByteArrayOutputStream
操作字符数组
CharArrayReader与CharArrayWrite
操作字符串
StringReader 与 StringWriter
字符编码
字符流的出现为了方便操作字符。
更重要是的加入了编码转换。
通过子类转换流来完成。
InputStreamReader
OutputStreamWriter
在两个对象进行构造的时候可以加入字符集
计算机只能识别二进制数据,早期由来是电信号。
为了方便应用计算机,让它可以识别各个国家的文字。
就将各个国家的文字用数字来表示,并一一对应,形成一张表。
这就是编码表。
ASCII:美国标准信息交换码。
用一个字节的7位可以表示。
ISO8859-1:拉丁码表。欧洲码表
用一个字节的8位表示。
GB2312:中国的中文编码表。
GBK:中国的中文编码表升级,融合了更多的中文文字符号。
Unicode:国际标准码,融合了多种文字。
所有文字都用两个字节来表示,Java语言使用的就是unicode
UTF-8:最多用三个字节来表示一个字符。
......
可以将字符以指定编码格式存储。
可以对文本数据指定编码格式来解读。
指定编码表的动作由构造函数完成。