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[])方法。
//将读取到的字符存