您的位置:首页 > 职场人生

黑马程序员_IO流(上)

2012-09-15 00:34 239 查看
---------- android培训java培训、期待与您交流!
----------


IO流 (上)

1.理解:IO流即Input流和Output流;

输入流:外围设备——>核心处理器;

输出流:核心处理器——>外围设备;

总之:以内存为中心。

2.作用:用来处理设备之间的数据传输;设备又分为输入设备和输出设备;

3.字节流和字符流:

字节流:处理的数据都是字节;

字符流:由来:早期的字节流和编码表;

作用:为了更便于对文字数据的操作;在内部可以融合编码表。

体系技巧:该体系中的子类对象中,后缀名都是父类名称,前缀名都是该流对象的功能名称。

4.字节流的抽象基类:InputStream和OutputStream ;

5.字符流的抽象基类:Reader和Writer;

读——>输入; 写——>输出

操作文件中的数据:

1. 写:将字符串写入到指定文件中;

1.创建输出流对象;对象一建立就会将指定的文件创建出来,若存在同名文件,则被覆盖;

2.通过调用write方法来写入数据;该数据被写入到了缓冲区中;

3.通过调用flush()方法刷新流对象。将缓冲区的数据写入到目的地中;

4.通过调用close()方法将流对象关闭,但关闭之前会刷新流。

代码体现:

FileWriter fw=new FileWriter("c:\\jdk.txt");
fw.write("abscds");
fw.flush();
fw.close();


flush和close方法的区别:

flush():刷新流对象,流没有关闭; close():刷新流对象且关闭流。

IO异常的处理方式:

1.在创建输出流对象时,可能路径不存在,所以会抛异常;

2.写数据时可能磁盘空间不足,仍会抛异常;

3.关闭资源时,可能关闭失败,抛异常;

4.所以将这三句使用try...catch,将异常捕获;

5.但如果对象创建失败,就不能再调用close方法即不能关闭流对象;而使用完资源后必须关闭资源,所以将close放在finally语句块中;

6.在finally语句块中仍然需要抛异常;

7.对象变量名在try语句块中,则只能在try中使用,finally中就不能使用,则不能调用close方法;所以将变量定义在try外,将其初始化为空;

8.如果流对象创建失败,则一直为空,就不能调用close方法,则发生空指针异常;所以要判断到底是否为空,不为空再调用close方法。

代码体现如下:

FileWriter fw = null;
try {
fw = new FileWriter("demo.txt",true);
fw.write("hello"+LINE_SPARATOR+"world");
} catch (IOException e) {
System.out.println(e.toString());
} finally {
if (fw != null)
try {
fw.close();
} catch (IOException e) {

throw new RuntimeException("关闭失败");
}
}


小细节;1.续写文件中的内容:通过构造函数FileWriter(String,boolean):boolean 为真则续写;

2.将文件中的内容换行:

private static final String LINE_SEPARATOR=System.getProperty(line.separator);//获取当前系统的换行符
fw.write("Hello"+LINE_SEPARATOR+"World");


2.读:将指定文件的内容读取并打印出来;

第一种方式:通过read()读取单个字符,返回int,码值,若到结束标记则返回-1;

FileReader fr=new FileReader("d:\\demo.java");//对象一建立,就必须要明确被读取的文件
int i=0;//定义一个变量表示读取后的数值
while((i=fr.read())!=-1) {
System.out.println((char)i); //打印i所对应的字符
}
fr.close();


第二种方式:通过read(char[] chs)将读取到的字符存入到字符数组中,返回读取的字符个数,若到结束标记则返回-1;

FileReader fr=new FileReader("d:\\demo.java");//对象一建立,就必须要明确被读取的文件
int len=0;//定义一个变量表示读取的字符个数
char[] chs = new char[1024];//定义字符数组存储读取的字符,长度为2kb,因为一个字符2字节;
while((len=fr.read(chs))!=-1) {
System.out.println(new String(chs,0,len)); //打印字符数组中的"有效字符"
}
fr.close();


注意:如果在 char[] chs = new char[3];//若字符串为abcde,int len1=fr.read(chs);则此时,读取到的len1为3,读取到的内容是abc;若再
int len2=fr.read(chs);此时因数组长度至始至终都为3,从d开始 读,d覆盖a,读完e就遇到结束标记,而此时e就将b覆盖了,所以最终数组中的三个元素时dec;若再
int len3=fr.read(chs);此时已经读到结束标记了,所以返回-1.而chs中的元素仍然是dec.

3.复制文件的原理:从指定文件中读取文件的数据,将读取到的数据写入到另一个目的地。



6.字符流的缓冲区

1.好处:提高了对字符流读写数据的效率;若流不存在,则缓冲区存在没有意义;

2.对应抽象基类:BufferedWriter;BufferedReader

3.原理:将数据进行存储到数组中,字符流——>字符数组

4.方法:缓冲区中的写方法都是将数据写入到缓冲区中,读方法是从内存中读数据;

close():内部调用的是流对象中的close()方法,所以关闭缓冲区即关闭流;

newLine():内部调用System.getProperty("line.separator");获取系统的换行符;是缓冲区对象才能使用,特有方法。

5.BufferedReader 类:该类对象一建立,就创建了一个字符数组,默认长度为8192,同时多了一个提高行的效率;

read():读内存中的数据 ;而流对象中的read方法是从硬盘读数据;

