20210325JavaIO流

JavaIO流

编辑时间:2021/03/25

读完本节:大概花费40钟,共5493词

1.File类的使用
  1. java.io.File类:文件和文件目录路径的抽象表示形式,与平台无关,声明在java.io包下
  2. File能新建、删除、重命名文件和目录,但File不能访问内容本身。如果需要访问文件内容本身,则需要使用输入/输出流
  3. 想要在Java程序中表示一个真实存在的文件或目录,那么不许有一个File对象,但是Java程序中的一个File对象,可能没有一个真实存在的文件或目录
  4. File对象可以作为参数传递给流的构造器,指明读取或者写入的“终点”
  5. File类常用的三个构造器:
    1. public File(String pathname):以pathname为路径创建File对象,可以是绝对路径或相对路径,如果pathname是相对路径,则默认的当前路径在系统属性user.dir中存储
      1. 绝对路径:是一个固定的路径,从盘符开始
      2. 相对路径:是相对于某个位置开始
    2. public File(String parent, String child):以parent为父路径,child为子路径创建File对象
    3. public File(File parent, String child):根据一个父File对象和子文件路径创建File对象
  6. File类中的路径分割符:
    1. 路径中的每级目录之间使用一个路径分隔符隔开
    2. 路径分隔符的表示个系统环境有关:
      1. Windows和DOS系统默认使用“\”来表示
      2. Unix和URL使用“/”来表示
    3. Java程序支持跨平台运行,因此路径分隔符要正确使用
    4. 为了满足跨平台运行的要求,java.io.File类提供了一个常量:public static final String separator。根据操作系统,动态的提供分隔符
    5. 举例:
      1. Windows和DOS情况下:*File file1 = new File(“d:\\doc\\example”);*两个“\\”的原因是Java中存在转义字符,为了正确的表达“\”需要另一个“\”辅助显示
      2. Unix或URL情况下:File file2 = new File(“d:/doc/example”);
      3. 使用JavaAPI中java.io.File提供的separator:File file3 = new File(“d:” + File.separator + “doc” + File.separator + “example”);
  7. File类中常用的方法
    1. File类的获取功能
      1. public String getAbsolutePath():获取绝对路径
      2. public String getPath():获取路径
      3. public String getName():获取名称
      4. public String getParent():获取上层文件目录路径,若无返回null
      5. public long length():获取文件长度(即字节数)。该方法不能获取目录的长度
      6. public long lastModified():获取最后一次修改的时间,毫秒值
      7. public String[] list():获取指定目录下所有文件或者文件目录的名称数组,仅适用于文件目录
      8. public File[] listFiles():获取指定目录下的所有文件或者文件目录的File数组,仅适用于文件目录
    2. File类的重命名功能
      1. public boolean renameTo(File dest):把文件重命名为指定的文件路径。例file1.renameTo(file2),要想返回true,需要file1在硬盘中是存在的,且file2不能在硬盘中存在
    3. File类的判断功能
      1. public boolean isDirectory():判断是否是文件目录
      2. public boolean isFile():判断是否是文件
      3. public boolean exists():判断是否存在,文件和文件目录都适用
      4. public boolean canRead():判断是否可读
      5. public boolean canWrite():判断是否可写
      6. public boolean isHidden():判断是否隐藏
    4. File类的创建功能
      1. public boolean createNewFile():创建文件,若文件存在,则不创建,返回false
      2. public boolean mkdir():创建文件目录。如果此文件目录存在,就不创建。如果文件的上层目录不存在,也不创建
      3. public boolean mkdirs():创建文件目录。如果文件的上层目录不存在,一并创建
      4. 如果创建文件或者文件目录没有写绝对路径,则默认在项目路径下创建文件
    5. File类的删除功能
      1. public boolean delete():删除文件或者文件目录,在Java中使用该方法删除的文件或者文件目录不会经过操作系统的回收站。想要删除一个文件目录,那么该文件目录内不能包含文件或文件目录,可以考虑使用递归进层的方式遍历删除待删文件目录直至该待删文件目录下不包含文件或文件目录
