天天看点

理解java的I/O流:

理解java的I/O流:

Java的IO流是实现输入输出的基础,他可以方便的实现数据的输入输出操作,在Java中把不同的输入/输出园(键盘,文件,网络连接等)抽象描述为流(stream),通过流的方式允许Java程序使用相同的方式来访问不同的输入输出源。

Java把所有传统的流类型(类或抽象类)都放在java.io中包中,用以实现输入输出功能。

因为Java提供了这种IO流的抽象,所以开发者可以使用一致的IO代码去读写不同的IO流节点。

(1)流的分类:

1.输入流和输出流:

按照流的流向来分,可以分为输入流和输出流。

输入流:只能从中读取数据,而不能向其写入数据

输出流:只能向其写入数据,而不能从中读取数据。

Java的输入流主要由InputStream和Reader作为基类,而输出流主要由OutputStream和Writer作为基类,他们都是一些抽象基类,无法直接创建实例。

2.字节流和字符流:字节流和字符流的用法几乎完全一样,区别在于字节流和字符流所操作的数据单元不同,字节流操作的是8位的字节,而字符流操作的是16位的字符。

字节流主要由InputStream和OutputStream作为基类,而字符流主要由Reader和Writer作为基类。

3.节点流和处理流:

按照流的角色来分,可以分为节点流和处理流:

可以和一个特定的IO设备读写数据的流,称为节点流,节点流也被称为低级流(Low Level Stream)

处理流则用于对一个已存在的流进行连接或封装,通过封装后的流来实现数据读写的功能。处理流也被称为高级流。

当使用处理流进行输入输出时,程序并不会连接到实际的数据库,没有和实际的输入输出节点连接。使用处理流的一个明显好处是,只要使用相同的处理流,程序就可以采用完全相同的输入输出代码来翻不过问不同的数据源,随着处理流所包装节点流的变化,程序实际所有所访问的数据源也相应的发生变化。

实际上,Java使用处理流来包装节点流是一种典型的装饰器设计模式,通过使用处理流来包装不同的节点流,既可以消除不同节点流的实现差异,也可以提供更方便的方法完成输入输出功能。因此处理流也被称为包装流。

——————————————————————————————————————————

字节流和字符流:

InputStream和Reader:

InputStream和Reader是所有输入流的抽象基类,本身并不能创建实例来执行输入,但他们将成为所有输入流的模板,所以他们的方法是所有输入流都可以使用的方法:

在InputStream里包含如下三个方法:

int read() 从输入流中读取单个字节,返回所读取的字节数据(字节数据可直接转换为int类型)

int read(byte[] b) 从输入流中最多读取b.length个字节的数据,并将其存储在数组b中,返回实际读取的字节数。

int read(byte [ ] b,int off, int len): 从输出流中读取len个字节的数据,并将其存储在数据b中,并不是从数组起点开始,而是从off位置开始,返回实际读取的字节数。

在Reader里包含如下三个方法:

int read() 从输入流中读取单个字符,返回所读取的字节数据,字符数据可直接转换为int类型)

int read(char[] cbuf) 从输入流中最多读取cbuf.length个字符的数据,并将其存储在数组cbuf中,返回实际读取的字符数。

int read(char [ ] cbuf,int off, int len): 从输出流中读取len个字符的数据,并将其存储在数据cbuf中,并不是从数组起点开始,而是从off位置开始,返回实际读取的cbuf

数。

(2)InputStream和Reader都是抽象类,本身不能创建实例,但他们分别有一个用于读取文件的输入流:FileInputStrean和FileReader,他们都是节点流,会直接和指定文件关联。

//FileInputStream来读取自身

OutputStream和Writer:提供的方法

void write(int c) 将指定的字节字符流输出到输出流中,c可以代表字节和字符

void write(byte[] /char[] buf) 把字节字符数组中的数据输出到指定输出流中

void write(byte[] /char[] buf,int off,int len) 将字节数组字符数组从off位置开始,长度为len的字节字符流输出到输出流中

Writer还有如下两个方法:

void write(String str) 将str字符串里包含的字符输出到指定输出流中

void write(String str,int off ,int len)

//使用FileInputStream来执行输入,并使用FileOutputStream来执行输出,用于实现复制FileOutputStreamTest.java

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamTest{
     public static void main(String[] args) throws IOException {
           //创建数字输入流
           FileInputStream  fis=new FileInputStream("FileOutputStreamTest.java");
           //创建字节输出流
           FileOutputStream  fos=new  FileOutputStream("newFile.txt");
           byte []  bbuf=new  byte[];
           int hasRead =;
           //循环从输入流中取出数据
           while((hasRead=fis.read(bbuf))>){
                //每读一次,即写入文件输出流,读了多少,就写多少
                fos.write(bbuf,,hasRead);
           }
     }
}

           

处理流的用法:

(1)使用处理流的典型思路是,使用处理流来包装节点流,程序通过处理流来执行输入输出功能,让节点流与底层的IO设备文件交互。

(2)实际识别处理流非常简单,只要流的构造器参数不是一个物理节点,而是已经存在的流,那么这种流一定是处理流,而所有的节点流都是直接以物理IO作为构造器参数的。

//使用PrintStream处理流来包装OutputStream。
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
public class PrintStreamTest{
     public static void main(String[] args) throws FileNotFoundException {
           FileOutputStream  fos=new FileOutputStream("test.txt");
           PrintStream  ps=new  PrintStream(fos);
           //使用PrintStream执行输出
           ps.println("普通字符串");
           //直接使用PrintStream输出对象
           ps.println(new  PrintStreamTest());
     }
}
           

转换流:

输入输出流体系中还提供了两个转换流,用于实现将字节流转换成字符流,其中InputStreamReader将字节输入流转换成字符输入流,OutputStreamWriter将字节输出流转换为字符输出流。

//以获取键盘输入为例来介绍转换流的做法

Java使用System.in代表标准输入,即键盘输入,但这个标准输入流是InputStream类的实例,使用不方便,而且键盘输入内容都是文本内容,所以可以使用InputStreamReader将其转换为字符输入流,普通的Reader读取内容时读取输入内容来说也不方便,可以将普通的Reader再次包装成BufferedReader,利用BufferedReader的readLine()方法可以一次读取一行内容:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public  class  keyinTest{
     public static void main(String[] args) throws IOException {
           //将System.in对象转换为Reader对象
           InputStreamReader  reader=new  InputStreamReader(System.in);
           //将普通的Reader包装为BufferReader
           BufferedReader  br=new BufferedReader(reader);
           String  line=null;
           //采用循环方式来逐行进行读取
           while((line  =br.readLine())!=null){
                //如果程序读取的字符串是exit,则退出
                if(line.equals("exit"));
                {
                     System.exit();
                }
                //打印读取的内容
                System.out.println("输入内容为:"+line);
           }
     }
}