首先讲到的是File类,首先查看
博客文章“Java IO File类总结”
流类:
流的概念:
---java程序通过流来完成输入/输出。流是生产或消费信息的抽象。流通过Java的输入/输出系统与物理
设备链接。尽管与
他们链接的物理设备不尽相同,所有流的行为具有同样的方式。这样,相同的输入/输出类和方法适用于所有类型的外部设备。这意味着一个输入流能够抽象多种不同类型的输入:从磁盘文件,从键盘或从网络套接字。同样,一个输出流可以输出到控制台,磁盘文件或相连的网络。流是处理输入/输出的一个洁净的方法,例如它不需要代码
理解键盘和网络的不同。Java中流的实现是在java.io包定义的类层次结构内部的。
输入/输出流的概念:
---输入/输出时,数据在通信通道中流动。所谓“数据流(stream)”指的是所有数据通信通道之中,数据的起点和终点。信息的通道就是一个数据流。只要是数据从一个地方“流”到另一个地方,这种数据流动的通道都可以称为数据流。
---输入/输出是相对于程序来说的。程序在使用数据时所扮演的角色有两个:一个是源,一个是目的。若程序是数据流的源,即数据的提供者,这个数据流对程序来说就是一个“输出数据流”(数据从程序流出)。若程序是数据流的终点,这个数据流对程序而言就是一个“输入数据流”(数据从程序外流向程序)
输入/输出类:
---在java.io包中提供了60多个类(流)。
---从功能上分为两大类:输入流和输出流。
---从流结构上可分为字节流(以字节为处理单位或称面向字节)和字符流(以字符为处理单位或称面向字符)。
---
字节流的输入流和输出流基础是InputStream和OutputStream这两个抽象类,字节流的输入输出操作由这两个类的子类实现。字符流是Java 1.1版后新增加的以字符为单位进行输入输出处理的流,字符流输入输出的基础是抽象类Reader和Writer。
字符流底层也是采用字节流实现的。在底层,所有的输入/输出都是字节形式的。基于字符的流只处理字符提供方便有效的方法。
Java 2定义了两种类型的流:字节流和字符流。字节流(byte stream)为处理字节的输入和输出提供了方便的方法。例如
使用字节流可以读取或写入二进制数据。字符流(character stream)为字符的输入和输出提供了方便。它们采用了统一的
编码标准,因而可以国际化。当然,在某些场合,字符流比字节流更有效。
---字节流类(Byte Streams) 字节流类用于向字节流读写8位二进制的字节。一般的,字节流类主要用于读写诸如图像或声音等的二进制数据。
---字符流类(Character Streams) 字符流类用于向字符流读写16位二进制字符。
两种基本的流是:输入流(Input Stream)和输出流(Output Stream)。可从中读出一系列字节的对象称为输入流。而能向其中写入一系列字节的对象称为输出流。
输入流:
读数据的逻辑为:
open a stream【打开一个流,就像一个水库,开砸了才能取水】
while more information【一次不可能把全部信息读取完,读一部分之后while判断是否还有更多信息】
read information【还有更多信息的话就继续读取信息】
close the stream【读取完信息之后关闭流,流是一种资源,必须关闭了其他地方才能再使用,比如我打开一个文件,但是没有关,那么我就删不掉这个文件,一样的道理】
写数据的逻辑为:
open a stream
while more information
write information
close the stream
流的下一个分类(节点流和过滤流):
节点流直接是和目标交互的,比如说我要从
硬盘上读取一个文件,那么这个节点流就是针对于文件的流,直接和文件进行连接的,在读取的过程当中,我可以对节点刘进行一个过滤(比如读取到信息之后我可以对它进行一个包装,增加一些新的功能等),这就是过滤流。过滤流总是与节点流打交道或是与其他的过滤流打交道,而节点刘总是与特定的目标信息打交道的。
字节流类以InputStream和OutputStream为顶层类,他们都是抽象类(abstract)
抽象类InputStream和OutputStream定义了实现其他流类的关键方法。最重要的两种方法是read()和write(),他们分别对数据的字节进行读写。两种方法都在InputStream和OutputStream中被定义为抽象方法。
它们被派生的流类重写。
每个抽象类都有多个具体的子类,这些子类对不同的
外设进行处理,例如磁盘文件,网络连接,甚至是
内存缓冲区。
InputStream三个基本的读方法:
---abstract int read():读取一个字节数据,并返回读到的数据,如果返回-1,表示读到了输入流的末尾。
---int read(byte[] b):将数据读入一个字节数组,同时返回实际读取的字节数。如果返回-1,表示读到了输入流的末尾。
---int read(byte[] b, int off, int len):将数据读入一个字节数组,同时返回实际读取的字节数。如果返回-1,表示读到了输入流的末尾。Off指定在数组b中存放数据的其实偏移位置;len指定读取的最大字节数。
问题:为什么只有第一个read方法是抽象的,而其余两个read方法都是具体的?
答案:因为第二个read方法依靠第三个read方法来实现,而第三个read方法又依靠第一个read方法来实现,所以说只有第一个read方法是与具体的I/O设备相关的,它需要InputStream的子类来实现。
Jdk提供的InputStream的每一个子类里面都要重写read()这个方法,而用于完成不同功能的输入流子类,他们重写read()方法的实现方式肯定是不同的。这个read()方法你即便在InputStream你给我定义好了,我的子类里面也一定需要把它重写,你定义的肯定是不符合要求的,这不就符合抽象类的它的含义么(包含抽象方法,包含具体方法,它的子类必须实现抽象方法),具体read()的实现方式你根据自己的实际需求来定,
假如你是处理网络的,你就按照网络的那种方式来实现,假如你是处理字节数组的,你就按照字节数组的那种方式来实现,你处理文件的,就按照文件的方式来实现…..。所以InputStream不同的子类对read()方法的实现完全是不一样的。
下面实际开发中流的使用最最常见的一种用法(固定模式):
class="java">package com.shengshiyuan.io2;
import java.io.File;
import java.io.FileInputStream;
/**
* 输入流使用的常见的通用使用方式
* 类: InputStreamTest1 <br>
* 描述: TODO <br>
* 作者:
* 时间: Nov 13, 2013 3:23:44 PM
*/
public class InputStreamTest1 {
public static void main(String[] args) throws Exception {
FileInputStream inputStream = new FileInputStream(new File(
"C:/a/hello.txt"));
byte[] b = new byte[200];
StringBuffer str = new StringBuffer();
int length = 0;
// 从0开始读,最多读200个,并返回实际读取到的字节个数赋给length
while ((length = inputStream.read(b, 0, 200)) != -1) {
// 把字节数组转换成字符串,从第0个位置开始转,并指定将length个字节转换成字符。绝对不能写200哈,因为最后一次读取到的字节数很可能不够200个
String s = new String(b, 0, length);
str.append(s);
}
System.out.println(str.toString());
inputStream.close();
}
}
- 大小: 40.4 KB
- 大小: 23.7 KB