2.IO流原理及流的分类
  1. JavaIO原理

    1. I/O是Input/Output的缩写,用于处理设备之间的数据传输,如读写文件、网络通讯等
    2. Java程序中,对于数据的输入输出操作以流(steam)的方式进行
    3. java.io包下提供了各种“流”类和接口,用以获取不停种类的数据,并通过标准的方法输入或输出数据
    4. Input:读取外部数据(磁盘、光盘等存储设备的数据)到程序(内存)中
    5. Output:将程序(内存)数据输出到磁盘、光盘等存储设备中
  2. 流的分类:

    1. 按照数据单位的不同分为:字节流(8bit)、字符流(16bit)

    2. 按照数据流的流向的不同分为:输入流、输出流

    3. 按照流的角色的不同分为:节点流、处理流

      抽象基类字节流字符流
      输入流InputStreamReader
      输出流OutPutStreamWriter
    4. Java的IO流共涉及40多个类,实际上非常规则,都是从如上的四个抽象基类派生出来的

    5. 由这四个类派生出来的子类名称都是以其父类名作为子类名的后缀

    image-20210326140907374

    1. IO流体系

      分类字节输入流字节输出流字符输入流字符输出流
      抽象基类InputStreamOutputStreamReaderWriter
      访问文件FileInputStreamFileOutputStreamFileReaderFileWriter
      访问数组ByteArrayInputStreamByteArrayOutputStreamCharArrayReaderCharArrayWriter
      访问管道PipedInputStreamPipedOutputStreamPipedReaderPipedWriter
      访问字符串StringReaderStringWriter
      缓冲流BufferedInputStreamBufferedOutputStreamBufferedReaderBufferedWriter
      转换流InputStringReaderInputStringWriter
      对象流ObjectInputStreamObjectOutputStream
      FilterInputStreamFilterOutputStream
      打印流PrintStreamPrintWriter
      推回输入流PushbackInputStreamPushbackReader
      特殊流DataInputStreamDataOutputStream
