黑马程序员 — IO流

-------android培训java培训、期待与您交流! ----------


IO流


什么是流:

流就是程序和设备之间嫁接起来的一根用于数据传输的管道,这个管道上有很多按钮,不同的按钮可以实现不同的功能


节点流与处理流:

节点流:(也叫原始流)

节点流为可以从一个特定的数据源(节点)读写数据(如:文件,内存)

处理流:(也叫包裹流)

处理流是“连接”在已存在的流(节点流或处理流)之上,通过对数据的处理为程序提供更为强大的读写功能


流的分类和使用:


四大基本抽象流:


InputStream和OutputStream读写数据的单位是一个字节,Reader和Writer读写数据的单位的一个字符

InputStream OutputStream Reader Writer 这四个类都是抽象类

凡是以Stream结尾的都是字节流


InputStream 流中常用的方法:


public int read()  读取一个字节并以整数的形式返回,如果读取到输入流的末尾则返回-1

public int read(byte[] b)从输入流中读取一定数据的字节,并将其存储在缓冲区数组b中,以整数形式返回实际的字节数

public int read(byte[] b, int off, int len)    从输入流中最多读取len个字节的数据并存入bete中

public void close()   关闭此输入流并释放与该流关联的所有系统资源


OuputStream 流中的常用方法:


public void write(int b) 向输入流中写入一个字节数据,该字节数据为参数b的低8位

public void write(byte[] b)  将一个字节类型的数组中的数据写入输出流

public void wirte(byte[] b, int off, int len) 将一个字节类型的数组中的从指定位置(off)开始的len个字节定稿到输出流

public void close()  关闭流释放内存资源 

public void flush()  将输出流中缓冲的数据全部写出到目的地


Reader 流中的常用方法:


public int read() 读取一个字符并以整数的形式返回(0~255),如果返回-1已到输入流的末尾

public int read(char[] cbuf) 读取一系列字符并存储到一个数组buf,返回实际读取的字符数,台电读取前已到输入流的末尾返回-1


public int read(char[] cbuf, int offset, int length) 最多读取length个字符,并存储在一个数组buf,从length位置开始,返回实际读取的字符数,如果读取前已到输入流末尾返回-1


public void close() 关闭流释放内存资源

public long skip(long n) 跳过 n 个字符不读,返回实际跳过的字节数


Writer 流中的常用方法:

public void write(int c)  向输出流中写入一个字符数据,该字符数据为参数b的低16位

public void write(char[] buf)  将一个字符类型的数组中的数据写入输出流

public void write(char[] buf, int offset, int length) 将一个字符类型的数组中的从指定位置(offset)开始的length个字符写入到输出流

public void write(String str)  将一个字符串的字符写入到输出流

public void write(String str, int offset, int length) 将一个字符串从offset开始的length个字符写入到输出流

public void close() 关闭流释放内存资源

public void flush() 将输出流中的缓冲的数据全部写出到那目的地


字节流与字符流的区别:

FileInputStream 和 FileOutputSteram 可以完成所有格式文件的复制

FileReader 和FileWirte 只可以完成文本文件的复制,却无法完成视频格式文件的复制

因为字节是不需要解码和编码的,将字节转化为字符才存在解解码和编码的问题

字节流可以从所有的格式的设备中读写数据,但字符流只能从文本格式的设备中读写数据



文件流:


文件流包括:

FileInputStream, FileOutputStream  --字节流
FileReader, FileWrite              --字符流


例子: 读取一个文件的内容并将其输出到显示器上,并统计读取出来的字节的个数


[java]   view plain copy

/*  
    利用FileReader流来读取一个文件中的数据,并在显示器上输出!  
*/   
  
import  java.io.*;  
  
