黑马程序员_day22_IO流 (一)

2014-11-24 11:47:31 · 作者: · 浏览: 0

IO流用来处理设备之间的数据传输

Java对数据的操作是通过流的方式

Java用于操作流的对象都在IO包中

流按操作数据分为两种:字节流和字符流

流按流向分为:输入流、输出流

一、字符流的由来:

以前处理数据都是字节数据,使用字节流技术就可以完成了。


因为后期编码表的不断出现,识别某一文字的码表不唯一。比如中文,GBK,unicode都可以识别。

就出出现了编码问题。


中文字节数据 gbk --> 流处理--->gbk解析可以了。


后期:容器出现这样的问题:

中文字节数据gbk --> 流处理 unicode来处理-->数据错误。


为了处理文字数据,就需要通过 字节流技术+编码表 相结合来完成。注意:只有文字是这样的,因为文字涉及编码问题。

其他数据比如dvd mp3 图片等是不涉及这个问题的。


虽然字节流+编码表可以解决文字数据处理问题,但是较为麻烦。

为了便于使用,将字节流和编码表进行了封装,就出现了便于文字操作的流技术:字符流。

其实字符流就是:字节流+编码表。

二、IO的体系

字节流两个基类:

InputStream(字节输入流) OutputStream(字节输出流)


字符流两个基类:

Reader(字符输入流) Writer(字符输出流)


学习io流体系:看顶层(父类共性功能),用底层(子类具体对象)。


该体系的一个好处就是:

每个子类的后缀名都是所属体系的父类的名称,很容易区分所属的体系。而且每一个子类前缀名都是该子类对象的功能体现。

三、练习


1、需求:将一个段文字数据写入到硬盘上.

思路:

1,一段文字就是字符串数据。

2,写到硬盘上,字符串数据在内存中,是将内存中的数据搞 到硬盘上,这就涉及到了设备之间的数据处理。就要用到IO 技术。从内存到硬盘,应该是输出流。

3,对于文字而言,io中提供了便捷的操作,比如字符流。

4,结合两者,需要输出流,需要字符流,可使用字符输出流。 Writer

5,具体用哪个子类对象呢?硬盘上用于存储数据的体现:文 件。希望可以在Writer体系中知道可以操作文件的Writer对象。

找到了具体的对象FileWriter.


1,通过FileWriter创建流对象。构造时,必须明确写入数据需要存储的位置。

该对象一创建,目的文件就会被创建。

如果该文件已经存在,会被覆盖。

做了什么事呢?在堆内存中创建一个对象。同时调用了系统的资源。

FileWriter fw = new FileWriter("demo.txt");

当前目录下创建demo.txt文件。

2,使用字符输出流对象将字符串进行写入。调用写入方法。

数据没有直接写入到目的文件中,而是写入到了临时缓冲中。

fw.write("abcdef");


3,怎么把数据弄到文件中呢?Writer类中有一个flush()方法。刷新缓冲区,将缓冲的数据立即写入到目标中。

fw.flush();

4,关闭此流,关闭资源。在关闭之前,先刷一次缓冲,将数据都写入到目的中。

fw.close();


fw.write("XIXI");//Stream closed流已关闭。不能再写


flush()和close()有什么区别?

flush():仅将缓冲中的数据刷新到目的地。流对象可以继续使用。可以使用多次。

close():将缓冲中的数据刷到目的地后,直接关闭流资源,流无法继续使用。只能使用一次。

在close()方法当中其实在关闭之前都会调用一次flush();


2、需求:想要来个续写。

这个对象创建是不行的,因为该构造一创建,就覆盖了已有的文件。

可以使用另一个构造函数,加入一个boolean参数,为true,就可以实现续写。

3、需求:想要将数据分行写入。

window中的特有软件比如notepad。只识别window中的特有换行 \r\n.

为了在不同系统平台下换行。可使用System类获取当前系统信息。

续写和换行的代码:

private static final String LINE_SPARATOR = System.getProperty("line.separator");


public static void main(String[] args) throws IOException {

FileWriter fw = new FileWriter("tempfile\\demo2.txt",true);

fw.write("xi"+LINE_SPARATOR+"xi");

fw.close();

}


四、IO异常的处理规范

IO异常的处理规范: 创建流对象。 在try外创建流对象的引用。 在try内对流对象进行初始化。

FileWriter fw = null;

try {

fw = new FileWriter("k:\\demo3.txt");

fw.write("abcde");

fw.flush();

} catch (IOException e) {

System.out.println(e.toString());

} finally {

if (fw != null)健壮性判断否则会出现空指针异常。注意如果 需关闭多个流,则需一个一个的判断

try {

fw.close();

} catch (IOException e) {

相关的代码处理。比如说,将关闭失败的信息记录到日志 文件中。

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

}

}


五、FileReader 读取字符

public static void main(String[] args) throws IOException {

使用FileReader在构造时明确被读取的文件。

通过FileReader和指定的文件相关联。

FileReader fr = new FileReader("tempfile\\demo.txt");


调用字符读取流对象的read方法。对关联的文件进行读取。

read():一次读取一个字符。并返回该字符的对应的数字。

读取到什么字符,就返回什么字符,读到结尾就返回-1.用-1来标示结束了。

// int ch = fr.read();

// System.out.println("ch="+ch);

// int ch1 = fr.read();

// System.out.println("ch1="+ch1);

// int ch2 = fr.read();

// System.out.println("ch2="+ch2);

// int ch3 = fr.read();

// System.out.println("ch3="+ch3);


//代码使用循环解决

int ch = 0;

while((ch=fr.read())!=-1){

System.out.println((char)ch);

}

//关闭资源。

fr.close();

}


FileReader读取字符的方式二


需求:演示Reader中的read(char[]);读取方法。 这种读取的效率要比第一种高的多。

FileReader fr = new FileReader("tempfile\\demo.txt");


//创建一个字符数组。

char[] buf = new char[1024];


//调用了Reader中的read(char[])方法。

//将读取到的字符存