3.节点流(文件流)
  1. FileInputStreamFileOutputStreamFileReaderFileWriter

  2. 节点流使用步骤:

    1. 实例化File类的对象,指明要操作的文件
    2. 提供具体的流
    3. 数据的读入/数据的读出
    4. 关闭流资源
    5. 异常处理
  3. testFileReader

    1. read():返回读入的一个字符,如果达到文件末尾,返回-1

    2. 异常的处理:为了保证不能被垃圾回收机制自动处理的流资源正确关闭,需要使用try-catch-finally处理,并且在一定会执行的finally中关闭流资源

    3. 读入的文件一定要存在,否则编译器回报FileNotFoundException

    4. testFileReader代码

      import org.junit.Test;
      
      import java.io.File;
      import java.io.FileReader;
      import java.io.IOException;
      
      /**
       * @Author: xuehai.XUE
       * @MailBox: xuehai.xue@qq.com
       * @Date: 2021/3/26 14:25
       * @Description:
       */
      public class FileReaderWriterTest {
      
          @Test
          public void testFileReader(){
      
              FileReader fr = null;
              //5.异常处理
              try {
                  //1. 实例化File类的对象,指明要操作的文件
                  File file = new File("hello");
      
                  //2. 提供具体的流
                  fr = new FileReader(file);
      
                  //3. 数据的读入
                  //read():返回读入的一个字符串,如果达到文件末尾,返回-1
                  //方式一:
      //            int data = fr.read();
      //            while(data != -1){
      //                System.out.print((char)data);
      //                data = fr.read();
      //            }
                  //对方式一的语法改进:
                  int data;
                  while((data = fr.read()) != -1){
                      System.out.print((char)data);
                  }
      
              } catch (IOException e) {
                  e.printStackTrace();
              } finally {
                   //当且仅当fr被创建了之后才需要关闭流资源
      //            try{
      //                if(fr != null){
      //                    fr.close();
      //                }
      //            }catch(IOException e){
      //                e.printStackTrace();
      //            }
                  //或
                  if(fr != null){
                      //4. 关闭流资源
                      try {
                          fr.close();
                      } catch (IOException e) {
                          e.printStackTrace();
                      }
                  }
              }
      
          }
      }
      
  4. testFileReader1:对read()操作的升级,使用read的重载方法

    1. read(char[] cbuf):返回每次读入cbuf数组中字符的个数。如果达到文件末尾,返回-1

    2. char[] cbuf:相当于一个缓冲区,用于存储读入的数据

    3. teatFileReader1代码

      import org.junit.Test;
      
      import java.io.File;
      import java.io.FileReader;
      import java.io.IOException;
      
      /**
       * @Author: xuehai.XUE
       * @MailBox: xuehai.xue@qq.com
       * @Date: 2021/3/26 14:25
       * @Description:
       */
      public class FileReaderWriterTest {
      
          /** 对read()操作的升级,使用read的重载方法 */
          @Test
          public void testFileReader1(){
      
              FileReader fr = null;
              //5.异常处理
              try {
                  //1. 实例化File类的对象,指明要操作的文件
                  File file = new File("hello");
      
                  //2. 提供具体的流
                  fr = new FileReader(file);
      
                  //3. 数据的读入
                  //read(char[] cbuf):返回每次读入cbuf数组中字符的个数。如果达到文件末尾,返回-1
                  char[] cbuf = new char[5];
                  int len;
                  while((len = fr.read(cbuf)) != -1){
                      //方式一:
                      //正确的写法:
      //                for(int i = 0;i < len;i++){
      //                    System.out.println(cbuf[i]);
      //                }
      //                //错误的写法:
                      for(int i = 0;i < cbuf.length;i++){
                          System.out.println(cbuf[i]);
                      }
      
                      //方式二:
                      //正确的写法:
                      String str = new String(cbuf,0,len);
                      System.out.print(str);
                      //错误的写法:
                      //对应着方式一的错误的写法
      //                String str = new String(cbuf);
      //                System.out.println(str);
      
                  }
      
              } catch (IOException e) {
                  e.printStackTrace();
              } finally {
                  //当且仅当fr被创建了之后才需要关闭流资源
      //            try{
      //                if(fr != null){
      //                    fr.close();
      //                }
      //            }catch(IOException e){
      //                e.printStackTrace();
      //            }
                  //或
                  if(fr != null){
                      //4. 关闭流资源
                      try {
                          fr.close();
                      } catch (IOException e) {
                          e.printStackTrace();
                      }
                  }
              }
      
          }
      }
      
  5. testFileWriter

    1. 从内存中写出数据到文件里

    2. 写出操作对应的文件可以不存在。程序运行时并不会报异常

      1. File对应的文件如果在硬盘中不存在,在输出的过程中,会自动创建文件
      2. File对应的文件如果在硬盘中存在:
        1. 如果流使用的构造器是:FileWriter(file,false) / FileWriter(flie):对原有文件的覆盖
        2. 如果流使用的构造器是:FileWriter(file,true):不会对原有文件覆盖,而是在原有文件的基础上追加内容
    3. testFileWriter代码

      import org.junit.Test;
      
      import java.io.File;
      import java.io.FileReader;
      import java.io.FileWriter;
      import java.io.IOException;
      
      /**
       * @Author: xuehai.XUE
       * @MailBox: xuehai.xue@qq.com
       * @Date: 2021/3/26 14:25
       * @Description:
       */
      public class FileReaderWriterTest {
          
          @Test
          public void testFileWriter(){
              FileWriter fw = null;
              //5. 异常处理
              try {
                  //1. 实例化File类的对象,指明要操作的文件
                  File file = new File("hello1.txt");
                  //2. 提供具体的流
                  //FileWriter(file,false),后一个boolean属性代表是否在文件上追加,false代表覆盖,true代表追加
                  fw = new FileWriter(file,false);
      
                  //3. 数据的读出
                  fw.write("Java is the best computer language in the world!\n");
                  fw.write("Python is one of easy computer language in the world.");
              } catch (IOException e) {
                  e.printStackTrace();
              } finally {
                  if(fw != null){
                      //4. 关闭流资源
                      try {
                          fw.close();
                      } catch (IOException e) {
                          e.printStackTrace();
                      }
                  }
              }
          }
      }
      
  6. testFileReaderFileWirter

    1. 读取文件一的内容,然后将文件一读取的内容写入文件二

    2. testFileReaderFileWirter代码

      import org.junit.Test;
      
      import java.io.File;
      import java.io.FileReader;
      import java.io.FileWriter;
      import java.io.IOException;
      
      /**
       * @Author: xuehai.XUE
       * @MailBox: xuehai.xue@qq.com
       * @Date: 2021/3/26 14:25
       * @Description:
       */
      public class FileReaderWriterTest {
      
          @Test
          public void testFileReaderFileWriter(){
              FileReader fr = null;
              FileWriter fw = null;
              //5. 异常处理
              try {
                  //1. 实例化File类的对象,指明要操作的文件
                  File srcFile = new File("hello");
                  File destFile = new File("hello2.txt");
      
                  //2. 提供具体的流
                  fr = new FileReader(srcFile);
                  fw = new FileWriter(destFile);
      
                  //3. 数据的读入/数据的读出
                  char[] cbuf = new char[5];
                  //记录每次读入到cbuf数组中的每个字符的个数
                  int len;
                  while ((len = fr.read(cbuf)) != -1){
                      //每次写出len个字符
                      fw.write(cbuf,0,len);
                  }
              } catch (IOException e) {
                  e.printStackTrace();
              } finally {
                    //4. 关闭流资源,俩个流资源是并列关系,先关闭哪一个都行
      //            //方式一:使用try-catch-finally
      //            if(fw != null){
      //                try {
      //                    fw.close();
      //                } catch (IOException e) {
      //                    e.printStackTrace();
      //                }finally {
      //                    try {
      //                        fr.close();
      //                    } catch (IOException e) {
      //                        e.printStackTrace();
      //                    }
      //                }
      //            }
                  //方式二:使用两个平行的try-catch
                  if(fw != null){
                      try {
                          fw.close();
                      } catch (IOException e) {
                          e.printStackTrace();
                      }
                  }
                  if(fr != null){
                      try {
                          fr.close();
                      } catch (IOException e) {
                          e.printStackTrace();
                      }
                  }
              }
          }
      }
      
  7. testFileInputOutputStream

    1. 对于文本文件(.txt/.java/.c/.cpp等)使用字符流处理

    2. 对于非文本文件(.doc/.jpge/.mp3等)使用字节流来处理

    3. 使用字节流FileInputStream处理文本文件可能出现乱码

    4. testFileInputOutputStream代码:实现一张图片的复制

      import org.junit.Test;
      
      import java.io.*;
      
      /**
       * @Author: xuehai.XUE
       * @MailBox: xuehai.xue@qq.com
       * @Date: 2021/3/26 14:25
       * @Description:
       */
      public class FileInputOutputStreamTest {
          @Test
          public void testFileInputOutputStream(){
              FileInputStream fis = null;
              FileOutputStream fos = null;
              //5. 异常处理
              try {
                  //1. 实例化File类的对象,指明要操作的文件
                  File srcFile = new File("C:\\Users\\XUE31\\Desktop\\UnlimitedProgress.jpg");
                  File destFile = new File("C:\\Users\\XUE31\\Desktop\\UnlimitedProgress_bak.jpg");
                  //2. 提供具体的流
                  fis = new FileInputStream(srcFile);
                  fos = new FileOutputStream(destFile);
      
                  //3. 数据的读入/写出
                  //节点流中,一般情况下使用长度为1024的字节数组速度最快
                  byte[] buffer = new byte[1024];
                  int len;
                  while((len = fis.read(buffer)) != -1){
                      fos.write(buffer,0,len);
                  }
              } catch (IOException e) {
                  e.printStackTrace();
              } finally {
                  //4. 关闭流资源
                  if(fos != null){
                      try {
                          fos.close();
                      } catch (IOException e) {
                          e.printStackTrace();
                      }
                  }
                  if(fis != null){
                      try {
                          fis.close();
                      } catch (IOException e) {
                          e.printStackTrace();
                      }
                  }
              }
          }
      }
      

      image-20210326160039754

  8. copyFile&testCopyFile使用模板方法设计复制一张图片

    1. 将高度重复的部分抽取出来作为模板,将易变的部分作为参数传入,此处高度重复的部分是对文件的操作,易变的部分是文件的路径

    2. copyFile代码如下

      import org.junit.Test;
      
      import java.io.File;
      import java.io.FileInputStream;
      import java.io.FileOutputStream;
      import java.io.IOException;
      
      /**
       * @Author: xuehai.XUE
       * @MailBox: xuehai.xue@qq.com
       * @Date: 2021/3/26 16:03
       * @Description:
       */
      public class FileInputOutputStreamTest {
      
          /**
           * 复制文件的模板方法
           * @param srcPath 被复制文件的地址
           * @param destPath 复制后文件保存的地址
           */
          public void copyFile(String srcPath,String destPath){
              FileInputStream fis = null;
              FileOutputStream fos = null;
              //4. 异常处理
              try {
                  //1. 使用匿名对象的方式创建File对象,并赋给fis
                  fis = new FileInputStream(new File(srcPath));
                  fos = new FileOutputStream(new File(destPath));
      
                  //2. 读入写出操作
                  //创建字节数组
                  byte[] buffer = new byte[1024];
                  int len;
                  //复制的过程
                  while ((len = fis.read(buffer)) != -1){
                      fos.write(buffer,0,len);
                  }
              } catch (IOException e) {
                  e.printStackTrace();
              } finally {
                  //3. 关闭流资源
                  if(fos != null){
                      try {
                          fos.close();
                      } catch (IOException e) {
                          e.printStackTrace();
                      }
                  }
                  if(fis != null){
                      try {
                          fis.close();
                      } catch (IOException e) {
                          e.printStackTrace();
                      }
                  }
              }
          }
      }
      

      testCopyFile代码如下:

      import org.junit.Test;
      
      import java.io.File;
      import java.io.FileInputStream;
      import java.io.FileOutputStream;
      import java.io.IOException;
      
      /**
       * @Author: xuehai.XUE
       * @MailBox: xuehai.xue@qq.com
       * @Date: 2021/3/26 16:03
       * @Description:
       */
      public class FileInputOutputStreamTest {
          @Test
          public void testCopyFile(){
              //顺便测测整个过程耗费的时间
              long start = System.currentTimeMillis();
              long end;
              String srcPath = "C:\\Users\\XUE31\\Desktop\\UnlimitedProgress.jpg";
              String destPath = "C:\\Users\\XUE31\\Desktop\\UnlimitedProgress_bak1.jpg";
              copyFile(srcPath,destPath);
      
              end = System.currentTimeMillis();
      
              System.out.println("复制的所花费的时间为:" + (end - start) + "ms");//28ms
          }
      }
      