public   class  TestFileReader  
{  
     public   static   void  main(String[] args)  
    {  
        FileReader fr =  null ;  
  
         try   
        {  
            fr =  new  FileReader( "C:\\Documents and Settings\\others\\桌面\\java\\TestFileReader.java" );  
             int  cnt =  0 ;  
             int  ch;    
  
             while  (- 1  != (ch=fr.read()))  //20行       
            {  
                System.out.print(( char )ch);   // System.out.print(int ch); 这是在显示器上输出ch的整数值,所以必须的进行类型转化,我们需要输出的是ch所代表的整数对应的字符   
                ++cnt;  
            }  
  
            System.out.printf( "总共从TestFileReader.java文件中读取了%d个字符" , cnt);              
        }  
         catch  (FileNotFoundException e)  
        {  
            System.out.println( "找不到文件!" );  
            System.exit(- 1 );  
        }  
         catch  (IOException e)  
        {  
            System.out.println( "文件读取失败!" );  
            System.exit(- 1 );  
        }  
    }  
}  



FileInputStream 的使用:

InputStream 是用来读取字节的,是个抽象类,我们通常使得的是该类的子类
FiledInputStream 是InputStream的子类,利用FileInputStream可以将一个文件的内容按字节为单位读取出来

FileInputStream 有一个很常用的构造函数 :

public fileInputStream(String fileName)
利用该构造函数可以实现将输入流连接到某个文件的功能 
必须对本构造函数抛出异常进行捕捉

如果用字符串来表示扣件系统的文件路径时,我们可以使用\\ 和/两种方式来作为文件夹的路径分隔符

FileOutputStream 同理


缓冲流:


什么是缓冲流:

缓冲流就是带有缓冲区的输入输出流

为什么需要缓冲流:

缓冲流可以显著的减少我们对IO访问的次数,保护我们的硬盘


说明:

缓冲流本身就是处理流(处理流也叫包裹流),缓冲流必须提依附节点流(节点流也叫原始流)

缓冲流要"套接"在相应的节点流上,对读写的数据提供了缓冲的功能,提高了读写的效率,同时增加了一些新的方法

缓冲输入流支持其父类的mark和reset方法

BufferedReader提供了readLine方法用于读取一行字符串(以\r或\n分隔 )

BufferedWriter提供了newLine用于写入一行分隔符

对于输出的缓冲流,写出的数据会先在内存中缓存,使用flush方法会使内存中的数据立刻写出


BufferedOUtputStream 和 BufferedInputStream:


BufferedOutputStream 带缓冲的输出流,允许一次向硬盘写入多个字节的数据

BufferedInputStream 带缓冲的输入流,允许一次向程序中读入多个字节的数据

BufferedOutputStream 和 BufferedInputStream 都是包裹流,必须的依附于OutputStream 和 InputStream


例:
[java]   view plain copy

/*  
 
    利用BufferedOutputStream 和 BufferedInputStream完成大容量文件的复制  
    这远比单纯利用 FileInputStream  和 FileOutputStream 要快得多  
 
    BufferedOutputStream 和 BufferedInputStream 都是包裹流,必须的依附于  
    OutputStream  和 OutputStream   
*/   
  
  
import  java.io.*;  
  
