zoukankan      html  css  js  c++  java
  • IO流

    1. 文件系统和File类

         File类在Java.io包中   对于一个File对象来说它能够代表硬盘上的一个文件或者文件夹

          原理:当我们创建一个File对象时,在内存中分配了一块内存区域,创建一个File对象并不会在系统中真的创建一个文件或者文件夹,而只在JVM内存中

                      创建了一个对象,通过这个对象能够跟磁盘打交道,从而操作底层的文件。因此File对象所代表的的文件或者文件夹可能不存在。

     

          1、 File有四个构造方法其中三个比较常用

                   (1)  File(String pathname) :     表示一个路径名 用来创建一个文件或者文件夹

                        (2)     File(String parent, String child) :   用来构建parent/child 的文件或者文件夹

                      (3)   File(File parent, String child) :     同样用 parent 表示父目录,只不过这个 parent 是用 File 类型来表示。

            2、   File 类的一些基本操作

                   (1)    createNewFile() : 这个方法可以用来创建一个新文件。需要注意的是,如果这个文件在系统中已经存在,createNewFile 方法不会覆盖原有文件。

                   (2)    mkdir() / mkdirs() : 这两个方法都可以用来创建文件夹。所不同的是,mkdir 只能创建一层文件夹,而 mkdirs 能够创建多层文件夹。

                      (3)      delete() : 这个方法能够删除 File 所代表的文件或者文件夹。
     
                      (4)      deleteOnExit() : 这个方法也能用来删除文件或者文件夹。所不同的是,delete()方法被调用时,这个文件或者文件夹会被立刻删除,
                                     而 deleteOnExit()方法被调用  后,文件或者文件夹并不会立刻被删除,而会等到程序退出以后再删除。
     
                       (5)      getPath() : 返回路径
                       (6)      getName() : 返回文件名
                       (7)     getParent() : 返回所在的文件夹

    2.   IO 分类  问题引入

                1.     所谓的流,指的是:用来传输数据的对象

                2.     流可以按照方向分类,分为输入流和输出流

                3.     流可以按照数据单位分类,分为字节流和字符流

                 4.      流可以按照功能分类,分为节点流和过滤流

                5.     任何数据都可以按照字节的方式进行传输。

                 问题:汉字占用的有时并不是一个字节如果使用字节传输 ,传输过程中出现传输错误只保留半个汉字出现这种错误

                 解决:字符流

             1. 字符流    

                    字符流传输数据的单位是字符。这种流专门用于处理文本,能够方便的处理字符编码的问题。

              2. 节点流

                   真正能够完成传输功能的流,而相对的,过滤流并不能完成真正的数据传输,过滤流是用来为其他流增强功能。

     3. 设计模式         

                在节点流和过滤流的设计上,I/O 框架中使用了一种设计模式,这种设计模式被称为“装饰模式”。

                                                          

    在 I/O 框架中对应的概念就是节点流。而零件的那些子类,是为枪械增强功能的,本身并不能完成射击的功能,因此对应于 I/O 的概念,就是过滤流。

                                       

    4. 字节流

              (1).   特点:数据单位是字节,能够处理任何一种文件

                (2) .      InputStream 和OutputStream  所有字节流的父类         

                                   

               1.  FileInputStream 

                   (1)FileInputStream(Sting filename):通过文件路径获得文件输入流

                   (2)FileFileInputStream(File file): 通过文件对象获得文件输入流

                   (3)close()关闭流资源

                   (4)int read()   每次从文件中读取一个字节

                   (5)int read(byte[] b)  每次调用这个方法会把读取到的数据放入到bs数组中,

                             这个方法的返回值返回的是读到的字节数  

                   (6) int read(byte[] b ,int off ,int  len)  让数组在数组中从off开始 读取长度为len

                             每次读取一个字节       int read()

                          

                               将数据读入到数组中然后写出来            int read(byte[] b)   

                            

                        2. FileOutPutStream

                               1. FileOutputStream(String path)  根据路径创建文件输出流

                               2. FileOutPutStream(File file)  : 根据文件对象创建文件输出流

                               3. close 关闭流

                               4.   void write(int  v)  每次调用写入一个字节

                                5.   void  write(byte[]  bs): 写入 一个byte数组 

                                6. void write(byte[] ,int off,int len)  从数组小标off开始  写入长度为len

                                 

                                 7.  FileOutPutStream(String path ,boolean append)

                                 8.  FileOutPutStream (File file ,boolean append)

                            当这个参数为false的时候,这两个构造方法与只有一个参数的构造方法用起来相同:如果文件不存在,
                            则FileOutputStream会创建新文件;如果文件已存在,则覆盖原件。

                            如果这个参数为true,则:当如果文件不存在,依然会创建新文件;而如果文件已存在,则会用追加的方式写文件。

                                                   

     5. 过滤流

                         1. DataInputStream和DataOutputStream。  增强了读写八种基本类型和字符串的功能。
     
                               问题:由于 FileOutputStream没有一个接受double类型作为参数的write方法,因此必须要想别的方法

                               思路:  一个double变量占据8个字节,因此写一个double类型的时候,比较直观的方法应当是把这个

                                             double类型的数拆分成8个字节, 然后把这8个字节写入到流中去  当 然,把double类型进行

                                               拆分是一件比较麻烦的事情

                              内容:

                                     1. 我们可以看一下DataOutputStream的方法:除了有OutputStream中有的几个write方法之外,

                                         还有writeBoolean,writeByte,writeShort...等一系列方法,这些方法接受  某一种基本类型,

                                          把基本类型写入到流中。

                                     2.  有一个writeInt(intn)方法,这个方法接受一个int类型的参数。这个方法和write(intv)方法不同。
                                         writeInt方法是DataOutputStream特有的方法,这个方法一次写入参 数n的四个字节。
                                          而write方法则一次写入参数v的最后一个字节。
                                     3.   与之对应的,DataInputStream的方法中,除了有几个read方法之外,还有readBoolean,
                                           readByte,readInt等一系列方法,这些方法能够读入若干个字节,然后 拼成所需要的数据。
                                            例如readDouble方法,就会一次读入8个字节,然后把这8个字节拼接成一个double类型。

                

                                     4. 最后要提示的是,DataXXXStream中有readUTF和writeUTF这两个方法用来读写字符串,但是一般来说,
                                         我们读写字符串的时候几乎不使用Data流。Data流主要 是用在8种基本类型的读写上。
     
                               使用:
                                       
                                       1、创建节点流。这个步骤是使用过滤流的先决条件,由于过滤流无法直接实现数据传输功能,
                                             因此必须先有一个节点流,才能够进行数据传输。
                          
                                       2、封装过滤流。所谓的“封装”,指的是创建过滤流的时候,必须以其他的流作为构造方法的参数。
                                             需要注意的是,可以为一个节点流封装多个过滤流。
     
                                       3、读/写数据。
     
                                       4、关闭外层流。这指的是,关闭流的时候,只需要关闭最外层的过滤流即可,内层流会随着外层流的关闭而一起被关闭。
     
                                                              
    6  . BufferedInputStream和BufferedOutputStream。这两个流增强了缓冲区的功能。
                            
                                   问题:
                                          什么叫缓冲区呢?在之前的代码中,我们每调用一次read或者write方法,都会触发一 次I/O操作。
                                          而由于I/O操作要跨越JVM的边界,因此进行I/O操作的时候,
                                          事实上效率会 非常低,这非常不利于程序的高效。为了让程序的效率得到提升,我们引入了缓冲机制。
     
                                   原理:我们会在内存中开辟一块空间,当调用read或者write方法时,并不真正进行I/O操作,
                                              而是对内存中的这块空间进行操作。我们以write操作为例,使用了缓冲机 制之后,
                                              我们调用write方法时,并不真正把数据写入到文件中,而是先把数据放到缓冲区里。
                                              等到缓冲区满了之后,再一次性把数据写入文件中。
                                      
                                                    
                                            需要注意的是,如果把bout.close()方法去掉,此时在看test.txt文件,会发现文件的内容为空。这是因
                                            为,我们在调用write方法的时候,其实并没有真正把数据写  入到文件中,而只是把数据写入到缓冲区
                                            中。 那什么时候缓冲区中的数据会真正写入到文件中呢?
                                            第一种情况:是缓冲区已满,
                                            第二种情况:是调用close方法。
                                            第三种情况:把缓冲区内的东西真正写入流中,应当调用一个方法:flush()。
                                                                  这个方法用来清空缓冲区,往往用在输出流上面。当一个带缓冲的输 出流调用flush()之后,
                                                                 就能保证之前在缓冲区中的内容真正进行了I/O操作,而不是仅仅停留在缓冲区。
     
     
      7. PrintStream
                      
                   PrintStream是一个比较特殊的过滤流,我们简单介绍一下,读者作为一般性的了解即可。
     
                   PrintStream作为过滤流,增强的功能有以下几个:
                   1、缓冲区的功能
                   2、写八种基本类型和字符串
                   3、写对象需要注意的是,这个流写基本类型和写对象的时候,是按照字符串的方式写的。
                        也就是说,这个流写八种基本类型的时候,会把基本类型转换成字符串以后再写,而写对象的时候,
                        会写入对象的toString()方法返回值。
     
                   重点:    System.out对象,这就是一个PrintStream类型的对象。
     
                  要注意的是,PrintWriter写基本类型的方式,是把基本类型转换为字符串再写入流中,
                                         与Data流不同。举例来说,对于3.14这个double类型的数,Data流会把这个数拆分成8个字 节写入文件,
                                         而PrintWriter会把这个数字转化为字符串“3.14”,写入文件中此外,PrintWriter写对象的时候,
                                         写入的是对象的toString()方法返回值,与对象序列化 有本质区别。
                                     
                                          PrintWriter除了可以作为过滤流之外,还可以作为节点流。PrintWriter类的构造方法中,
                                          可以直接接受一个文件名或File对象作为参数,直接获得一个输出到文件的 rintWriter。
                                          当然,编码方式采用的是系统默认的编码方式。
     
                                      最后,PrintWriter的构造方法可以接受一个InputStream,也就是说,可以使用PrintWriter进行桥转换。
                                      只不过使用PrintWriter进行桥转换的时候,无法指定编码方式,采 用的是系统默认的编码方式。
     
                                               
    8. 对象的序列化
                      
                    ObjectInputStream和ObjectOutputStream。这两个也是过滤流,增强的功能如下:
                              1、增强了缓冲区功能
                              2、增强了读写八种基本类型和字符串的功能。读写基本类型和字符串的方式,与Data流完全一样。
                     
                              3、增强了读写对象的功能。这是这两个流最主要的作用。在ObjectInputStream类有一 个readObject方法,
                                     这个方法能够从流中读取一个对象;而ObjectOutputStream类 中有 一个writeObject方法,
                                     这个方法能够向流中写入一个对象。
     
                      
                              4. ObjectInputStream和ObjectOutputStream能够完成对对象的读写。这种把对象放到流上进行传输的过程,
                                   称之为“对象序列化”。一个对象如果能够放到流上进行传输,则我  们称这个对象是“可序列化”的。
     
                   Serializable接口和transient关键字
                         
                             1. 并不是所有对象都是“可序列化”的。
                              2. 如果要让一个类成为可序列化的,只要让这个类实现一个接口:java.io.Serializable接口即可。
                             
                             需要注意的是,由于readObject方法返回值为Object类型,因此需要对返回值进行强转。
                              
                           transient。这个关键字是一个修饰符,这个修饰符可以用来修饰属性,用transient修饰的属性表示:
                                            这个属性不参与序列化。
     
                                            

                              注意:

                                1.    在使用对象序列化的时候,注意这样两个问题: 1、不要使用追加的方式写对象。也就是说,
                                       如果我们创建一个文件输出流采用FileOutputStream(file,true)的方式创建 节 点流,
                                       然后再在外面封装ObjectOutputStream,这样将无法完成我们设想的结果。如果对一个文件多次写入的话,
                                       读取对象的时候只能读取第一次写入的对象,而  后面用追加的方式写入的对象将无法被取。
                                       这是对象序列化底层机制所决定的。
     
                                2、如果一个对象的属性又是一个对象,则要求这个属性对象也实现了Serializable接口,
                                      如果一个对象的属性是一个集合,则要求集合中所有对象都实现Serializable接口。
                                      除非这个对象的属性被标记为transient,不参与序列化。
     
     9. 字符流
                                 问题:
                                         计算机中显示文字的时候,本质上是在屏幕上绘制一些图像用来显示文字。从这个意义上说,
                                         文字就是一种特殊的图片
     
     
                                         
             
    获得字符流与桥转换  
    InputStreamReader和OutputStreamWriter
       
                     
                                1. InputStreamReader这个类本身是Reader类的子类,因此这个类的对象是一个字符流。
     
                                        
     
                                 2. 这个流可以接受一个字节流作为参数,创建一个字符流。这个对象就起到了字节流向字符流转换的功能,
                                      我们往往称之为:桥转换。
     
                                 3. OutputStreamWriter类能够把一个输出字节流转换为一个输出字符流。 在桥转换的过程中,
                                     我们还可以指定编解码方式。如果不指定的话,则编码方式采用系统默认的编码方式。
     
                                 4. 如果需要指定编码方式,则应当使用桥转换。在无法直接获得字符流的情况下,可以先获得字节流,
                                     再通过桥转换获得字符流。
     
                               利用桥转换进行编程,需要以下五个步骤:
                                        1、创建节点流
                                        2、桥转换为字符流
                                        3、在字符流的基础上封装过滤流
                                        4、读/写数据
     
                                       
     
     
     
     
  • 相关阅读:
    读书笔记第四章
    读书笔记第三章
    读书笔记第二章
    读书笔记第一章
    第十章 读书笔记
    第九章 读书笔记
    第八章读书笔记
    第七章读书笔记
    第六章读书笔记
    第五章读书笔记
  • 原文地址:https://www.cnblogs.com/zhulina-917/p/11577832.html
Copyright © 2011-2022 走看看