java IO详解

一、Java I/O主要包括如下几个层次,包含三个部分:
   1.流式部分――IO的主体部分;
   2.非流式部分――主要包含一些辅助流式部分的类,如:File类、RandomAccessFile类和FileDescriptor等类;
   3.其他类--文件读取部分的与安全相关的类,如:SerializablePermission类,以及与本地操作系统相关的文件系统的类,如:FileSystem类和Win32FileSystem类和WinNTFileSystem类

二、 Java.io包下主要的类如下:
     1. File(文件特征与管理):用于文件或者目录的描述信息,例如生成新目录,修改文件名,删除文件,判断文件所在路径等。
     2. InputStream(二进制格式操作):抽象类,基于字节的输入操作,是所有输入流的父类。定义了所有输入流都具有的共同特征。
     3. OutputStream(二进制格式操作):抽象类。基于字节的输出操作。是所有输出流的父类。定义了所有输出流都具有的共同特征。
     4.Reader(文件格式操作):抽象类,基于字符的输入操作。
     5. Writer(文件格式操作):抽象类,基于字符的输出操作。
     6 . RandomAccessFile(随机文件操作):一个独立的类,直接继承至Object.它的功能丰富, 可以从文件的任意位置进行存取(输入输出)操作

三、Java IO设计所采用的模式  
   Java的IO模型设计非常优秀,它使用 Decorator(装饰者)模式,按功能划分Stream,您可以动态装配这些Stream,以便获得您需要的功能。
  例如,您需要一个具有缓冲的文件输入流,则应当组合使用FileInputStream和BufferedInputStream
还有 适配器模式,如inputStreamReader与OutputStreamWriter

四、IO流的分类
(1)根据 处理数据类型的不同分为:字符流和字节流
(2)根据 数据流向不同分为:输入流和输出流
(3)按 数据来源(去向)分类:
         1、File(文件): FileInputStream, FileOutputStream, FileReader, FileWriter 
         2、byte[]:ByteArrayInputStream, ByteArrayOutputStream 
         3、Char[]: CharArrayReader,CharArrayWriter 
         4、String:StringBufferInputStream, Stri6ngReader, StringWriter 
         5、网络数据流:InputStream,OutputStream, Reader, Writer
(4)按流的传输类型: 节点流和包装流

五、java IO流对象(重点)
1.输入字节流InputStream
1.    InputStream是所有的输入字节流的父类,它是一个抽象类。
2.    ByteArrayInputStream、StringBufferInputStream、FileInputStream是三种基本的介质流,它们分别从Byte数组、StringBuffer和本地文件中读取数据。
3.    PipedInputStream是从与其它线程共用的管道中读取数据.
4.    ObjectInputStream和所有FilterInputStream的子类都是装饰流(装饰器模式的主角)。
InputStream中的三个基本的读方法
      abstract int read() :读取一个字节数据,并返回读到的数据,如果返回-1,表示读到了输入流的末尾。
      int read(byte[] b) :将数据读入一个字节数组,同时返回实际读取的字节数。如果返回-1,表示读到了输入流的末尾。
      int read(byte[] b, int off, int len) :将数据读入一个字节数组,同时返回实际读取的字节数。如果返回-1,表示读到了输入流的末尾。off指定在数组b中存放数据的起始偏移位置;len指定读取的最大字节数。
流结束的判断:方法read()的返回值为-1时;readLine()的返回值为null时。
2.输出字节流OutputStream
1.    OutputStream是所有的输出字节流的父类,它是一个抽象类。
2.    ByteArrayOutputStream、FileOutputStream是两种基本的介质流,它们分别向Byte数组、和本地文件中写入数据。PipedOutputStream是向与其它线程共用的管道中写入数据。
3.    ObjectOutputStream和所有FilterOutputStream的子类都是装饰流。
outputStream中的三个基本的写方法
   abstract void write(int?b):往输出流中写入一个字节。
     void write(byte[]?b) :往输出流中写入数组b中的所有字节。
     void write(byte[]?b, int?off, int?len) :往输出流中写入数组b中从偏移量off开始的len个字节的数据。
其它方法
   void flush() :刷新输出流,强制缓冲区中的输出字节被写出。
     void close() :关闭输出流,释放和这个流相关的系统资源。
3.字符输入流Reader
1.    Reader是所有的输入字符流的父类,它是一个抽象类。
2.    CharReader、StringReader是两种基本的介质流,它们分别将Char数组、String中读取数据。PipedReader是从与其它线程共用的管道中读取数据。
3.    BufferedReader很明显就是一个装饰器,它和其子类负责装饰其它Reader对象。
4.    FilterReader是所有自定义具体装饰流的父类,其子类PushbackReader对Reader对象进行装饰,会增加一个行号。
5.    InputStreamReader是一个连接字节流和字符流的桥梁,它将字节流转变为字符流。FileReader可以说是一个达到此功能、常用的工具类,在其源代码中明显使用了将FileInputStream转变为Reader的方法。
reader主要方法:
     (1) public int read() throws IOException; //读取一个字符,返回值为读取的字符 
     (2) public int read(char cbuf[]) throws IOException; /*读取一系列字符到数组cbuf[]中,返回值为实际读取的字符的数量*/ 
     (3) public abstract int read(char cbuf[],int off,int len) throws IOException; 
/*读取len个字符,从数组cbuf[]的下标off处开始存放,返回值为实际读取的字符数量,该方法必须由子类实现*/ 
4.字符输出流Writer
1.    Writer是所有的输出字符流的父类,它是一个抽象类。
2.    CharArrayWriter、StringWriter是两种基本的介质流,它们分别向Char数组、String中写入数据。PipedWriter是向与其它线程共用的管道中写入数据,
3.    BufferedWriter是一个装饰器为Writer提供缓冲功能。
4.    PrintWriter和PrintStream极其类似,功能和使用也非常相似。
(1)  public void write(int c) throws IOException; //将整型值c的低16位写入输出流 
(2)  public void write(char cbuf[]) throws IOException; //将字符数组cbuf[]写入输出流 
(3)  public abstract void write(char cbuf[],int off,int len) throws IOException; //将字符数组cbuf[]中的从索引为off的位置处开始的len个字符写入输出流 
(4)  public void write(String str) throws IOException; //将字符串str中的字符写入输出流 
(5)  public void write(String str,int off,int len) throws IOException; //将字符串str 中从索引off开始处的len个字符写入输出流 
5.转换流
OutputStreamWriter(OutStreamout):将字节流以字符流输出。
InputStreamReader(InputStream in):将字节流以字符流输入。
6.字节流和字符流的区别(重点)
(1)输出输入的形式不同:字节流没有缓冲区,是直接输出的,而字符流是输出到缓冲区的。因此在输出时,字节流不调用colse()方法时,信息已经输出了,而字符流只有在调用close()方法关闭缓冲区时,信息才输出。要想字符流在未关闭时输出信息,则需要手动调用flush()方法。
(2)读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。
(3) 处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据
结论:只要是处理纯文本数据,就优先考虑使用字符流。除此之外都使用字节流。
六、非流式对象
1.File类
简介
File类是对文件系统中文件以及文件夹进行封装的对象,可以通过对象的思想来操作文件和文件夹。File类是Object的直接子类,同时它继承了Comparable接口可以进行数组的排序,继承了Serializable接口,可以被序列化。
一个对应于某磁盘文件或目录的File对象一经创建, 就可以通过调用它的方法来获得文件或目录的属性。  
 常用方法:
       1)public boolean exists( ) 判断文件或目录是否存在
       2)public boolean isFile( ) 判断是文件还是目录 
       3)public boolean isDirectory( ) 判断是文件还是目录
       4)public String getName( ) 返回文件名或目录名
       5)public String getPath( ) 返回文件或目录的路径。
       6)public long length( ) 获取文件的长度 
       7)public String[ ] list ( ) 将目录中所有文件名保存在字符串数组中返回。 
       File类中还定义了一些对文件或目录进行管理、操作的方法,常用的方法有:
       1) public boolean renameTo( File newFile );    重命名文件
       2) public void delete( );   删除文件
       3)  public boolean mkdir( ); 创建目录
2.RandomAccessFile类
简介
此类的实例支持对随机访问文件的读取和写入。随机访问文件的行为类似存储在文件系统中的一个大型 byte 数组。存在指向该隐含数组的光标或索引,称为 文件指针;输入操作从文件指针开始读取字节,并随着对字节的读取而前移此文件指针。输出操作从文件指针开始写入字节,并随着对字节的写入而前移此文件指针。写入隐含数组的当前末尾之后的输出操作导致该数组扩展。 该文件指针可以通过 getFilePointer 方法读取,并通过 seek 方法设置
构造函数
RandomAccessFile(File file,String mode)
RandomAccessFile(String name,String mode)
mode可以取“r“只读;”rw“读写;”rws“,”rwd“读写,同时更新到底层设备
注意:该对象在实例化时,如果要操作的文件不存在,会自动创建;如果文件存在,写数据未指定位置,会从头开始写,即覆盖原有的内容。  可以用于多线程下载或多个线程同时写数据到文件,还可以实现断点续传。
七、System类对IO的支持
针对一些频繁的设备交互,Java语言系统预定了3个可以直接使用的流对象,分别是:
·        System.in(标准输入),通常代表键盘输入。
·        System.out(标准输出):通常写往显示器。
·        System.err(标准错误输出):通常写往显示器。
注意:
(1)System类不能创建对象,只能直接使用它的三个静态成员。
(2)每当main方法被执行时,就自动生成上述三个对象。
附加:IOException(常见异常类)
1.public class  EOFException :   非正常到达文件尾或输入流尾时,抛出这种类型的异常。
2.public class FileNotFoundException:   当文件找不到时,抛出的异常。
3.public class InterruptedIOException: 当I/O操作被中断时,抛出这种类型的异常。
八、字节流与字符流比较
字节流和字符流的主要区别是什么呢?
            一.字节流在操作时不会用到缓冲区(内存),是直接对文件本身进行操作的。而字符流在操作时使用了缓冲区,通过缓冲区(内存)再操作文件。
           二.在硬盘上的所有文件都是以字节形式存在的(图片,声音,视频),真正存储和传输数据时都是以字节为单位的, 而字符值在内存中才会形成,所以,字节流适用范围更为宽广。
如果是音频文件、图片、歌曲,就用字节流,
如果是关系到中文(文本)的,用字符流好点。
在实际开发中出现的汉字问题实际上都是在字符流和字节流之间转化不统一而造成的 


附:IO中同步、异步,阻塞与非阻塞的区别
Java BIO : 同步并阻塞 ,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。即使使用了bufferedReader等缓冲区仍然是阻塞式的,只是改善了读的过程。
Java NIO : 同步非阻塞 ,服务器实现模式为一个请求一个线程, 每个线程亲自处理 I/O(同步) ,即客户端发送的连接请求都会注册到多路复用器selector上,另外的线程轮询检查是否 I/O 准备完毕, 不必等待 I/O 完成(非阻塞) ,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。
Java AIO(NIO.2) : 异步非阻塞 ,服务器实现模式为一个有效请求启动一个线程, 客户端的 I/O 请求都是由操作系统先完成 了再通知服务器应用去启动线程进行处理, 每个线程不必亲自处理 I/O,而是委派操作系统来处理(异步) ,并且也 不需要等待 I/O 完成(非阻塞) ,如果完成了操作系统会另行通知的。

BIO方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前的唯一选择,但程序直观简单易理解。
NIO方式适用于连接数目多且连接比较短(轻操作)的架构 ,比如聊天服务器,并发局限于应用中,编程比较复杂,JDK1.4开始支持。
AIO方式适用于连接数目多且连接比较长(重操作)的架构 ,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK7开始支持。

同步与异步
同步与异步是对应的,它们是 线程之间的关系 ,两个线程之间要么是同步的,要么是异步的。
同步:一个线程通知另一个线程该做的任务,然后必须等待它完成并返回,才能继续自己的任务。或者线程亲自处理该任务。
异步:一个线程通知另一个线程该做的任务,然后不必等待,继续做自己的事,另一个线程完成任务后会通知该线程,然后对该任务继续处理。
(对于IO中的同步与异步:同步与异步考虑的是进程与内核的交互方式,同步指的是通道就绪后,进行IO操作并转移到内核buffer,等待系统内核将数据从内核buffer复制到用户进程buffer。而异步指的是这些事儿由系统内核做,用户进程继续做其他事儿,完成后通过回调函数告诉用户进程取数据.)
阻塞与非阻塞
阻塞与非阻塞是 对同一个线程来说 的,在某个时刻,线程要么处于阻塞,要么处于非阻塞
阻塞:线程调用方法后,等待方法处理完并返回结果,方法处理执行过程中,该线程一直处于等待状态。
非阻塞:线程调用方法后,不等待,直接执行后续的代码,方法处理的结果可先写入缓冲区,处理完毕再通知线程接受处理。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值