4.处理流(缓冲流)
  1. 缓冲流的作用:提升流的读取、写入的速度;能够提升读取、写入速度的原因是在类的内部提供了一个缓冲区

  2. 处理流就是“套接”在已有流的基础上

  3. testBufferedStream:实现非文本文件的复制

    import org.junit.Test;
    
    import java.io.*;
    
    /**
     * @Author: xuehai.XUE
     * @MailBox: xuehai.xue@qq.com
     * @Date: 2021/3/26 16:35
     * @Description:
     */
    public class BufferedTest {
        @Test
        public void testBufferedStream(){
            BufferedInputStream bis = null;
            BufferedOutputStream bos = null;
            //5. 异常处理
            try {
                //1. 实例化File类对象
                File srcFile = new File("C:\\Users\\XUE31\\Desktop\\UnlimitedProgress.jpg");
                File destFile = new File("C:\\Users\\XUE31\\Desktop\\UnlimitedProgress_bak2.jpg");
    
                //2. 实例化流
                //2.1 实例化节点流
                FileInputStream fis = new FileInputStream(srcFile);
                FileOutputStream fos = new FileOutputStream(destFile);
    
                //2.2 实例化缓冲流
                bis = new BufferedInputStream(fis);
                bos = new BufferedOutputStream(fos);
    
                //3. 复制
                byte[] buffer = new byte[1024];
                int len;
                while ((len = bis.read(buffer)) != -1){
                    bos.write(buffer,0,len);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                //4. 关闭流资源,关闭外层处理流资源时,内层的文件流会自动关闭流资源
                if(bos != null){
                    try {
                        bos.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if(bis != null){
                    try {
                        bis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    
  4. copyFileWithBuffered:使用处理流实现文件复制的模板方法

    import org.junit.Test;
    
    import java.io.*;
    
    /**
     * @Author: xuehai.XUE
     * @MailBox: xuehai.xue@qq.com
     * @Date: 2021/3/26 16:35
     * @Description:
     */
    public class BufferedTest {
        /**
         * 使用Buffered缓冲流实现文件复制的模板方法
         * @param srcPath 被复制文件的地址
         * @param destPath 复制后文件保存的地址
         */
        public void copyFileWithBuffered(String srcPath,String destPath){
            BufferedInputStream bis = null;
            BufferedOutputStream bos = null;
            //4. 异常处理
            try {
                //1. 使用匿名对象的方式创建File对象\FileInputStream或FileOutputStream对象,并分别赋给bis和bos
                bis = new BufferedInputStream(new FileInputStream(new File(srcPath)));
                bos = new BufferedOutputStream(new FileOutputStream(new File(destPath)));
    
                //2. 读入写出操作
                //创建字节数组
                byte[] buffer = new byte[1024];
                int len;
                //复制操作
                while((len = bis.read(buffer)) != -1){
                    bos.write(buffer,0,len);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                //3. 关闭流资源
                if(bos != null){
                    try {
                        bos.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if(bis != null){
                    try {
                        bis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    

    testCopyFileWithBuffered

    import org.junit.Test;
    
    import java.io.*;
    
    /**
     * @Author: xuehai.XUE
     * @MailBox: xuehai.xue@qq.com
     * @Date: 2021/3/26 16:35
     * @Description:
     */
    public class BufferedTest {
        @Test
        public void testCopyFileWithBuffered(){
            //顺便测测整个过程耗费的时间
            long start = System.currentTimeMillis();
            long end;
            String srcPath = "C:\\Users\\XUE31\\Desktop\\UnlimitedProgress.jpg";
            String destPath = "C:\\Users\\XUE31\\Desktop\\UnlimitedProgress_bak3.jpg";
            copyFileWithBuffered(srcPath,destPath);
    
            end = System.currentTimeMillis();
    
            System.out.println("复制的所花费的时间为:" + (end - start) + "ms");//2ms
           }
    }
    
  5. BufferedInputStream继承于FilterInputStream,定义了私有静态变量 DEFALUT_BUFFER_SIZE = 8192;(8192 = 1024 * 8),在调用BufferedInputStream的默认构造器时,就会产生一个长度为8192的缓冲区。

    image-20210326174040507

  6. BufferedInputStream和BufferedOutputStream都有flush()方法,通过手动调用该方法可以刷新缓冲区,但是不建议手动调用,因为两个类在内部都已经调用了这个方法,无需重复调用

    image-20210326174829232

  7. testBufferedReaderBufferWriter

    1. 使用BufferReader和BufferedWriter实现文本文件的复制

    2. BufferedReader和BufferedWriter底层都有哟个默认的defaultCharBufferSize = 8192

    3. testBufferedReaderBufferWriter代码

      import org.junit.Test;
      
      import java.io.*;
      
      /**
       * @Author: xuehai.XUE
       * @MailBox: xuehai.xue@qq.com
       * @Date: 2021/3/26 16:35
       * @Description:
       */
      public class BufferedTest {
      
          @Test
          /** 使用BufferedReader和BufferedWriter实现文本文件的复制 */
          public void testBufferedReaderWriter(){
              BufferedReader br = null;
              BufferedWriter bw = null;
              //4.异常处理
              try {
                  //1. 造对象、造流
                  br = new BufferedReader(new FileReader(new File("hello")));
                  bw = new BufferedWriter(new FileWriter(new File("hello3.txt")));
      
                  //2. 读入写出
      //            //方式一:使用char数组
      //            char[] cbuf = new char[5];
      //            int len;
      //            while ((len = br.read(cbuf)) != -1){
      //                bw.write(cbuf,0,len);
      //            }
                  //方式二:使用String
                  String data;
                  while((data = br.readLine()) != null){
      //                //data中不包含换行符
      //                bw.write(data);
      //                //手动添加换行符
      //                bw.write(data+ "\n");
                      //用方法添加换行
                      bw.newLine();
                  }
              } catch (IOException e) {
                  e.printStackTrace();
              } finally {
                  //3. 关闭流资源
                  if(bw != null){
                      try {
                          bw.close();
                      } catch (IOException e) {
                          e.printStackTrace();
                      }
                  }
                  if(br != null){
                      try {
                          br.close();
                      } catch (IOException e) {
                          e.printStackTrace();
                      }
                  }
              }
          }
      }
      
5.转换流
  1. 转换流提供了在字节流和字符流之间转换的方法,转换流是字符流

  2. JavaAPI提供了两个转换流:

    1. InputStreamReader:将InputStream转换为Reader,即将一个字节的输入流转换为字符的输入流
    2. OutputStreamWriter:将Writer转换为OutputStream,即将一个字符的输出流转换为字节的输出流
  3. 字节流中的数据都是字符时,转换为字符流操作更为高效

  4. 很多时候使用转换流来处理文件乱码的问题。实现编码和解码的功能

  5. 转换流两个类的使用图示:

    image-20210326183303642

  6. 两个类的使用示例:

    import org.junit.Test;
    
    import java.io.*;
    
    /**
     * @Author: xuehai.XUE
     * @MailBox: xuehai.xue@qq.com
     * @Date: 2021/3/26 18:15
     * @Description:
     */
    public class InputStreamReaderTest {
    
        @Test
        /** InputStreamReader的使用,实现了字节的输入流到字符输入流的转换 */
        public void test1(){
            InputStreamReader isr = null;
            try {
                FileInputStream fis = new FileInputStream("hello1.txt");
                //isr的构造器第二个参数不指定字符集的情况下,使用系统默认的字符集
                isr = new InputStreamReader(fis,"UTF-8");
    
                char[] cbuf = new char[20];
                int len;
                while ((len = isr.read(cbuf)) != -1){
                    String str = new String(cbuf,0,len);
                    System.out.print(str);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if(isr != null){
                    try {
                        isr.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    
        @Test
        /** 综合使用InputStreamReader和OutputStreamWriter */
        public void test2(){
            InputStreamReader isr = null;
            OutputStreamWriter osw = null;
            try {
                //1. 实例化Flie对象和相应的流对象
                File file1 = new File("hello1.txt");
                File file2 = new File("hello1_gbk.txt");
    
                FileInputStream fis = new FileInputStream(file1);
                FileOutputStream fos = new FileOutputStream(file2);
    
                isr = new InputStreamReader(fis,"UTF-8");
                osw = new OutputStreamWriter(fos,"gbk");
    
                //2. 读写过程
                char[] cbuf = new char[20];
                int len;
                while((len = isr.read(cbuf)) != -1){
                    osw.write(cbuf,0,len);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                //3. 关闭资源
                if(isr != null){
                    try {
                        isr.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if(osw != null){
                    try {
                        osw.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
    
    
        }
    }
    
6.字符编码
  1. 常见的编码表
    1. ASCII:美国信息交换标准代码,用以一个字节的7位可以表示
    2. ISO8859-1:拉丁码表。欧洲码表,用一个字节的8位表示
    3. GBK2312:中文编码表
    4. GBK:中文编码表,融合了更多的中文字符符号。最多两个字节编码,一个字节表示一个字符时采用0开头,两个字节表示一个字符时,采用1开头
    5. Unicode:国际标准码,融合了大多数字符。为每个字符分配唯一的字符码。所有的文字都用两个字节表示。Unicode不完美,部分字符仅需要一个字节即可,而Unicode定长两字节,耗费大量的内存空间;无法区别两个字节编码的Unicode和一个字节编码的ASCII,若采用GBK同样的方式来表示,则表数范围不够装载所有字符
    6. UTF-8:变长的编码方式,可用1-4个字节来表示一个字符,UTF-8每次8个位传输数据,UTF-16就是每次16个位传输数据;UTF-8采用1个字节表示字符时,开头是0;用两个字节表示字符时,第一个字节开头是110,第二个字节开头是10;用三个字节表示字符时,第一个字节开头是1110,第二、第三个字符开头是10;采用4个字节表示字符时,第一个字节开头是11110,第二、三、四个字节以10开头;无论是几个字节表示,除了开头用于表示几位表字符的位,其余位次用该字符的Unicode编码填充。
7.标准输入、输出流
  1. System.in和System.out分别代表了系统标准的输入和输出设备
  2. 默认的输入设备是:键盘;输出设备是:控制台
  3. System.in的类型是InputStream
  4. System.out的类型是PrintStream,它是OutputStream、FilterOutputStream的子类
  5. 重定向:通过System类的setIn,setOut方法对默认设备进行改变
    1. public static void setIn(InputStream is)
    2. public static void setOut(PrintStream ps)
8.打印流
  1. 实现将基本数据类型的数据格式转换为字符串输出
  2. 打印流:PrintStream和PrintWriter
    1. 提供了一系列重载的print()和println()方法,用于多种数据的类型的输出
    2. PrintStream和PrintWriter的输出不会抛出IOException异常
    3. PrintStream和PrintWriter有自动flush功能
    4. PrintStream打印的所有字符都是用平台默认的字符编码转换为字节,在需要写入字符而不是写入字节的情况下,应该使用PrintWriter类
    5. System.out返回的是PrintStream的实例
9.数据流
  1. 为了方便的操作Java语言的基本数据类型和String的数据,可以使用数据流。
  2. 数据流有两个类:(用于读取和写出基本数据类型、String类的数据)
    1. DataInputStream和DataOutputStream
    2. 分别“套接”在InputStream和OutputStream子类的流上
  3. DataInputStream中的方法
    1. boolean readBoolean()
    2. byte readByte()
    3. char readChar()
    4. float readFloat()
    5. double readDouble()
    6. short readShort()
    7. long readLong()
    8. int readInt()
    9. String readUTF()
    10. void readFully(byte[] b)
  4. DataOutStream中的方法
    1. 同上述的DataInputStream方法类似,将方法名中的read替换为write即可
  5. 读取不同类型的数据的顺序要与当初写入文件时保存的数据顺序一致

image-20210303180846928

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值