Java的IO

概要:

       Java的核心库java.io提供了全面的IO接口。包括:文件读写、标准设备输出等。Java中IO是以流为基础进行输入输出的,所有数据被串行化写入输出流,或者从输入流读入。

       java的IO 是输入输出的基础,可以方便的实现数据输入和输出操作。那么,在java 中把不同的输入和输出源(键盘,连接,网络连接等)抽象表述为“流”(Stream)。通过流的的形式允许java程序使用相同的方式来访问不同的输入输出源。Stream是从起源(source)到接收(sink)的有序数据。

注:java把所有的传统的流类型都放到在java io包下,用于实现输入和输出功能。

流的分类:

        一、按照流的流向分,可以分为输入流和输出流;

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

               2、输出流:只能向其写入数据,但不能向其读取数据。

               此处的输入、输出涉及一个方向的问题,对于如图15.1所示的数据流向,数据从内存到硬盘,称之为输出流-----也就是说;这里的输入、输出都是从程序运行所在的内存角度来划分的。

               注:如果从硬盘的角度来考虑,图15.1所示的数据流应该是输入流才对;但划分输入/输出流时是从程序运行所在的内存的角度来考虑的,因此如图15.1所在的流时输出流。而不是输入流。

               对于15.2所示的数据流向,数据从Server通过网络流向Linent,此情况下,Server端的内存负责将数据输出到网络里,程序为:Server 端的程序使用输出流,将数据输出到网络,Clinent 端的内存负责从网络里(使用的为输入流)读取数据。

è¿æ¯å¾çæè¿°

                注:java的输入流主要是以InputStream(字节输入流)和Reader(字符输入流)作为基础类,而输出流则是以OutputStream(字节输出流)和Writer( 字符输出流 )作为基础类,他们是一些抽象基类,无法直接创建实例。

        二、按照操作单元可以划分为字节流和字符流;

               字节流和字符流的用法机会完全一样,区别在于两者操作的数据单元不同,字节流操作的是数据单元为8位的字节, 字          符流操作的则是数据单元为16bit的字符。

               注:这里的字节流主要是由InputStream(输入流)和OutputStreanm(输出流)作为基础类,而字符流则Reader(输入          流)和Writer(输出流)作为基础类。

        三、按照流的角色划分为节点流和处理流。

                      可以从/向一个特定的Io设备(如:磁盘、网络)读/写数据的流,称为节点流或者低级流。如图15-3;

               如图所示:当节点流进行输入或者输出时,程序直接连接的数据源,和实际的输入和输出节点及进行连接。

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

               如图15-4

è¿éåå¾çæè¿°

   以上15-4可以看出,当使用处理流进行输入/输出时,程序并不会连接到实际的数据源,没有和实际的输入/输出节点进行连接。使用处理流的一个明显的好处是,只要使用相同的处理流,程序就可以使用相同的输入/输出的demo访问不同的数据源,随着处理流所包装的节点流的变化,程序实际访问的数据源也相应的发生变化。

流的与原理解析和分类表:

       IO基于InputStreanm 及Reader   OutputStream及Writer 派生除了40多个类。

       对于InputStream 和Reader 而言,他们把输入输出抽象成一个水管,这个水管的“水滴”依次排列,如图:15-5所示

       由图看出,字节流和字符流处理的方式较为相似,只是他们处理输入/输出单位不同而已。输入流采用隐式的记录指针来表示当前正准备从那个“水滴”开始读取,每当程序从InputStream 或者 Reader 里面读取到一个或者多个“水滴”后,记录指针自动向后移动,那么InputStream 和Reader 里面必然需要提供控制该指针移动的方法。

è¿éåå¾çæè¿°

       对于OutputStream 和Wirter而言,他们同样把输出设备抽象成一个水管,只是这个水管中没有水滴。

       正如15-6所示:当执行输出时,程序相当于依次把“水滴”放入到输出流的水管中,输出流同样采用隐式指针来表示当前“水滴”即将放入的位置,每当程序向OutputStream 和Writer 输出一个或者多个水滴时,记录指针自动向后移动。

 图15.5和图15.6显示了java Io的基本概念模型,除此之外,Java的处理流模型则体现了Java输入和输出流设计的灵活性。处理流的功能主要体现在以下两个方面。

  • 性能的提高:主要以增加缓冲的方式来提供输入和输出的效率。
  • 操作的便捷:处理流可能提供了一系列便捷的方法来一次输入和输出大批量的内容,而不是输入/输出一个或者多个“水滴”。

    处理流可以“嫁接”在任何已存在的流的基础之上,这就允许Java应用程序采用相同的代码,透明的方式来访问不同的输入和输出设备的数据流。图15.7显示了处理流的模型。

java输入/输出流体系中常用的流的分类表

分类字节输入流字节输出流字符输入流字符输出流
抽象基类InputStreamOutputStreamReaderWriter
访问文件FileInputStreamFileOutputStreamFileReaderFileWriter
访问数组ByteArrayInputStreamByteArrayOutputStreamCharArrayReaderCharArrayWriter
访问管道PipedInputStreamPipedOutputStreamPipedReaderPipedWriter
访问字符串  StringReaderStringWriter
缓冲流BufferedInputStreamBufferedOutputStreamBufferedReaderBufferedWriter
转换流  InputStreamReaderOutputStreamWriter
对象流ObjectInputStreamObjectOutputStream  
抽象基类FilterInputStreamFilterOutputStreamFilterReaderFilterWriter
打印流 PrintStream PrintWriter
推回输入流PushbackInputStream PushbackReader 
特殊流DataInputStreamDataOutputStream  

注:表中粗体字所标出的类代表节点流,必须直接与指定的物理节点关联:斜体字标出的类代表抽象基类,无法直接创建实例。

 IO 的用法

         IO 的用法围绕着四个基类展开,即(InputStream和 Reader  OutputStream  和Wirter )字节输入流、字符输入流、字节输出流、字符输出流。

         InputStream 和Reader 本身不能创建实例进行输入,所有创建输入都可使用它们内部方法来创建输入。

         InputStream里面包含的三个方法:

         1、int read(); 从输入流中读取单个字节

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

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

         Reader 中包含的三个方法:

         1、int  read();从输入流中读取单个字符。

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

         3、int  read(char[]   b,int  off,int  len); 从输入流中最多读取len个字符的数据,并将其存储在数组b中,放入数组b中时,并不是从数组起点开始,而是从off位置开始,返回实际读取的字符数。 

         InputStream 和Reader所提供的方法,就不难发现这两个基类的功能基本是一样的。InputStream和Reader都是将输入数据抽象成如图15.5所示的水管,所以程序即可以通过read()方法每次读取一个”水滴“,也可以通过read(char[] chuf)或者read(byte[] b)方法来读取多个“水滴”。当使用数组作为read()方法中的参数, 我们可以理解为使用一个“竹筒”到如图15.5所示的水管中取水,如图15.8所示read(char[] cbuf)方法的参数可以理解成一个”竹筒“,程序每次调用输入流read(char[] cbuf)或read(byte[] b)方法,就相当于用“竹筒”从输入流中取出一筒“水滴”,程序得到“竹筒”里面的”水滴“后,转换成相应的数据即可;程序多次重复这个“取水”过程,直到最后。程序如何判断取水取到了最后呢?直到read(char[] chuf)或者read(byte[] b)方法返回-1,即表明到了输入流的结束点。

è¿éåå¾çæè¿°

InputStream和Reader提供的一些移动指针的方法:

  • void mark(int readAheadLimit); 在记录指针当前位置记录一个标记(mark)。
  • boolean markSupported(); 判断此输入流是否支持mark()操作,即是否支持记录标记。
  • void reset(); 将此流的记录指针重新定位到上一次记录标记(mark)的位置。
  • long skip(long n); 记录指针向前移动n个字节/字符。

OutputStream和Writer: 
OutputStream和Writer的用法也非常相似,它们采用如图15.6所示的模型来执行输入,两个流都提供了如下三个方法:

  • void write(int c); 将指定的字节/字符输出到输出流中,其中c即可以代表字节,也可以代表字符。
  • void write(byte[]/char[] buf); 将字节数组/字符数组中的数据输出到指定输出流中。
  • void write(byte[]/char[] buf, int off,int len ); 将字节数组/字符数组中从off位置开始,长度为len的字节/字符输出到输出流中。

因为字符流直接以字符作为操作单位,所以Writer可以用字符串来代替字符数组,即以String对象作为参数。Writer里面还包含如下两个方法。

  • void write(String str); 将str字符串里包含的字符输出到指定输出流中。
  • void write (String str, int off, int len); 将str字符串里面从off位置开始,长度为len的字符输出到指定输出流中。

Io体系的基类文件流的使用(FileInputStream/FileReader ,FileOutputStream/FileWriter)

      前面说过InputStream和Reader都是抽象类,本身不能创建实例,但它们分别有一个用于读取文件的输入流:FileInputStream和FileReader,它们都是节点流——会直接和指定文件关联。下面程序示范使用FileInputStream和FileReader。 
 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值