----------- android培训、java培训、java学习型技术博客、期待与您交流! ------------
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[])方法。
//将读取到的字符存储到了数组中,并返回了读到的个数 。
// int len1 = fr.read(buf);
// System.out.println(len1+":"+new String(buf,0,len1));
// int len2 = fr.read(buf);
// System.out.println(len2+":"+new String(buf,0,len2));
// int len3 = fr.read(buf);
// System.out.println(len3+":"+new String(buf,0,len3));
// int len4 = fr.read(buf);
// System.out.println(len4+":"+new String(buf));
用循环
int len = 0;
while((len=fr.read(buf))!=-1){
System.out.println(new String(buf,0,len));
}
fr.close();
}
六、复制文本文件
练习:将c盘的一个文本文件复制到d盘。
思路:
1,c盘的文件是一个数据的源。
复制到的d盘,说明d盘是数据的存储的目的。该目的中应该有一个文件。
2,先读取c盘的文件。将读取到的数据写入到目的地中。
3,既然是操作文本文件,只要使用字符流即可。
方式一:读一个 写一个 效率低
public static void main(String[] args) throws IOException {
//1,创建字符读取流对象和源相关联。
FileReader fr = new FileReader("tempfile\\IO流.txt");
//2,创建字符输出流对象,明确要存储数据的目的。
FileWriter fw = new FileWriter("tempfile\\copy_demo.txt");
//3,进行读写操作。读取一个,就写入一个。
int ch = 0;
while((ch=fr.read())!=-1){
fw.write(ch);
}
//4,关闭资源。
fw.close();
fr.close();
}
方式二 :先将硬盘上的源文件数据通过输入流存储到内存中创建的缓存区,再从缓存区通过输出流写入目的文件中。效率高
使用缓冲区数组。
使用的就是可以操作数组的读写方法。
//1,定义字符输入流和字符输出流的引用。
FileReader fr = null;
FileWriter fw = null;
try {
//2,对流对象进行初始化。
fr = new FileReader("tempfile\\demo.txt");
fw = new FileWriter("tempfile\\copy_demo2.txt");
//3,定义一个数组缓冲区。用于缓冲读取到的数据。
char[] buf = new char[1024];
//4,读写操作。
int len = 0;
while((len = fr.read(buf))!=-1){
fw.write(buf,0,len);读入len个,就写len个字符
}
} catch (Exception e) {
System.out.println(e.toString());
}finally{
if(fw!=null)
try {
fw.close();
} catch (IOException e) {
throw new RuntimeException("写入关闭失败");
}
if(fr!=null)
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
七、字符串的缓冲区。BufferedWriter
缓冲区给给流的操作动作(读写)提高效率.所以缓冲区的对象建立必须要有流对象。
public static void main(String[] args) throws IOException {
//创建一个流对象。
FileWriter fw = new FileWriter("tempfile\\buf.txt");
//为了提高效率。创建缓冲区对象,并和要被提高效率的流相关联。
BufferedWriter bufw = new BufferedWriter(fw);
//接下来就使用缓冲区的方法。因为缓冲区的操作的都是数组中的元素的高效方法。
bufw.write("abcde");
bufw.newLine();换行=System.getProperty("line.separator");
bufw.write("xixixi");
//要对缓冲区进行刷新。记住:一般只要使用了缓冲区,就一定要刷新。
bufw.flush();
//关闭缓冲区。
bufw.close();//问:还用关闭fw.close()?不用,因为关闭缓冲区,其实就是在关闭缓冲区关联的流。
}
八、字符串的缓冲区BufferedReader
演示BufferedReader
1,先有字符读取流。
2,该类有一个特有方法。readLine().一次读一行。
//创建读取流对象和文件相关联。
FileReader fr = new FileReader("tempfile\\buf.txt");
//创建读取缓冲区对象和流对象关联,对其进行高效操作。
BufferedReader bufr = new BufferedReader(fr);
// String line1 = bufr.readLine();
// System.out.println("line1:"+line1);
// String line2 = bufr.readLine();
// System.out.println("line2:"+line2);
// String line3 = bufr.readLine();
// System.out.println("line3:"+line3);
// String line4 = bufr.readLine();
// System.out.println("line4:"+line4);
// String line5 = bufr.readLine();
// System.out.println("line5:"+line5);
String line = null;
while((line=bufr.readLine())!=null){
System.out.print(line);
}
bufr.close();
}
九、 使用缓冲区对文本文件进行复制。 该缓冲区也只能对文本文件
BufferedReader bufr = null;
BufferedWriter bufw = null;
try {
bufr = new BufferedReader(new FileReader("tempfile\\IO流.txt"));
bufw = new BufferedWriter(new FileWriter("tempfile\\copy_buf.txt"));
//读写行的操作。
String line = null;
while((line=bufr.readLine())!=null){
bufw.write(line);
bufw.newLine();
bufw.flush();
}
catch (Exception e) {
System.out.println(e.toString());
}finally{
if(bufw!=null)后开先关
try {
bufw.close();
} catch (IOException e) {
e.printStackTrace();
}
if(bufr!=null)
try {
bufr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}