IO(Input Output)流:
Java用于操作流的对象都在IO包中
流按照操作数据分为两种:字节流和字符流
流按流向分为:输入流,输出流
IO流常用基类:
字节流的抽象基类:
InputStream OutputStream
字符流的抽象基类:
Reader Writer
注:由这四个类派生出来的子类名称都是以其父类名作为子类名的后缀
如:
InputStream的子类FileInputstream
Reader的子类FileReader
进行IO异常处理
在finally中对流进行关闭
思考:
字符流:创建文件
创建流对象,建立数据存放文件
FileWriter fw = new FileWriter("Test.txt");
调用流对象的写入方法,将数据写入流
fw.write("text");
关闭流资源,并将流中的数据清空到文件中
fw.close();
不写close方法会有什么结果呢?
//写入到写入流中的数据不会被刷新到设备中,并且底层调用的系统资源不会被关闭。
如果想在原有文件上继续加入新数据呢?
//建立流对象时,构造函数中可以添加参数,是否在原文件继续加入新数据。
完整代码:
FileWriter fw = null;
try{
fw = new FileWriter("Test");
fw.write("text");
}
catch(IOException e){
System.out.println(e.toString());
}
finally{
if(fw!=null){
try{
fw.close();
}
catch(IOException e){
System.out.println(e.toString());
}
}
}
字符流:读取文件
建立一个流对象,将已存在的一个文件加载进流
FileReader fr = new FileReader("Test");
创建一个临时存放数据的数组。
char[] ch = new char[1024];
调用流对象的读取方法将流中的数据导入到数组中
fr.read(ch);
思考:
在加载文件时候是否是将文件全部加载进流?
//不是,只加载一部分。
为什么定义数组,要定义多大呢?
//为了把读取到的一个一个的字符临时存储起来,一次性操作读取到的数据。一般定义1024的整数倍。
完整代码:
FileReader fr = null;
try{
fr = new FileReader("c:\\Test.txt");
char[] ch = new char[1024*2];
len = 0;
while((len = fr.read(ch))!=-1){
System.out.println(new String(ch,0,len));
}
}
catch(IOException e){
System.out.println(e.toString());
}
finally{
if(fr!=null){
try{
fr.close();
}
catch(IOException e){
System.out.println(e.toString());
}
}
}
注意:
定义文件路径时,可以用“/”或者“\\”。
在创建一个文件时,如果目录下有同名文件将被覆盖。
在读取文件时,必须保证该文件已存在,否则出异常。
练习:Copy一个文本文件
字符流的缓冲区:
缓冲区的出现提高了对数据的读写效率。
对应类:
BufferedWriter
BuffereaReader
缓冲区要结合流才可以使用
在流的基础上对流的功能进行了增强。
装饰设计模式:
对原有类进行功能的改变,增强。
装饰模式的基本格式。
它与继承有什么不同?
//避免了继承体系的臃肿,只要是这个体系中的类,都可以使用该模式(多态),操作更加灵活。
了解BufferedReader的原理
练习:
模拟一个BufferedReader类。
模拟一个LineNumberReader类。
字节流:
基本操作与字符流类相同
但它不仅可以操作字符,还可以操作其他媒体文件
Copy一个jpg文件
字节流的缓冲区:
同样是提高了字节流的读取效率。
练习:
通过几种方式对MP3进行拷贝,比较它们的效率。
模拟一个BufferedInputStream
转换流:
InputStreamReader,OutputStreamWriter
转换流的由来:
字符流与字节流之间的桥梁
方便了字符流与字节流之间的操作
转换流的应用:
字节流中的数据都是字符时,转成字符流操作更高效。
标准输入输出流:
System类中的字段:in,out
它们各代表了系统标准的输入输出设备
默认输入设备是键盘,输出设备是显示器(控制台)
System.in的类型是InputStream
System.out的类型是PrintStream是OutputStream的子类,FilterOutputStream的子类。
标准输入输出流示例:
例:获取键盘录入数据,然后将数据流向显示器,那么显示器就是目的地。
通过System类的setIn,setOut方法对默认设备进行改变。
System.setIn(new FileInputStream("1.txt"));//将源改成文件1.txt
System.setOut(FileOutputStream("2.txt"));//将目的改成文件2.txt
因为是字节流处理的文本数据,可以转换成字符流,操作更方便。
BufferedReader bfr =
new BufferedReader(new InputStreamReader(System.in));
BufferedWriter brw = new BufferedWriter(new OutputStreamWriter(System.out));
流的基本应用小节:
流是用来处理数据的。
处理数据时,一定要先明确数据源,与数据目的地(数据汇)。
数据源可以是 文件、键盘、内存
数据目的地可以是 文件、控制台(屏幕)、内存。
而流只是在帮助数据进行传输,并对传输的数据进行处理,比如过滤处理,转换处理等。
File类
用来将文件或者文件夹封装成对象
方便对文件与文件夹的属性信息进行操作
File对象可以作为参数传递给流的构造函数
了解File类中的常用方法
递归:
函数自己调用自己
注意:递归时一定要明确结束条件
应用场景:
当某一功能要重复使用时
练习:
列出一个文件夹下所有的子文件以及子文件夹
思考:
删除一个目录的过程是如何进行的?
//通过递归,先将最里层的文件夹中的文件删除,然后删除该文件夹。
IO包中的其他类:
RandomAccessFile:
随机访问文件,自身具备读写的方法
通过skipBytes(int x),seek(int x)来达到随机方法
管道流:
PipedInputStream和PipedOutputStream
输入输出可以直接进行连接,通过结合线程使用。
打印流:
PrintWriter与PrintStream
可以直接操作输入流和文件
序列流:
SequenceInputStream
对多个流进行合并
操作对象
ObjectInputStream 与 ObjectOutputStream
被操作的对象需要实现Serializable(标记接口);
练习:
文件分割程序
操作基本数据类型:
DataInputStream与DataOutputStream
操作字节数组
ByteArrayInputStream与ByteArrayOutputStream
操作字符数组
CharArrayReader与CharArrayWriter
操作字符串
StringReader与StringWriter
字符编码:
字符流的出现为了方便操作字符
更重要的是加入了编码转换
通过子类转换流来完成
InputStreamReader
OutputStreamWriter
在两个对象进行构造的时候可以加入字符集
OutputStreamWriter = new OutputStreamWriter(new FileOutputStream("a.txt"),"GBK");
编码表的由来:
计算机只能识别二进制数据,早期由来是电信号
为了方便应用计算机,让它可以识别各个国家的文字
就将各个国家的文字用数字来表示,并一一对应,形成一张表
这就是编码表
常见的编码表:
ASCLL:美国标准信息交换码
用一个字节的7位可以表示
ISO8859-1:拉丁码表,欧洲码表
用一个字节的8位表示
GBK2312:中国的中文编码表
GBK:中国的中文编码表升级,融合了更多的中文文字符号
Unicode:国际标准码,融合了多种文字
UTF-8:最多用3个字节来表示一个字符
转换流的编码应用:
可以将字符以指定编码格式存储
可以对文本数据指定编码格式来解读
指定编码表的动作由构造函数完成
将“你好”两个字符查指定的utf-8的码表,获取对应的数字,并写入到text.txt文件中。
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(“text.txt”),”utf-8);
osw.write(“你好”);
osw.close();
读取硬盘上的文件数据,将获取到的数据查指定utf-8的码表来解析该数据。
InputStreamReader isr = new InputStreamReader(new FileInputStream(“text.txt”),”utf-8);
char[] buf = new char[10];
int num = isr.read(buf);
String s = new String(buf,0,num);
System.out.println(s);
传入编码表的方法都会抛出不支持编码异常(UnsupportedEncodingException);
字符编码:
编码:字符串--->字节数组 (写)
解码:字节数组--->字符串 (读)
举例:
将一个中文用gbk编码,用iso8859-1解码,乱码,
解决方式:对乱码进行iso8859-1编码,在用gbk解码即可。
问题:
用gbk编码,用utf-8解码,乱码,可是对乱码进行utf-8编码后,在用gbk解码,还是乱码??
因为,用gbk编码后的数字去查utf-8的码表时u8不识别,就直接用一个未知字符来表示,而这个未知字符是3个字节的。所以原数字码已经变化了,所以还原不回来了。
如果解错了,可以更换一个码表再解。
IO流用来处理设备之间的数据传输
Java对数据的操作是通过流的方式Java用于操作流的对象都在IO包中
流按照操作数据分为两种:字节流和字符流
流按流向分为:输入流,输出流
IO流常用基类:
字节流的抽象基类:
InputStream OutputStream
字符流的抽象基类:
Reader Writer
注:由这四个类派生出来的子类名称都是以其父类名作为子类名的后缀
如:
InputStream的子类FileInputstream
Reader的子类FileReader
IO程序的书写:
进行IO异常处理
在finally中对流进行关闭
思考:
有了垃圾回收机制为什么还要调用close方法进行关闭
答:垃圾回收器只能处理java虚拟机所产生的内存垃圾 而流所消耗的操作系统资源、硬件、网络资源等的外部资源 这不是java虚拟机能管的 当然也不是垃圾回收器能处理的。
为什么IO异常一定要处理字符流:创建文件
创建流对象,建立数据存放文件
FileWriter fw = new FileWriter("Test.txt");
调用流对象的写入方法,将数据写入流
fw.write("text");
关闭流资源,并将流中的数据清空到文件中
fw.close();
不写close方法会有什么结果呢?
//写入到写入流中的数据不会被刷新到设备中,并且底层调用的系统资源不会被关闭。
如果想在原有文件上继续加入新数据呢?
//建立流对象时,构造函数中可以添加参数,是否在原文件继续加入新数据。
完整代码:
FileWriter fw = null;
try{
fw = new FileWriter("Test");
fw.write("text");
}
catch(IOException e){
System.out.println(e.toString());
}
finally{
if(fw!=null){
try{
fw.close();
}
catch(IOException e){
System.out.println(e.toString());
}
}
}
字符流:读取文件
建立一个流对象,将已存在的一个文件加载进流
FileReader fr = new FileReader("Test");
创建一个临时存放数据的数组。
char[] ch = new char[1024];
调用流对象的读取方法将流中的数据导入到数组中
fr.read(ch);
思考:
在加载文件时候是否是将文件全部加载进流?
//不是,只加载一部分。
为什么定义数组,要定义多大呢?
//为了把读取到的一个一个的字符临时存储起来,一次性操作读取到的数据。一般定义1024的整数倍。
完整代码:
FileReader fr = null;
try{
fr = new FileReader("c:\\Test.txt");
char[] ch = new char[1024*2];
len = 0;
while((len = fr.read(ch))!=-1){
System.out.println(new String(ch,0,len));
}
}
catch(IOException e){
System.out.println(e.toString());
}
finally{
if(fr!=null){
try{
fr.close();
}
catch(IOException e){
System.out.println(e.toString());
}
}
}
注意:
定义文件路径时,可以用“/”或者“\\”。
在创建一个文件时,如果目录下有同名文件将被覆盖。
在读取文件时,必须保证该文件已存在,否则出异常。
练习:Copy一个文本文件
字符流的缓冲区:
缓冲区的出现提高了对数据的读写效率。
对应类:
BufferedWriter
BuffereaReader
缓冲区要结合流才可以使用
在流的基础上对流的功能进行了增强。
装饰设计模式:
对原有类进行功能的改变,增强。
装饰模式的基本格式。
它与继承有什么不同?
//避免了继承体系的臃肿,只要是这个体系中的类,都可以使用该模式(多态),操作更加灵活。
了解BufferedReader的原理
练习:
模拟一个BufferedReader类。
模拟一个LineNumberReader类。
字节流:
基本操作与字符流类相同
但它不仅可以操作字符,还可以操作其他媒体文件
Copy一个jpg文件
字节流的缓冲区:
同样是提高了字节流的读取效率。
练习:
通过几种方式对MP3进行拷贝,比较它们的效率。
模拟一个BufferedInputStream
转换流:
InputStreamReader,OutputStreamWriter
转换流的由来:
字符流与字节流之间的桥梁
方便了字符流与字节流之间的操作
转换流的应用:
字节流中的数据都是字符时,转成字符流操作更高效。
标准输入输出流:
System类中的字段:in,out
它们各代表了系统标准的输入输出设备
默认输入设备是键盘,输出设备是显示器(控制台)
System.in的类型是InputStream
System.out的类型是PrintStream是OutputStream的子类,FilterOutputStream的子类。
标准输入输出流示例:
例:获取键盘录入数据,然后将数据流向显示器,那么显示器就是目的地。
通过System类的setIn,setOut方法对默认设备进行改变。
System.setIn(new FileInputStream("1.txt"));//将源改成文件1.txt
System.setOut(FileOutputStream("2.txt"));//将目的改成文件2.txt
因为是字节流处理的文本数据,可以转换成字符流,操作更方便。
BufferedReader bfr =
new BufferedReader(new InputStreamReader(System.in));
BufferedWriter brw = new BufferedWriter(new OutputStreamWriter(System.out));
流的基本应用小节:
流是用来处理数据的。
处理数据时,一定要先明确数据源,与数据目的地(数据汇)。
数据源可以是 文件、键盘、内存
数据目的地可以是 文件、控制台(屏幕)、内存。
而流只是在帮助数据进行传输,并对传输的数据进行处理,比如过滤处理,转换处理等。
File类
用来将文件或者文件夹封装成对象
方便对文件与文件夹的属性信息进行操作
File对象可以作为参数传递给流的构造函数
了解File类中的常用方法
递归:
函数自己调用自己
注意:递归时一定要明确结束条件
应用场景:
当某一功能要重复使用时
练习:
列出一个文件夹下所有的子文件以及子文件夹
思考:
删除一个目录的过程是如何进行的?
//通过递归,先将最里层的文件夹中的文件删除,然后删除该文件夹。
IO包中的其他类:
RandomAccessFile:
随机访问文件,自身具备读写的方法
通过skipBytes(int x),seek(int x)来达到随机方法
管道流:
PipedInputStream和PipedOutputStream
输入输出可以直接进行连接,通过结合线程使用。
打印流:
PrintWriter与PrintStream
可以直接操作输入流和文件
序列流:
SequenceInputStream
对多个流进行合并
操作对象
ObjectInputStream 与 ObjectOutputStream
被操作的对象需要实现Serializable(标记接口);
练习:
文件分割程序
操作基本数据类型:
DataInputStream与DataOutputStream
操作字节数组
ByteArrayInputStream与ByteArrayOutputStream
操作字符数组
CharArrayReader与CharArrayWriter
操作字符串
StringReader与StringWriter
字符编码:
字符流的出现为了方便操作字符
更重要的是加入了编码转换
通过子类转换流来完成
InputStreamReader
OutputStreamWriter
在两个对象进行构造的时候可以加入字符集
OutputStreamWriter = new OutputStreamWriter(new FileOutputStream("a.txt"),"GBK");
编码表的由来:
计算机只能识别二进制数据,早期由来是电信号
为了方便应用计算机,让它可以识别各个国家的文字
就将各个国家的文字用数字来表示,并一一对应,形成一张表
这就是编码表
常见的编码表:
ASCLL:美国标准信息交换码
用一个字节的7位可以表示
ISO8859-1:拉丁码表,欧洲码表
用一个字节的8位表示
GBK2312:中国的中文编码表
GBK:中国的中文编码表升级,融合了更多的中文文字符号
Unicode:国际标准码,融合了多种文字
UTF-8:最多用3个字节来表示一个字符
转换流的编码应用:
可以将字符以指定编码格式存储
可以对文本数据指定编码格式来解读
指定编码表的动作由构造函数完成
将“你好”两个字符查指定的utf-8的码表,获取对应的数字,并写入到text.txt文件中。
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(“text.txt”),”utf-8);
osw.write(“你好”);
osw.close();
读取硬盘上的文件数据,将获取到的数据查指定utf-8的码表来解析该数据。
InputStreamReader isr = new InputStreamReader(new FileInputStream(“text.txt”),”utf-8);
char[] buf = new char[10];
int num = isr.read(buf);
String s = new String(buf,0,num);
System.out.println(s);
传入编码表的方法都会抛出不支持编码异常(UnsupportedEncodingException);
字符编码:
编码:字符串--->字节数组 (写)
解码:字节数组--->字符串 (读)
举例:
将一个中文用gbk编码,用iso8859-1解码,乱码,
解决方式:对乱码进行iso8859-1编码,在用gbk解码即可。
问题:
用gbk编码,用utf-8解码,乱码,可是对乱码进行utf-8编码后,在用gbk解码,还是乱码??
因为,用gbk编码后的数字去查utf-8的码表时u8不识别,就直接用一个未知字符来表示,而这个未知字符是3个字节的。所以原数字码已经变化了,所以还原不回来了。
如果解错了,可以更换一个码表再解。