readLine():读取一行文本,返回行内容,不返回行终止符,若到了末尾,则返回null;

readLine方法原理:内部调用了BufferedReader中的read方法,读到行终止符之前,将缓冲区中读取出来的字符临时存储,直到读到行终止符,将临时存储的数据
转成字符返回。

6.缓冲区的基本思想,提高效率的原理?

缓冲区的基本思想就是对要处理的数据进行临时存储。譬如购物车以及篮子。

原理:减少频繁的操作,给读取流对象和写入流对象提供中转站,相对于来回跑的麻烦,利用缓冲区的容量,可以一边先存储,满了后再写入的方式, 这样就提高了效
率。

7.缓冲区的原理分析:缓冲区一建立就已创建一个数组;

缓冲区中的read()方法:内部调用流的read([])方法,将硬盘上读出来的一部分数据到缓冲区的数组中;若缓冲区的数组中有数据,则调用read()方法将数组中的元素一个
一个的取出。

readLine():基于read()方法,read方法将缓冲区数组中的元素一个一个取出,当识别到数组中的元素为行终止符时,则不再取元素,将之前的元素取出打印,再去识别
数组中的元素。

8.装饰设计模式:

对一组对象进行功能的增强,职责的增强,还不改变原有对象(并不建议继承,否则体系逐渐庞大,不利于扩展和维护)。

建议;建立另一个类,持有原对象的引用,即与源对象相关联,对原对象进行装饰,比继承更灵活;

记住:被装饰类和装饰类必须属于同一个体系。

9.LineNumberReader 类:

BufferedReader 的子类,返回文本行,已定义了方法setLineNumber(int)和getLineNumber(),可分别用于设置和获取当前行号;默认 行标号从0开始 ,行号随
数据读取在每个行结束符递增,还可以更改行号;
若读完了返回null。

getLineNumber():获取行号;

10.字节流:什么数据都能处理;

InputStream OutputStream

FileOutputStream演示:

//1.自定义缓冲区数组 :复制mp3文件
FileInputStream fis=new FileInputStream("c:\\1.mp3");
FileOutputStream fos=new FileOutputStream("c:\\2.mp3");
byte[] by=new byte[1024];
int ch=0;
while((ch=fis.read())!=-1){
fos.write(by,0,ch);
}
fis.close();
fos.close();
//2.使用available()创建长度刚刚好的数组;
FileInputStream fis=new FileInputStream("c:\\1.mp3");
FileOutputStream fos=new FileOutputStream("c:\\2.mp3");
byte[] by=new byte[fis.available()];
int ch=0;
while((ch=fis.read())!=-1){
fos.write(by,0,ch);
}
fis.close();
fos.close();
//3.使用缓冲区复制
FileInputStream fis=new FileInputStream("c:\\1.mp3");
BufferedInputStream bis=new BufferedInputStream(fis);
FileOutputStream fos=new FileOutputStream("c:\\2.mp3");
BufferedOutputStream bos=new BufferedOutputStream(fos);
int by=0;
while((by=bis.read())!=-1){
bos.write(by);
}
bis.close();
bos.close();

//4.不使用缓冲区
FileInputStream fis=new FileInputStream("c:\\1.mp3");
FileOutputStream fos=new FileOutputStream("c:\\2.mp3");
int ch=0;
while((ch=fis.read())!=-1){
fos.write(ch);
}
fis.close();
fos.close();


开发时,建议使用第一种;

11.字节流和字符流读取区别:

字节流:一次只能读一个字节,半个中文;

字符流:一次能读两个字节,一个字符,一个中文;

注意:使用字符流不可以复制图片,因为字符流就是字节流+编码表,而用字符流去复制图片时,字符流会默认将图片的字节码格式进行编码,这样可能会导致 复制后的
图片与原图不一致。

12.字节流和字符流的桥梁:转换流,将字节流和编码表进行了封装,提供了对字符操作的更便捷方式。

由来:字节流读取中文,先将中文读取到字节数组中,通过String类的getBytes()方法将字节数组中的元素转为字符串,但这样不能读取单个中文,要读取 单个中文还得
通过toCharArray()方法将其转为数组;太过麻烦;所以引出字节流和字符流的桥梁——>InputStreamReader,OutputStreamWriter.

转换流的两个桥梁都是从哪里到哪里?

首先将文件通过InputStreamReader的方式将字节流数据转成字符流,为了高效,将其先存储到缓冲区中;

然后通过OutputStreamWriter将缓冲区中的字符数据转成字节,最后输出。

FileReader fr=new FileReader("XXX");
FileInputStream fis=new FileInputStream("XXX");
InputStreamReader isr=new InputStreamReader(fis);


上面三句话,第一句是第二句和第三句话的封装;FileReader是InputStreamReader类的子类,因为只有有了转换流,对字节进行查表编码,才可以读取字符,所
以FileReader方法都是来自转换流转化后的读写方法。

子父类的区别:FileReader是用于操作文本文件使用默认编码表的便捷类,因为它将字节流和编码表进行封装;如果操作的不是文件且不是默认编码表, 就不能用
RileReader类操作文件,而是用转换流,通过传入的具体字节流对象来确定指定操作的数据,而且还可以传入指定要使用的编码 表。

便捷类弊端 :因其是将文件、字节流和默认编码表封装,所以只能操作文件,而且只能使用默认编码表。

---------- android培训java培训、期待与您交流!
----------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: