黑马程序员----IO流


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

IO流

一.IO流概述

  流:可以理解数据的流动,就是一个数据流。IO流最终要以对象来体现,对象都存在IO包中。
 

 流也进行分类:
 

:输入流(读)和输出流(写)。

:因为处理的数据不同,分为字节流和字符流。

        字节流抽象基类:

            InputSteam,OutputStream

        字符流抽象基类:

            Reader,Writer

      字节流:   处理字节数据的流对象。字节流可以处理设备上的所有数据,所以字节流一样可以处理字符数据。

      字符流:  为了方便于文字的解析,所以将字节流和编码表封装成对象,这个对象就是字符流。只要操作字符数据,优先考虑使用字符流体系。 


    如何判断是输入流,还是输出流?
        以内存为参照,如果数据向内存流动,则是输入流,反之则为输出流.

二.字符流

    字符流的抽象基类:
     
|---->Reader:字符输入流

     |---->Writer:字符输出流
 

    构造方法:

    |--->FileWriter(String fileName) 

            根据给定的文件名构造一个 FileWriter 对象。 

    |--->FileWriter(String fileName, boolean append) 

       根据给定的文件名以及指示是否附加写入数据的 boolean 值来构造 FileWriter 对象。 

     可以实现文件的追加写入,第二个参数表示是否追加写入,默认是false,就会重头开始写入,如果是true,就会追加写入


    常用方法:

    |--->void write(String str):写入字符串。 

    |--->abstract void flush():刷新该流的缓冲 

    |--->abstract void close():关闭此流,但要先刷新它。 
 

    创建文件步骤:

      // 1.创建流对象,建立数据存放文件,指定目的地
      FileWriter fw = new FileWriter(“Test.txt”);
      //(注:该文件会被创建到指定目录下。如果该目录下已有同名文件,将被覆盖)
       //2.调用流对象的写入方法,将数据写入流
      fw.write(“text”);
    //3.刷新流对象中的缓冲中的数据,将数据刷到目的地中。
    fw.flush();
    //4.关闭流资源,并将流中的数据清空到文件中。
      fw.close();


    5.close()flush()的区别:
     
flush():将缓冲区的数据刷到目的地中后,流可以使用。

     close():将缓冲区的数据刷到目的地中后,流就关闭了,该方法主要用于结束调用的底层资源。这个动作一定做。


    在文本后面追加操作示例:

public class FileWriterDemo2 {  
    public static void main(String[] args) throws IOException{  
        FileWriter fw = null;  
        try{  
            fw = new FileWriter("fw2.txt",true);  
            for (int x = 0; x < 4; x++){  
                fw.write(x + "hello\r\n");// 调用writer方法  
            }  
        }   
        catch (IOException e){  
            throw new RuntimeException("写入失败");  
        }  
        finally {  // 释放资源 
            if(fw!=null){  
                try{  
                    fw.close();  
                }   
                catch (IOException e2) {  
                    throw new RuntimeException("关闭流失败");  
                }  
            }  
        }  
    }  
} 



    FileReader

    FileReader是Reader的一个子类,用来读取字符文件的便捷类
 

    构造方法:

   FileReader(File file) 

            在给定从中读取数据的 File 的情况下创建一个新 FileReader。 

   FileReader(String fileName) 

            在给定从中读取数据的文件名的情况下创建一个新 FileReader。 
 

    两种读取方法:

    int read():读取单个字符。 

    int read(char[] cbuf):将字符读入数组。 
 

     读取方法示例:

       

        FileReader fr = new FileReader("D:\\Demo\\sdfs.txt");  
        //创建一个文件读取流对象,和指定名称的文件相关联。  
        //要保证该文件是已经存在的,如果不存在,会发生异常FileNotFoundException  
        int ch = 0;  
        while((ch = fr.read())!=-1){  
            System.out.print((char)ch);  
        }  
        fr.close();  

 

 注意:

 

   1.定义文件路径时,可以用“/”或者“\\”。
   2.在创建一个文件时,如果目录下有同名文 件将被覆盖。
   3.在读取文件时,必须保证该文件已存在, 否则出异常。
 

三.字符流缓冲区

    缓冲区的出现提高了对数据的读写效率。要结合流才可以使用,在流的基础上对流的功能进行了增强。
 

    对应类:

        BufferedWriter (extends Reader)

        BufferedReader (extends Writer)

    这两个类同样具有内部缓存机制,并可以以行为单位进行输入/输出.
 

    BufferedWriter

    将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。该缓冲区中提供了一个跨平台的换行符:newLine();
 

    方法

   close():关闭此流,但要先刷新它。 

   flush():刷新该流的缓冲。 

    newLine():写入一个行分隔符。 可跨平台使用

   write(char[] cbuf, int off, int len):写入字符数组的某一部分。 

    write(int c):写入单个字符。 

    write(String s, int off, int len):写入字符串的某一部分。


特别注意:用到缓冲区,就要记得刷新。


    BufferedReader

    从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。

    该缓冲区提供了一个一次读一行的方法 readLine(),方便于对文本数据的获取。当返回null时,表示读到文件末尾。(注:readLine方法返回的时候只返回回车符之前的数据内容。并不返回回车符。)

    常用方法:

   void close():关闭该流并释放与之关联的所有资源。 

   int read():读取单个字符。 

   int read(char[] cbuf, int off, int len):将字符读入数组的某一部分。 

   String readLine():读取一个文本行。 

 


      字节流
 
    字节流的抽象基类:
    InputStream:字节输入流
    OutputStream:字节输出流
    它的操作与字符流类似,可以参与字符流的定义、读取、写入、处理异常的格式,只不过是处理的数据不同,因为对于非字符的数据,比如图片、视频、音频文件(例如mp3)等,这些文件只能用字节流对之进行操作。
 
    FileInputStream
    FileInputStream是InputStream的一个子类,用于读取诸如图像数据之类的原始字节流
    构造方法:
    FileInputStream(File file) 
            通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定。 
   FileInputStream(FileDescriptor fdObj) 
            通过使用文件描述符 fdObj 创建一个 FileInputStream,该文件描述符表示到文件系统中某个实际文件的现有连接。 
   FileInputStream(String name) 
            通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。 
    常用方法:
  int available()返回下一次对此输入流调用的方法可以不受阻塞地从此输入流读取(或跳过)的估计剩余字节数。 
    void close()关闭此文件输入流并释放与此流有关的所有系统资源。 
   int read()从此输入流中读取一个数据字节。 
  int read(byte[] b)从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。 
    int read(byte[] b, int off, int len)从此输入流中将最多 len 个字节的数据读入一个 byte 数组中。 
 

    //按字节数组读取  
    public static void read2(){  
        FileInputStream fis = null;  
        try {  
            fis = new FileInputStream("D:\\Demo\\demo.java");//新建字节读取的对象,明确源文件  
            int len = 0;  
            byte[] buff = new byte[1024];//定义一个字节数组,用于存储字节  
            while((len=fis.read(buff))!=-1){  //每次将读取到的字节存储进buff数组  
                System.out.println(new String(buff,0,len));//将字节数组转换成字符串输出  
            }  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
        finally{  //执行关闭资源的操作 
            if(fis!=null) {  
                try {  
                    fis.close();  
                } catch (IOException e2) {  
                    e2.printStackTrace();  
                }  
            }  
        }  
    }  
}  


    注意available()这个方法的用法,取文件字节数,然后定义一个刚好大小的字节数组。代码如下:
    fis =new FileInputStream(file);  
    byte [] ch =newbyte[fis.available()];  
    fis.read(ch);  
    System.out.println(new String(ch));  
    //但是如果文件过大,会造成内存溢出。


 
    FileOutputStream
    FileOutputStream是OutputStream的一个子类,用于写入诸如图像数据之类的原始字节的流。
 
    构造方法:
    FileOutputStream(File file) 
            创建一个向指定 File 对象表示的文件中写入数据的文件输出流。 
    FileOutputStream(String name) 
            创建一个向具有指定名称的文件中写入数据的输出文件流。 
   FileOutputStream(String name, boolean append) 
            创建一个向具有指定 name 的文件中写入数据的输出文件流。 
 
    常用方法:
   close():关闭此文件输出流并释放与此流有关的所有系统资源。  
   write(byte[] b):将 b.length 个字节从指定byte数组写入此文件输出流中。 
   write(byte[] b, int off, int len):将指定byte数组中从偏移量 off 开始的 len 个字节写入此文件输出流。 
   write(int b):将指定字节写入此文件输出流。 
 

字节流缓冲区

    字节流缓冲区同样是提高了字节流的读写效率。
    对应类:
        BufferedOutputStream (extends OutputStream)
        BufferedInputStream (extends InputStream)
 
