黑马程序员————IO流(1)
2015-08-11 16:51
441 查看
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流!-------
一、基本概念
IO流即输入(Input)输出(Output)流,用来处理设备之间的数据传输。
流:可以理解为数据的流动,就是一个数据流。IO流的最终要以对象来体现,对象都存在IO包中。
流的分类:
按操作数据:字节流和字符流
字节流:处理字节数据的流对象。设备上的数据无论是图片或者MP3,文字,它们都以二进制存储的。二进制的最终都是以一个8位为数据单元进行体现,所以计算机中的最小数据单元就是字节。意味着,字节流可以处理设备上的所有数据,所以字节流一样可以处理字符数据。
那么为什么要有字符流呢?因为字符每个国家都不一样,所以涉及到了字符编码问题,那么GBK编码的中文用unicode编码解析是有问题的,就是说一个中文用不能的码表可能出现的结果不同,所以需要获取中文字节数据的同时+ 指定的编码表才可以解析正确数据。为了方便于文字的解析,所以将字节流和编码表封装成对象,这个对象就是字符流。只要操作字符数据,优先考虑使用字符流体系。
按流向:输入流(读),输出流(写)
输入:将外设中的数据读取到内存中
写入:将内存中的数据写入到外设中
IO流的体系:有四个顶层的基类
字节流的顶层基类:
1.InputStream 2.OutputStream
字符流的顶层基类:
1.Reader 2.Writer
注:这四个类派生出的子类的名称,都是以父类的名作为子类名的后缀
例如:OutputStream的子类FileOutputStream
Reader的子类FileReader
二、字符流
1.一些需求来了解字符流
(1)需求1:将一些文字存储在硬盘中的文件中
close()和flush()的区别:
flush():将缓冲区的数据刷到目的地中后,流可以使用。可以使用多次
close():将缓冲区的数据刷到目的地中后,流就关闭了,该方法主要用于结束调用的底层资源。这个动作一定做。只能用一次,后面不能在写入数据了。
补充:
1.换行
2.续写
FileWriter fw = new FileWriter("demo.txt",true);
在原来的demo.txt文件后面续写内容
(2)异常的处理
(2)需求2:读取文本文件
注意:使用Reader体系,读取一个文本文件中的数据。返回 -1 ,标志读到结尾。
读取方式一:demo.txt文件的内容是 ab,每次读一个
(3)需求3:复制文本文件
方式一:
方式二:
(4)需求4:高效的复制--------用字符流缓冲区
字符流缓冲区:
BufferedWriter
-----newLine()方法:写一行换一行
BufferedReader
-----readLine()方法:读一行换一行
复制文本文件:
(5)装饰设计模式
含义:就是对已有的对象的功能进行增强
例子:
装饰和继承的区别:
相同点:
都能进行功能的扩展增强
不同点:
装饰更灵活,而继承如果体系多了,会显得比较臃肿。
比如说:
有一个体系:
Writer
|--TextWriter:用于操作文本
|--MediaWriter:用于操作媒体。
想要对操作的动作进行效率的提高
此时的体系就变为:
Writer
|--TextWriter:用于操作文本
|--BufferTextWriter:加入了缓冲技术的操作文本的对象。
|--MediaWriter:用于操作媒体。
|--BufferMediaWriter:加入了缓冲技术的操作媒体的对象。
如果这个体系还要进行功能的扩展,又多了流对象,那么这个流要提高效率,也要产生子类,这时就会发现只为提高功能,进行的继承,导致继承体系越来越臃肿。不够灵活。
而用装饰:
class BufferWriter extends Writer
{
BufferWriter(TextWriter text)
{}
BufferWriter(MedianWriter media)
{}
}
// 上面这个类扩展性很差。
// 找到其参数的共同类型,通过多态的形式,可以提高扩展性。例如:
class BufferWriter extends Writer
{
private Writer r;
BufferWriter(Writer r)
{}
}
Writer
|--TextWriter:用于操作文本
|--MediaWriter:用于操作媒体。
|--BufferWriter:用于提高效率。
三、字节流
需求1:复制Mp3
方法1:
方法2:
需求2:复制一个文本文件
需求3:将键盘录入信息,并写入到一个文件中
需求4:将一个文本的内容显示在控制台上
需求5:将键盘录入的信息显示在控制台上
四、流的操作规律
1,明确源和目的(汇)
源:InputStream Reader
目的:OutputStream Writer
2,明确数据是否是纯文本数据。
源:是纯文本:Reader
否:InputStream
目的:是纯文本 Writer
否:OutputStream
3,明确具体的设备。
源设备:
硬盘:File
键盘:System.in
内存:数组
网络:Socket流
目的设备:
硬盘:File
控制台:System.out
内存:数组
网络:Socket流
4,是否需要其他额外功能。
1,是否需要高效(缓冲区);
是,就加上buffer.
2,转换。
五、转换流的编码解码
发现转换流有一个子类就是操作文件的字符流对象:
InputStreamReader
|--FileReader
OutputStreamWriter
|--FileWrier
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(
"gbk_3.txt"), "GBK");
// FileWriter fw = new FileWriter("gbk_1.txt");
/*
* 这两句代码的功能是等同的。 FileWriter:其实就是转换流指定了本机默认码表(简体中文版的系统默认码表是GBK)的体现。而且这个转换流的子类对象,可以方便操作文本文件。
* 简单说:操作文件的字节流+本机默认的编码表。 这是按照默认码表来操作文件的便捷类。
* 如果操作文本文件需要明确具体的编码。FileWriter就不行了。必须用转换流。
*/
osw.write("你好");
osw.close();
如果需要制定码表,必须用转换流。
转换流 = 字节流+编码表。
转换流的子类File = 字节流 + 默认编码表。
凡是操作设备上的文本数据,涉及编码转换,必须使用转换流。
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流!-------
一、基本概念
IO流即输入(Input)输出(Output)流,用来处理设备之间的数据传输。
流:可以理解为数据的流动,就是一个数据流。IO流的最终要以对象来体现,对象都存在IO包中。
流的分类:
按操作数据:字节流和字符流
字节流:处理字节数据的流对象。设备上的数据无论是图片或者MP3,文字,它们都以二进制存储的。二进制的最终都是以一个8位为数据单元进行体现,所以计算机中的最小数据单元就是字节。意味着,字节流可以处理设备上的所有数据,所以字节流一样可以处理字符数据。
那么为什么要有字符流呢?因为字符每个国家都不一样,所以涉及到了字符编码问题,那么GBK编码的中文用unicode编码解析是有问题的,就是说一个中文用不能的码表可能出现的结果不同,所以需要获取中文字节数据的同时+ 指定的编码表才可以解析正确数据。为了方便于文字的解析,所以将字节流和编码表封装成对象,这个对象就是字符流。只要操作字符数据,优先考虑使用字符流体系。
按流向:输入流(读),输出流(写)
输入:将外设中的数据读取到内存中
写入:将内存中的数据写入到外设中
IO流的体系:有四个顶层的基类
字节流的顶层基类:
1.InputStream 2.OutputStream
字符流的顶层基类:
1.Reader 2.Writer
注:这四个类派生出的子类的名称,都是以父类的名作为子类名的后缀
例如:OutputStream的子类FileOutputStream
Reader的子类FileReader
二、字符流
1.一些需求来了解字符流
(1)需求1:将一些文字存储在硬盘中的文件中
public static void main(String[] args) throws IOException { //读、写都会发生IO异常 /* 1:创建一个字符输出流对象,用于操作文件。该对象一建立,就必须明确数据存储位置,是一个文件。 2:对象产生后,会在堆内存中有一个实体,同时也调用了系统底层资源,在指定的位置创建了一个存储数据的文件。 3:如果指定位置,出现了同名文件,文件会被覆盖。 */ FileWriter fw = new FileWriter("demo.txt"); // FileNotFoundException /* IO异常出现的原因是,如果我写入的路径是"k:/demo.txt",可是将这个程序给别人,被人没有k盘,就出现了异常。下面会说具体的处理方法。 */ /* 调用Writer类中的write(String)方法写入字符串。字符串并未直接写入到目的地中,而是写入到了流中,(其实是写入到临时存储缓冲区中)。怎么把数据弄到文件中? */ fw.write("abcde"); fw.flush(); // 刷新缓冲区,将缓冲区中的数据刷到目的地文件中。 fw.close(); // 关闭流,其实关闭的就是java调用的系统底层资源。在关闭前,会先刷新该流。 }
close()和flush()的区别:
flush():将缓冲区的数据刷到目的地中后,流可以使用。可以使用多次
close():将缓冲区的数据刷到目的地中后,流就关闭了,该方法主要用于结束调用的底层资源。这个动作一定做。只能用一次,后面不能在写入数据了。
补充:
1.换行
private static final String LINE_SEPARATOR =System.getProperty("line.separator"); public static void main(String[] args) throws IOException { FileWriter fw = new FileWriter("demo.txt"); fw.write("abc"+LINE_SEPARATOR+"cdef"); fw.close(); }
2.续写
FileWriter fw = new FileWriter("demo.txt",true);
在原来的demo.txt文件后面续写内容
(2)异常的处理
FileWriter fw = null; try { fw = new FileWriter("x:/Demo.txt");//可能没有x盘 fw.write("haha"); //写入失败 } catch (IOException e) { System.out.println(e.toString()); }finally{ try { if(fw!=null) //因为路径错误,fw就创建不出来,就会出现空指针异常 fw.close(); } catch (IOException e) { throw new RuntimeException("关闭失败"); } }
(2)需求2:读取文本文件
注意:使用Reader体系,读取一个文本文件中的数据。返回 -1 ,标志读到结尾。
读取方式一:demo.txt文件的内容是 ab,每次读一个
FileReader fr = new FileReader("demo.txt"); int ch=0; while((ch=fr.read())!=-1) System.out.println((char)ch); 读取方式二:用字符数组 FileReader fr = new FileReader("demo.txt"); char[] buf = new char[1024]; int len = 0; while((len = fr.read(buf))!=-1){ System.out.println(new String(buf,0,len)); }
(3)需求3:复制文本文件
方式一:
FileReader fr = new FileReader("Io_test.txt"); FileWriter fw = new FileWriter("Io_test1.txt"); int len = 0; while((len = fr.read())!=-1){ fw.write(len); } fw.close(); fr.close();
方式二:
FileReader fr = null; FileWriter fw = null; try { fr = new FileReader("Io_test.txt"); fw = new FileWriter("Io_test2.txt"); char[] buf = new char[1024]; int len = 0; while((len = fr.read(buf))!=-1){ fw.write(buf, 0, len); } } catch (IOException e) { e.printStackTrace(); }finally{ if(fr!=null) try{fr.close();} catch(IOException e){ throw new RuntimeException("关闭失败"); } if(fw!=null) try{fw.close();} catch(IOException e){ throw new RuntimeException("关闭失败"); } }
(4)需求4:高效的复制--------用字符流缓冲区
字符流缓冲区:
BufferedWriter
-----newLine()方法:写一行换一行
BufferedReader
-----readLine()方法:读一行换一行
复制文本文件:
FileReader fr = new FileReader("Buffered.txt"); BufferedReader bufr = new BufferedReader(fr); FileWriter fw = new FileWriter("copy_Buffered.txt"); BufferedWriter bufw = new BufferedWriter(fw); String line = null; while((line = bufr.readLine())!=null){ bufw.write(line); bufw.newLine(); bufw.flush(); } bufw.close(); bufr.close();
(5)装饰设计模式
含义:就是对已有的对象的功能进行增强
例子:
class Person{ void chifan(){ System.out.println("吃饭"); } } class NewPerson{ //为了不改变源代码,并且增强Person,这个类就出现了 private Person p; NewPerson(Person p){ this.p = p; } void chifan(){ System.out.println("喝点红酒"); p.chifan(); System.out.println("吃点甜点"); } }
装饰和继承的区别:
相同点:
都能进行功能的扩展增强
不同点:
装饰更灵活,而继承如果体系多了,会显得比较臃肿。
比如说:
有一个体系:
Writer
|--TextWriter:用于操作文本
|--MediaWriter:用于操作媒体。
想要对操作的动作进行效率的提高
此时的体系就变为:
Writer
|--TextWriter:用于操作文本
|--BufferTextWriter:加入了缓冲技术的操作文本的对象。
|--MediaWriter:用于操作媒体。
|--BufferMediaWriter:加入了缓冲技术的操作媒体的对象。
如果这个体系还要进行功能的扩展,又多了流对象,那么这个流要提高效率,也要产生子类,这时就会发现只为提高功能,进行的继承,导致继承体系越来越臃肿。不够灵活。
而用装饰:
class BufferWriter extends Writer
{
BufferWriter(TextWriter text)
{}
BufferWriter(MedianWriter media)
{}
}
// 上面这个类扩展性很差。
// 找到其参数的共同类型,通过多态的形式,可以提高扩展性。例如:
class BufferWriter extends Writer
{
private Writer r;
BufferWriter(Writer r)
{}
}
Writer
|--TextWriter:用于操作文本
|--MediaWriter:用于操作媒体。
|--BufferWriter:用于提高效率。
三、字节流
需求1:复制Mp3
方法1:
FileInputStream fis = new FileInputStream("0.mp3"); FileOutputStream fos = new FileOutputStream("2.mp3"); byte[] buf = new byte[1024]; int len=0; while((len=fis.read(buf))!=-1){ fos.write(buf,0,len); fos.flush(); } fis.close(); fos.close();
方法2:
BufferedInputStream buis = new BufferedInputStream(new FileInputStream("0.mp3")); BufferedOutputStream buos = new BufferedOutputStream(new FileOutputStream("5.mp3")); int ch = 0; while((ch=buis.read())!=-1){ buos.write(ch); buos.flush(); } buis.close(); buos.close();
需求2:复制一个文本文件
BufferedReader bufr = new BufferedReader(new FileReader("键盘录入.txt")); BufferedWriter bufw = new BufferedWriter(new FileWriter("键盘录入1.txt")); String line = null; while((line = bufr.readLine())!=null){ if("over".equals(line)) break; bufw.write(line); bufw.newLine(); bufw.flush(); } bufr.close(); bufw.close();
需求3:将键盘录入信息,并写入到一个文件中
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in)); BufferedWriter bufw = new BufferedWriter(new FileWriter("键盘录入.txt")); String line = null; while ((line = bufr.readLine()) != null) { if ("over".equals(line)) break; bufw.write(line); bufw.newLine(); bufw.flush(); } bufr.close(); bufw.close();
需求4:将一个文本的内容显示在控制台上
BufferedReader bufr = new BufferedReader(new FileReader("键盘录入.txt")); BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out)); String line = null; while((line = bufr.readLine())!=null){ if("over".equals(line)) break; bufw.write(line); bufw.newLine(); bufw.flush(); } bufr.close(); bufw.close();
需求5:将键盘录入的信息显示在控制台上
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in)); BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out)); String line = null; while((line=bufr.readLine())!=null){ if ("over".equals(line)) break; bufw.write(line); bufw.newLine(); bufw.flush(); } bufr.close(); bufw.close();
四、流的操作规律
1,明确源和目的(汇)
源:InputStream Reader
目的:OutputStream Writer
2,明确数据是否是纯文本数据。
源:是纯文本:Reader
否:InputStream
目的:是纯文本 Writer
否:OutputStream
3,明确具体的设备。
源设备:
硬盘:File
键盘:System.in
内存:数组
网络:Socket流
目的设备:
硬盘:File
控制台:System.out
内存:数组
网络:Socket流
4,是否需要其他额外功能。
1,是否需要高效(缓冲区);
是,就加上buffer.
2,转换。
五、转换流的编码解码
发现转换流有一个子类就是操作文件的字符流对象:
InputStreamReader
|--FileReader
OutputStreamWriter
|--FileWrier
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(
"gbk_3.txt"), "GBK");
// FileWriter fw = new FileWriter("gbk_1.txt");
/*
* 这两句代码的功能是等同的。 FileWriter:其实就是转换流指定了本机默认码表(简体中文版的系统默认码表是GBK)的体现。而且这个转换流的子类对象,可以方便操作文本文件。
* 简单说:操作文件的字节流+本机默认的编码表。 这是按照默认码表来操作文件的便捷类。
* 如果操作文本文件需要明确具体的编码。FileWriter就不行了。必须用转换流。
*/
osw.write("你好");
osw.close();
如果需要制定码表,必须用转换流。
转换流 = 字节流+编码表。
转换流的子类File = 字节流 + 默认编码表。
凡是操作设备上的文本数据,涉及编码转换,必须使用转换流。
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流!-------
相关文章推荐
- 黑马程序员————其他类对象
- 面试题记录(B1)
- 黑马程序员————集合类
- 黑马程序员————String类
- 为了面试,准备的知识点
- 写给新手程序员的一封信
- 黑马程序员————多线程
- 黑马程序员————异常
- 2014年终总结——-我的匆匆这一年(面试,毕业季,工作)
- IT面试
- 程序员技术练级攻略
- 黑马程序员————内部类
- 黑马程序员——java复习总结——Java基础知识
- 2015/8/11 网易游戏测试开发面试
- 为什么程序员的业余项目大多都死了?
- 写了个以程序员为主角的虚拟现实小说《天堂》
- 十道海量数据处理面试题与十个方法大总结
- 搜集到的面试题。
- 黑马程序员——面向对象封装-第9天
- 黑马程序员——iOS开发须知