一. 输入输出流的定义
输入流:程序从输入流读取数据源。数据源包括外界(键盘、文件、网络…),即是将数据源读入到程序的通信通道。可以类比为从水池(数据源)中的水(数据)导入房子(程序)。
输出流:程序向输出流写入数据。将程序中的数据输出到外界(显示器、打印机、文件、网络…)的通信通道。可以类比为从房子(程序)中把水(数据)流到下水道中(外界数据源)。
二.数据流的分类
流序列中的数据既可以是未经加工的原始二进制数据,也可以是经一定编码处理后符合某种格式规定的特定数据。因此Java中的流分为两种:
- 字节流:数据流中最小的数据单位是字节。
- 字符流:数据流中最小的数据单位是字符,在Java中,一个字符用两个字节表示。
三. Java IO层次的体系结构
(1)流式部分——IO的主体部分
(2)非流式部分——主要包含一些辅助流式部分的类,如:File类、RandomAccessFile类和FileDescriptor等类。
(3)其他部分——文件读取部分的与安全相关的类,如:SerializablePermission类,以及与本地操作系统相关的文件系统的类,如:FileSystem类和Win32FileSystem类和WinNTFileSystem类。
主要的类有:
1.File(文件特征与管理):用于文件或者目录的描述信息,例如生成新目录,修改文件名,删除文件,判断文件所在路径等。
2.InputStream(二进制格式操作,即字节流操作):抽象类,基于字节的输入操作,是所有输入流的父类。定义了所有输入流都具有的共同特征。
3.OutputStream(二进制格式操作):抽象类。基于字节的输出操作。是所有输出流的父类。定义了所有输出流都具有的共同特征。
4. Reader(字符流操作):抽象类,基于字符的输入操作。
5. Writer(字符流操作):抽象类,基于字符的输出操作。
6.RandomAccessFile(随机文件操作):它的功能丰富,可以从文件的任意位置进行存取(输入输出)操作。
四. Java IO流类库
java.io包中包含了流式I/O所需要的所有类。在java.io包中有四个基本类:InputStream、OutputStream及Reader、Writer类,它们分别处理字节流和字符流:
输入/输出 | 输入 | 输出 |
字节流 | InputStream | OutputStream |
字符流 | Reader | Writer |
由这个四个类可以派生出许多其他功能丰富的流
IO流的类型又可以分为以下几类:
1.Memory
- 从/向内存数组读写数据: CharArrayReader、 CharArrayWriter、ByteArrayInputStream、ByteArrayOutputStream
- 从/向内存字符串读写数据 StringReader、StringWriter、StringBufferInputStream
2.Pipe:实现管道的输入和输出(进程间通信)PipedReader、PipedWriter、PipedInputStream、PipedOutputStream
3.File文件流:对文件进行读、写操作 :FileReader、FileWriter、FileInputStream、FileOutputStream
4. Object输入输出:ObjectOutputStream,ObjectInputStream
5. 数据流:按基本数据类型读、写,处理的数据是Java的基本类型(如布尔型,字节,整数和浮点数),DataInputStream、DataOutputStream。
6.打印流: 包含方便的打印方法PrintWriter、PrintStream
7. Buffering:在读入或写出时,对数据进行缓存,以减少I/O的次数,BufferedReader、BufferedWriter、BufferedInputStream、BufferedOutputStream
8.Filter:在数据进行读或写时进行过滤FilterReader、FilterWriter、FilterInputStream、FilterOutputStream
9.转换流:按照一定的编码/解码标准将字节流转换为字符流,或进行反向转换,InputStreamReader、OutputStreamWriter
五. InputStream 与 OutputStream
InputStream 为字节输入流,它本身为一个抽象类,必须依靠其子类实现各种功能,此抽象类是表示字节输入流的所有类的超类。 继承自InputStream 的流都是向程序中输入数据的,且数据单位为字节。
InputStream类的常用方法
public abstract int read() throws IOException | 读取一个byte的数据,返回值是高位补0的int类型值。若返回值=-1说明没有读取到任何字节读取工作结束。 |
public int read(byte[] b) throws IOException | 读取b.length个字节的数据放到b数组中。返回值是读取的字节数 |
public int read(byte[] b, int off, int len) throws IOException | 从输入流中最多读取len个字节的数据,存放到偏移量为off的b数组中。 |
public void close() throws IOException | 关闭输入流 |
public int available() throws IOException | 返回输入流中可以读取的字节数。注意:若输入阻塞,当前线程将被挂起,如果InputStream对象调用这个方法的话,它只会返回0,这个方法必须由继承InputStream类的子类对象调用才有用, |
InputStream的使用实例:
1: public void InputStreamDemo(){
2: // 第一步:使用file类找到一个文件
3: File f = new File("D:" + File.separator + "test.txt");
4: try {
5: // 第二步:准备好一个输入流对象
6: InputStream input = new FileInputStream(f);
7: int len = 0;
8: byte[] b = new byte[1024];
9: int temp = 0;
10: // 第三步:利用read()循环读取
11: while((temp = input.read()) != -1){
12: // 将每次读取内容给temp变量,如果temp的值不是-1,表示文件没有读完
13: b[len] = (byte)temp;
14: len++;
15: }
16: // 第四步:关闭输入流
17: input.close();
18: } catch (FileNotFoundException e) {
19: // TODO Auto-generated catch block
20: e.printStackTrace();
21: } catch (IOException e) {
22: // TODO Auto-generated catch block
23: e.printStackTrace();
24: }
25:
26: }
OutputStream的使用实例:
1: public void OutputStramDemo(){
2: File file = new File("D:" + File.separator + "test.txt");
3: try {
4: OutputStream os = new FileOutputStream(file,true); //true表示在文件末尾追加内容
5: String str = "hello world";
6: byte[] b = str.getBytes();
7: for(int i = 0; i < b.length; i++){
8: os.write(b[i]);
9: }
10: os.close();
11: } catch (FileNotFoundException e) {
12: // TODO Auto-generated catch block
13: e.printStackTrace();
14: } catch (IOException e) {
15: // TODO Auto-generated catch block
16: e.printStackTrace();
17: }
18:
19: }
六. 缓冲输入输出流BufferedInputStream/BufferdeOutputStream
缓冲流就是每一个数据流分配一个缓冲区,一个缓冲区就是一个临时存储数据的内存。这样可以减少访问硬盘的次数,提高传输效率。
BufferedInputStream:当向缓冲流写入数据时候,数据先写到缓冲区,待缓冲区写满后,系统一次性将数据发送给输出设备。
BufferedOutputStream :当从向缓冲流读取数据时候,系统先从缓冲区读出数据,待缓冲区为空时,系统再从输入设备读取数据到缓冲区。
(1) 将文件读到内存(FileInputStream 与 BufferedInputStream 转换)
FileInputSteam is = new FileInputStream(new File(“test.txt”));
BufferedInputStream bufferIs = new BufferedInputStream(is)
(2) 将内存写到文件
FileOutputStream os = new FileOutputStream(new File(“test.txt”));
BufferedOutputStream bufferos = new BufferedOutputStream(os);
(3) 键盘输入流到内存
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader reader = new BufferedReader(isr)
七. 字符流Writer/Reader
在Java中,一个字符等于两个字节,Java提供了Reader和Writer两个专门操作字符流的类
(1)Writer
主要方法:
public abstract void throws IOException | 关闭输出流 |
public void writer(String str) throws IOException | 将字符串str中的字符写入输出流 |
public void writer(char[] cbuf) throws IOException | 将字符数组cbuf[]写入输出流 |
public abstract void flush() throws IOException | 刷空输出流,并输出所有被缓存的字节。 |
1: public void WriterDemo(){
2: File f = new File("D:" + File.separator + "test.txt");
3: Writer out;
4: try {
5: out = new FileWriter(f);
6: String str = " hello world";
7: out.write(str);
8: out.close();
9: } catch (IOException e) {
10: // TODO Auto-generated catch block
11: e.printStackTrace();
12: }
13: }
(2) Reader
主要方法:
public abstract void close() throws IOException | 关闭输入流 |
public int read() throws IOException | 读取一个字符,返回值为读取的字符 |
public int read(char[] cbuf) throws IOException | 读取一系列字符到数组cbuf[]中,返回值为实际读取的字符的数量 |
1: public void ReaderDemo(){
2: File file = new File("D:" + File.separator + "test.txt");
3: try {
4: Reader reader = new FileReader(file);
5: int len = 0;
6: char[] c = new char[1024];
7: int temp = 0;
8: while((temp = reader.read()) != -1){
9: c[len] = (char)temp;
10: len++;
11: }
12: reader.close();
13: } catch (FileNotFoundException e) {
14: // TODO Auto-generated catch block
15: e.printStackTrace();
16: } catch (IOException e) {
17: // TODO Auto-generated catch block
18: e.printStackTrace();
19: }
20:
21: }