利用缓冲区的技术,拷贝Mp3文件
public class copyMp3 {  
    public static void main(String[] args){  
        BufferedInputStream buis=null;  
        BufferedOutputStream buos=null;  
        try{  
 
            buis=new BufferedInputStream(new FileInputStream("D:\\play.mp3"));  
            buos=new BufferedOutputStream(new FileOutputStream("D:\\play_copy2.mp3"));  
             
            byte[] buff = new byte[1024];  
            int len = 0;  
            while((len=buis.read(buff))!=-1){  
                buos.write(buff,0,len);  
            }     
        }  
        catch(IOException e) {  
            throw new RuntimeException("复制失败");  
        }  
        finally{  
            if(buis!=null){  
                try {  buis.close();  
                }catch (Exception e2) {  
                    throw new RuntimeException();  
                }  
            }  
            if(buos!=null){  
                try {  buos.close();  
                } catch (Exception e2) {  
                    throw new RuntimeException();  
                }  
            }  
        }       
    }  
}  


  转换流
    转换流包括:
        InputStreamReader:字节流通向字符流的桥梁
        OutputStreamWriter:字符流通向字节流的桥梁
    转换流的由来:是字节流和字符流的桥梁;方便了字节流和字符流之间的操作
    转换流的应用:字节流中的数据都是字符时,转成字符流操作更高效
 
    InputStreamReader
    是字节流通向字符流的桥梁。
    每次调用 InputStreamReader 中的一个 read()方法都会导致从底层输入流读取一个或多个字节。要启用从字节到字符的有效转换,可以提前从底层流读取更多的字节,使其超过满足当前读取操作所需的字节。为了达到最高效率,可要考虑在 BufferedReader 内包装 InputStreamReader。
 
    构造方法:
    InputStreamReader(InputStream in)
    InputStreamReader(InputStream in, String charsetName)
    示例:BufferedReader in = new BufferedReader(new InputStreamReader(System.in));(必须记住)

    OutputStreamWriter 
    是字符流通向字节流的桥梁,将要写入流中的字符编码成字节。
    每次调用 write() 方法都会导致在给定字符(或字符集)上调用编码转换器。在写入底层输出流之前,得到的这些字节将在缓冲区中累积。为了获得最高效率,可考虑将 OutputStreamWriter 包装到 BufferedWriter 中,以避免频繁调用转换器。
    构造方法:
    OutputStreamWriter(OutputStream out)
    OutputStreamWriter(OutputStream out, String charsetName)
 
    示例:
    BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
    System.in 默认设备为键盘
        System.setIn(InputStream in)\\ 重新分配“标准”输入流。
    System.out 默认设备为控制台
        System. setOut(PrintStream out) \\重新分配“标准”输出流。

四.标准输入与输出
    System类中的字段:in,out,它们各代表了系统标准的输入和输出设备,默认输入设备是键盘,输出设备是显示器。
    System.in的类型是InputStream.
    System.out的类型是PrintStream
    示例:
    例:获取键盘录入数据,然后将数据流向显示器,那么显示器就是目的地。
    通过System类的setIn,setOut方法对默认设备进行改变:
        System.setIn(new FileInputStream(“1.txt”));//将源改成文件1.txt。
        System.setOut(new FileOutputStream(“2.txt”));//将目的改成文件2.txt
    因为是字节流处理的是文本数据,可以转换成字符流,操作更方便。
    BfferedReader bufr =new BufferedReader(new InputStreamReader(System.in));
    BufferedWriter bufw =new BufferedWriter(new OutputStreamWriter(System.out)); 

File类
    
File类是文件和目录路径名的抽象表示形式。 是io包中唯一代表磁盘文件本身的对象,其定义了一些与平台无关的方法来操作文件,可以通过调用File类中的方法,实现创建.删除.重命名文件等操作,File类是对象主要用来获取未文件本身的一些信息,如文件所在的目录、文件的长度、文件的读写权限等。File对象可以作为参数传递给流的构造函数。
 
    构造方法:
   File(File parent, String child) 
            根据 parent 抽象路径名和 child 路径名字符串创建一个新 File 实例。 
   File(String pathname) 
            通过将给定路径名字符串转换为抽象路径名来创建一个新 File 实例。 
   File(String parent, String child) 
            根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例。 
   File(URI uri) 
            通过将给定的 file: URI 转换为一个抽象路径名来创建一个新的 File 实例。 
 
    常见方法:
    1.创建
        boolean createNewFile():在指定位置创建文件,如果该文件已经存在,则不创建,返回false。
        boolean mkdir():创建文件夹。
        boolean mkdirs():创建多级文件夹。
        注:File类创建文件的方法createNewFile()与输出流的方法不同点:
            File类通过createNewFile方法来创建文件的话,如果文件存在则不创建
            输出流是对象一建立就创建文件,如果文件存在就会覆盖原文件。
    2.删除
        boolean delete():删除失败返回false。如果文件正在被使用,则删除不了返回falsel。
        void deleteOnExit():在程序退出时删除指定文件。
    3.判断
        boolean  exists():文件或目录是否存在。
        boolean isFile():是否是一个标准文件。
        boolean isDirectory():是否是一个目录。
        boolean isHidden():是否是一个隐藏文件。
        boolean isAbsolute():是否为绝对路径名。
        boolean canRead()是否可读
        boolean canWrite()是否可写
    4.获取
        String getName():返回由此抽象路径名表示的文件或目录的名称。
        String getPath():获取相对路径
        String getParent():获取父级目录,如果此路径名没有指定父目录,则返回 null。
        String getAbsolutePath():获取绝对路径
        long lastModified():返回此抽象路径名表示的文件最后一次被修改的时间。
        long length():返回由此抽象路径名表示的文件的长度.
        static File[] listRoots():列出系统的可用的根
        String[] list():获取指定目录下的所有文件和文件夹的名称数组
        File[] listFiles():获取指定目录下的所有文件和文件夹的File数组
    5.修改
        boolean renameTo(File dest):重新命名此抽象路径名表示的文件。

Properties类

    Properties是hashtable的子类,也就是说它具备map集合的特点。而且它里面存储的键值对都是字符串。
    是集合中和IO技术相结合的集合容器。
 
    该对象的特点:可以用于键值对形式的配置文件,那么在加载数据时,需要数据有固定格式:键=值。
 
    构造方法:
   Properties():创建一个无默认值的空属性列表。 
   Properties(Properties defaults):创建一个带有指定默认值的空属性列表。
 
    常用方法:
   Object setProperty(String key,String value)
            调用Hashtable的put方法,设置键值对
    String getProperty(String key)
            用指定的键在此属性列表中搜索属性
   Set stringPropertyNames
            获取集合中所有的键
    void load(InputStream in)
            从输入流中读取属性列表(键和元素对)。
    void load(Reader reader)
            按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。
    void list(PrintStream out)  
            将属性列表输出到指定的输出流。
   void list(PrintWriter out)   
            将属性列表输出到指定的输出流。
    void Store(OutputStream out,String comments)
            以适合使用 load(InputStream) 方法加载到 Properties 表中的格式,将此 Properties 表中的属性列表(键和元素对)写入输出流。 
   void store(Writer writer, String comments) 
            以适合使用 load(Reader) 方法的格式,将此 Properties 表中的属性列表(键和元素对)写入输出字符。
 
class PropertiesDemo {  
    public static void main(String[] args) throws IOException {  
        loadDemo();  
    }  
    public static void loadDemo()throws IOException{  
        Properties prop = new Properties();  
        FileInputStream fis = new FileInputStream("info.txt");  
  
        //将流中的数据加载进集合。  
        prop.load(fis);  
        prop.setProperty("wangwu","39");//并没有写入到硬盘中,只写入到流中  
  
        FileOutputStream fos = new FileOutputStream("info.txt");  
        prop.store(fos,"haha");//将流中的数据写入到硬盘中  
        prop.list(System.out);//列出目录  
  
        fos.close();  
        fis.close();  
    }  
    //设置和获取元素。  
    public static void setAndGet() {  
        Properties prop = new Properties();  
        prop.setProperty("zhangsan","30");//设置元素  
        prop.setProperty("lisi","39");  
  
        String value = prop.getProperty("lisi");  
        System.out.println(value);//打印出39  
              
        prop.setProperty("lisi",89+"");  
  
        Set names = prop.stringPropertyNames();  
        for(String s : names){  
            System.out.println(s+":"+prop.getProperty(s));  
        }  
    }  
}  


打印流

    可以直接操作输入流和文件,该流提供了打印方法,可以将各种数据类型的数据都原样打印。
 
    字节打印流:PrintStream
        构造函数可以接收的参数类型:
        1.file对象:File
        2.字符串路径:String
        3.字节输出流:OutputStream

    字符打印流:PrintWriter
        构造函数可以接收的参数类型:
        1.file对象:File
        2.字符串路径:String
        3.字节输出流:OutputStream
        4.字符输出流:Writer
    注:与其他输出流不同,PrintStream 永远不会抛出IOException,而且打印流可以根据指定编码转成字符!
