IO

Java流操作有关的类和接口

说明
File 文件类
RandomAccessFile 随机存取文件类
InputStream 字节输入流
OutputStream 字节输出流
Reader 字符输入流
Writer 字符输出流

Java流类库结构图:

流的概念和作用

流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。

即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。

 

IO流的分类

  • 根据处理数据类型的不同分为:字符流和字节流
  • 根据数据流向不同分为:输入流和输出流

字符流和字节流

字符流的由来: 因为数据编码的不同,而有了对字符进行高效操作的流对象。本质其实就是基于字节流读取时,去查了指定的码表。 字节流和字符流的区别:

  • 读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。
  • 处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。

结论:只要是处理纯文本数据,就优先考虑使用字符流。 除此之外都使用字节流。

输入流和输出流

对输入流只能进行读操作,对输出流只能进行写操作,程序中需要根据待传输数据的不同特性而使用不同的流。 

关于File

File包括文件和目录,对文件和目录的操作是新建目录mkdir,新建文件createNewFile,删除文件和目录delete。

BufferedInputStream

==============================

BufferedInputStream对外提供滑动读取的功能,通过预先读入一整段原始输入流数据至缓冲区中,而外界对BufferedInputStream的读取操作实际上是在缓冲区上进行,如果读取的数据超过了缓冲区的范围,那么BufferedInputStream负责重新从原始输入流中载入下一截数据填充缓冲区,然后外界继续通过缓冲区进行数据读取。

这样的设计的好处是:避免了大量的磁盘IO,因为原始的InputStream类实现的read是即时读取的,即每一次读取都会是一次磁盘IO操作(哪怕只读取了1个字节的数据),可想而知,如果数据量巨大,这样的磁盘消耗非常可怕。

而通过缓冲区的实现,读取可以读取缓冲区中的内容,当读取超过缓冲区的内容后再进行一次磁盘IO,载入一段数据填充缓冲,那么下一次读取一般情况下就直接可以从缓冲区读取,减少了磁盘IO。

说白了buffered就是用来缓存的,可以用来提高读取的效率,之所以说FileInputStream是阻塞的方法是因为CUP的速度和磁盘的速度是不匹配的,如果每次要读取的时候都访问磁盘这样就造成了阻塞。

通过以上的说明可以看出buffered则并不是阻塞的。所以我们读取文件的时候一般都在文件流上边套上一层buffer流。

==============================

数据在硬盘上都是以字节的方式存储的,那么什么时候使用字符流,什么时候使用字节流呢?

字符流是对字符操作的,也就是对文本文件或者其他字符文件操作。

而对于图片,声音,视频这些文件则用字节流操作。

接下来是对字符流的操作,字符流相当于是字节流+编码表。

可以向文件中直接写入字符串。读取的时候注意是用字符数组接受,不是字节数组。

 1 package qugeng;
 2 
 3 import java.io.File;
 4 import java.io.FileReader;
 5 import java.io.FileWriter;
 6 import java.io.IOException;
 7 
 8 public class Test {
 9 
10     public static void main(String[] args) throws IOException {
11         File file = new File("file.txt");
12 
13         FileReader reader = new FileReader(file);
14         FileWriter writer = new FileWriter("2.txt");
15 
16         int len;
17         char[] buf = new char[1024];
18         while ((len = reader.read(buf)) != -1) {
19             System.out.println(new String(buf, 0, len));
20             writer.write(buf, 0, len);
21         }
22         writer.write("\r\n" + "end");
23         reader.close();
24         writer.close();
25     }
26 }

以下是缓冲的字符流。经过缓冲以后可以读取和写入一行的数据

package qugeng;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class Test {

    public static void main(String[] args) throws IOException {
        File file = new File("file.txt");
        BufferedReader bufferedReader = new BufferedReader(new FileReader(file));
        BufferedWriter bufferWriter = new BufferedWriter(
                new FileWriter("2.txt"));
        String buf;
        while ((buf = bufferedReader.readLine()) != null) {
            bufferWriter.write(buf);
            bufferWriter.newLine();
            System.out.println(buf);
        }
        bufferedReader.close();
        bufferWriter.close();
    }
}

最后解决的一个问题是字节流和字符流的转化,使用的是InputStreamReader和OutputStreamWriter,它们本身属于的是reader和writer字符流。

之所以会用到这些转化流是因为系统有时候只给我们提供了字节流,为了方便操作,要用到字符流。

比如说System.in标准输入流就是字节流。你想从那里得到用户在键盘上的输入,只能是以转换流将它转换为Reader以方便自己的程序读取输入。

再比如说Socket里的getInputStream()很明显只给你提供字节流,你要想读取字符,就得给他套个InputStreamReader()用来读取。

posted on 2015-04-16 15:47  夜雨梧桐  阅读(249)  评论(0编辑  收藏  举报

导航