public   class  TestBufferedInputStreamOutputStreamCopy  
{  
     public   static   void  main(String[] args)  
    {  
        BufferedOutputStream bos =  null ;  
        BufferedInputStream bis =  null ;  
          
         try   
        {  
            bos =  new  BufferedOutputStream (  
                                         new  FileOutputStream( "e:/OutputView.txt" )  
                                    );   //bos 输出流有个默认的缓冲区,大小为32个字节     
                                      
            bis =  new  BufferedInputStream(  
                                         new  FileInputStream( "c:\\11.rmvb" )  
                                    );   //bis 输入流有个默认的缓冲区,大小为32个字节     
             byte [] buf =  new   byte [ 1024 ];  
             int  len = bis.read(buf,  0 1024 );  //一定要注意,这不是从buf中读数据,而是从bis所关联到的D:\\综艺\\电影\\猫和老鼠\\CD4.rmvb文件中读取数据,并将读取的数据写入bis自己的默认缓冲区中,然后再将缓冲区的内容写入buf数组中,每次最多向buf数组中写入1024个字节,返回实际写入buf数组的字节个数,如果读到了文件的末尾,无法再向buf数组中写入数据,则返回-1   
             while  (- 1  != len)  
            {  
                bos.write(buf,  0 , len);   //不是写入buf数组,而是将buf数组中下标从0开始的到len-1为止的所有数据写入bos所关联到的"d:/share/OutputView.txt"文件中   
                len = bis.read(buf);  //bis.read(buf);  等价于 bis.read(buf, 0, buf.length);   
            }  
            bos.flush();  
            bis.close();  
            bos.close();                          
        }  
         catch  (FileNotFoundException e)  
        {  
            System.out.println( "没有找到文件!" );  
            System.exit(- 1 );  
        }  
         catch  (IOException e)  
        {  
            System.out.println( "文件读写错误!" );  
            System.exit(- 1 );  
        }  
          
        System.out.println( "文件复制成功!" );    
    }             
}  



如果我们希望用BufferedInputStream和BufferedOutputStream完成“将一个设备中的数据导入另一个设备中” 我们就就忘定义一个临时的bete类型的数组,用这个临时数组作为输入流与输出流进行交互的中转枢纽


转换流:


Reader

       |--InputStreamReader

              |--FileReader:专门用于处理文件的字符读取流对象。

Writer

       |--OutputStreamWriter

                   |--FileWriter:专门用于处理文件的字符写入流对象。

        

特点:

         1,是字节流和字符流之间的桥梁。

         2,该流对象中可以对读取到的字节数据进行指定编码表的编码转换。

        

         什么时候使用呢?

         1,当字节和字符之间有转换动作时。

         2,流操作的数据需要进行编码表的指定时。

 

         具体的对象体现:

         1,InputStreamReader:字节到字符的桥梁。

         2,OutputStreamWriter:字符到字节的桥梁。

 

         这两个流对象是字符流体系中的成员。

 

         那么它们有转换作用,而本身又是字符流。所以在构造的时候,需要传入字节流对象进来。

 

         构造函数:

         InputStreamReader(InputStream):通过该构造函数初始化,使用的是本系统默认的编码表GBK。

         InputStreamReader(InputStream,String charSet):通过该构造函数初始化,可以指定编码表。

 

         OutputStreamWriter(OutputStream):通过该构造函数初始化,使用的是本系统默认的编码表GBK。

         OutputStreamWriter(OutputStream,String charSet):通过该构造函数初始化,可以指定编码表。

 

         操作文件的字符流对象是转换流的子类。

         Reader

                   |--InputStreamReader

                            |--FileReader

 

         Writer

                   |--OutputStreamWriter

                            |--FileWriter

 

         转换流中的read方法。已经融入了编码表,

         在底层调用字节流的read方法时将获取的一个或者多个字节数据进行临时存储,

         并去查指定的编码表,如果编码表没有指定,

         查的是默认码表。那么转流流的read方法就可以返回一个字符比如中文。

        

         转换流已经完成了编码转换的动作,对于直接操作的文本文件的FileReaer而言,就不用在重新定义了,

         只要继承该转换流,获取其方法,就可以直接操作文本文件中的字符数据了



Print流:


    Print流只有输出流无输入流,PrintWriter和PrintStream分别针对字符字节
    两个类提供了重载的Print和Println方法用于多种数据类型的输出
    PrintWriter和PrintStream的输出操作不会抛出异常
    PrintWriter和PrintStream有自动flush功能
    ----System.setOut(接收OutputStream类):用于设置系统默认输出流


Object流:


    等同于c#序列化,用直接将Object写入或读出
    transient关键字为不序列化此成员变量
    需要序列化的类必须实现Serializable接口
    主要方法:writeObject(Object); readObject();
    读出为Object类型需要强转数据类型

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值