class  PrintStreamDemo{  
    public static void main(String[] args) throws IOException{  
        BufferedReader bufr =   
            new BufferedReader(new InputStreamReader(System.in));//读取键盘输入  
  
        PrintWriter out = new PrintWriter(new FileWriter("a.txt"),true);//ture代表自动刷新  
  
        String line = null;  
  
        while((line=bufr.readLine())!=null){  
            if("over".equals(line))  
                break;  
            out.println(line.toUpperCase());//转换成大写  
            //out.flush();//刷新  
        }  
        out.close();  
        bufr.close();  
    }     
}  



对象序列化

 
    数据可以封装成对象,对象运行时是在堆内存中的,如果对象的数据需要存储在硬盘上,那么就要用到对象的序列化流。对象序列化(也叫对象的可串行性)其实就是对象持久化,把内存中的对象,变成硬盘上的文件内容。
    IO中供对象序列化的流对象为ObjectInputStream和ObjectOutputStream。
 
    注意:
        1.用ObjectOutputStream写入的的文件,只能用ObjectInputStream来重构读取。
        2.被序列化的对象必须实现Serializable接口。
        3.对象的静态成员和被transient关键字修饰的成员不能被序列化。(当对象在堆内存的私有对象不希望被序列化时,可以使用transient关键字标识)。
 
  ObjectInputStream
        对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化。
 
    构造方法:
   protected  ObjectInputStream() 
        为完全重新实现 ObjectInputStream 的子类提供一种方式,让它不必分配仅由 ObjectInputStream 的实现使用的私有数据。 
    ObjectInputStream(InputStream in) 
        创建从指定 InputStream 读取的 ObjectInputStream。 
    特有方法:
    Object readObject() :从 ObjectInputStream 读取对象。 
 
 
    ObjectOutputStream
        将 Java 对象的基本数据类型和图形写入 OutputStream。可以使用 ObjectInputStream 读取(重构)对象。通过在流中使用文件可以实现对象的持久存储。
 
    构造方法:
   protected  ObjectOutputStream() 
        为完全重新实现 ObjectOutputStream 的子类提供一种方法,让它不必分配仅由 ObjectOutputStream 的实现使用的私有数据。 
   ObjectOutputStream(OutputStream out) 
        创建写入指定 OutputStream 的 ObjectOutputStream。 
    特有方法:
    void writeObject(Object obj):将指定的对象写入 ObjectOutputStream。
 
    Serializable接口
    在对对象进行序列化时,必须实行Serializable接口,否则使用ObjectOutputStream写入时,会出现NotSerializableException异常。
    Serializable接口并没必须要实现的方法,类定义时仅标示一下实现即可。实现Serializable的类,都有serialVersionUID,如果你没有在类中显式定义一个serialVersionUID,那么编译器会根据该类中的成员生成一个具有唯一性的serialVersionUID。
    显式定义serialVersionUID的好处:
    1.如果你在对类对象进行了序列化之后,又修改了这个类,那么再次读取修改前序列化的对象时,编译器可以识别;
    2.如果没有显式定义,你修改后的类经过编译器编译后会生成一个新的serialVersionUID,这个serialVersionUID跟修改前类的serialVersionUID不同,当你再次读取时,编译器会报出InvalidClassException异常。所以,如果类对象需要序列化,建议显式定义serialVersionUID。



操作字节数组

    ByteArrayInputStream :在构造的时候,需要接收数据源,。而且数据源是一个字节数组。
        包含一个内部缓冲区,该缓冲区包含从流中读取的字节。内部计数器跟踪 read 方法要提供的下一个字节。
    ByteArrayOutputStream: 在构造的时候,不用定义数据目的,因为该对象中已经内部封装了可变长度的字节数组,这就是数据目的地。此类实现了一个输出流,其中的数据被写入一个 byte 数组。缓冲区会随着数据的不断写入而自动增长。可使用 toByteArray() 和 toString() 获取数据。 
    注意:
        1.因为这两个流对象都操作的是数组,并没有使用系统资源,所以,不用进行close关闭,即使你关闭了,它的其他方 
   法还可以使用,而不会抛出IOException。
        2.使用这对对象操作时,它的源和目的都是内存。
    用途:这两个对象是在用流的思想来操作数组,当我们需要把一个文件中的数据加入内存中的数组时,就可以考虑用这个两个对象。此外,它还有writeTo(OutputStream os)可以把ByteArrayOutputStream对象内部定义的缓冲区内容,一次性写入os中。操作字符数组、字符串的流对象类型与之相似,可以参与它们的使用方法。
