IO 流

来源:互联网 发布:电动插桶泵淘宝 编辑:程序博客网 时间:2024/05/17 02:30

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

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

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

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

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

一、字符流的由来:

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

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

就出出现了编码问题。

中文字节数据 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盘。

思路:

1c盘的文件是一个数据的源。

复制到的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();

}

}

}