class  PrintStreamDemo{  
    public static void main(String[] args) throws IOException{  
        BufferedReader bufr =   
            new BufferedReader(new InputStreamReader(System.in));//读取键盘输入  
  
        PrintWriter out = new PrintWriter(new FileWriter("a.txt"),true);//ture代表自动刷新  
  
        String line = null;  
  
        while((line=bufr.readLine())!=null){  
            if("over".equals(line))  
                break;  
            out.println(line.toUpperCase());//转换成大写  
            //out.flush();//刷新  
        }  
        out.close();  
        bufr.close();  
    }     
}  


字符编码

    字符流的出现是为了方便操作字符数据,其方法操作的原因是因为内部加入了编码表。Java中能够实现字节根据指定编码表转成字符的,有四个类:InputStreamReader和OutputStreamWriter,PrintStream和PrintWriter。它们都能够加构造时,指定编码表;但后两个是打印流,只能用于打印,使用有局限,所以相对而言,还是前两个转换流使用多一些。
    编码表的由来:
    计算机只能识别二进制数据,早期是电信号。为了应用计算机方便,让它可以识别各个国家的文字,就将各个国家的文字用数字来表示,并将文字与二进制数字一一对应,形成了一张表,这个表就是编码表。
常见的编码表
    地域码表
    1.ASCII:美国码表,息交换码,用一个字节的7位表示。
    2.ISO8859-1:欧洲码表,拉丁码表,用一个字节的8位表示,最高位1
    3.GB2312:中国中文编码表,它用两个字节表示,为兼容ASCII,它的两个字节的高位都是1,也即是两个负数;但与ISO8859-1冲突。大概有六七千个字。
    4.GBK:中国的中文编码表的升级版,扩容到2万多字。
    通用码表:
    1.Unicode:国际标准码,融合多种语言文字。所有的文字都用两个字节表示,Java默认使用的就是Unicode。
    2.UTF-8:UnicodeTransform Format -8。Unicode码把用一个字节能装下的文字,也用两个字节表示,有些浪费空间,对之进行优化的结果就是UTF-8。UTF-8编码表,一个文字最少用1个字节表示,最多用3个字节表示,并且每个字节开始都有标识头,所以很容易于其他编码表区分出来。
    当一写入文件采用的编码与读取文件采用的编码不相同时,可能会出现乱码,因为每个编码在各自的编码表中对应的编码值是不同的,所以在读取与写入的时候就要指定好使用的是何种编码,而转换流就可以指定编码表,他的应用可以分为两种:
    1.可以将字符以指定的编码格式存储。
    2.可以对文本数据以指定的编码格式来解读。
 
    指定编码表的动作由构造函数完成:
    1.InputStreamReader(InputStream in,String charsetName) 
        创建使用指定字符集的InputStreamReader。
    2.OutputStreamWriter(OutputStream out,String charsetName) 
        创建使用指定字符集的OutputStreamWriter。


  IO流总结

 
    使用IO思考步骤:
    1:搞清楚数据源和目的地都可以用哪些对象操作
     数据源:InputStream
             Reader
     目的地:OutputStream
             Writer
 
    2:分清楚数据源和目的地是什么类型的文件?
      数据源:Reader:文本文件
              InputStream:媒体文件
      目的地:Writer:文本文件
              OutputStream:媒体文件
 
    3:搞清楚数据源和目的地的设备
       数据源:
        文件   FileReader
        键盘录入  InputStream is = System.in;
                  使用转换流InputStreamReader isr = new InputStreamReader(System.in);
       目的地:
         文件  FileWriter
         控制台输出  OutputStream os = System.out;
                     使用转换流OutputStreamWriter osw = new OutputStreamWriter(os);
 
    4:是否要求高效
       是:使用Buffered流对象
       否:不使用Buffered流对象
 
    源与目的地操作规律:
 
    1.文本文件--文本文件
        BufferedReader br = new BufferedReader(new FileReader("a.txt"));
        BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));
 
    2.文本文件--控制台输出
        BufferedReader br = new BufferedReader(new FileReader("a.txt"));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
 
    3.键盘录入--文本文件
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));
 
    4.键盘录入--控制台输出
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

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

你可能感兴趣的:(学习笔记)