JAVA深化篇_24—— IO常用流详解(附代码及注释)

常用流详解

文件字节流

FileInputStream通过字节的方式读取文件,适合读取所有类型的文件(图像、视频、文本文件等)。

FileOutputStream 通过字节的方式写数据到文件中,适合所有类型的文件(图像、视频、文本文件等)。

FileInputStream文件输入字节流

public class TestFileInputStream {
  public static void main(String[] args) {
    //使用try-with-resource方式关闭资源。
    //在try中打开资源,不需要在代码中添加finally块关闭资源。
    try(FileInputStream fis = new FileInputStream("d:/a.txt");){
      StringBuilder sb = new StringBuilder();
      int temp=0;
      while((temp = fis.read()) != -1){
        sb.append((char) temp);


       }
      System.out.println(sb);
     }catch(Exception e){
      e.printStackTrace();
     }
   }

FileOutputStream文件输出字节流

public class TestFileOutputStream {
  public static void main(String[] args) {
    String str = "Ou";
    // true表示内容会追加到文件末尾;false表示重写整个文件内容。
    try(FileOutputStream fos = new FileOutputStream("d:/a.txt",true)){
      //将整个字节数组写入到文件中。
      fos.write(str.getBytes());
      //将数据从内存中写入到磁盘中。
      fos.flush();
     }catch (IOException e){
      e.printStackTrace();
     }
   }
}

通过字节缓冲区提高读写效率

通过创建一个指定长度的字节数组作为缓冲区,以此来提高IO流的读写效率。该方式适用于读取较大文件时的缓冲区定义。注意:缓冲区的长度一定是2的整数幂。一般情况下1024长度较为合适。

public class TestFileByteBuffer{
  public static void main(String[] args) {
    long time1 = System.currentTimeMillis();
    copyFile("d:/1.jpg", "d:/2.jpg");
    long time2 = System.currentTimeMillis();
    System.out.println(time2 - time1);
   }


  /**
   *
   * @param src 源文件
   * @param desc 目标文件
   */
  public static void copyFile(String src,String desc){
        //“后开的先关闭!”按照他们被创建顺序的逆序来关闭
    try(FileInputStream fis = new FileInputStream(src);
      FileOutputStream fos = new FileOutputStream(desc)){
      //创建一个缓冲区,提高读写效率
      byte[] buffer = new byte[1024];


      int temp = 0;
      while ((temp = fis.read(buffer)) != -1){
     //将缓存数组中的数据写入文件中,注意:写入的是读取的真实长度;
      fos.write(buffer,0,temp);


      }
      //将数据从内存中写入到磁盘中。
      fos.flush();
    }
    catch (IOException e) {
      e.printStackTrace();
     }
   }
}

注意 在使用字节缓冲区时,我们需要注意:

  • 为了减少对硬盘的读写次数,提高效率,通常设置缓存数组。相应地,读取时使用的方法为:read(byte[] b);写入时的方法为:write(byte[ ] b, int off, int length)
  • 程序中如果遇到多个流,每个流都要单独关闭,防止其中一个流出现异常后导致其他流无法关闭的情况。

缓冲字节流

Java缓冲流本身并不具有IO流的读取与写入功能,只是在别的流(节点流或其他处理流)上加上缓冲功能提高效率,就像是把别的流包装起来一样,因此缓冲流是一种处理流(包装流)。

BufferedInputStream和BufferedOutputStream这两个流是缓冲字节流,通过内部缓存数组来提高操作流的效率。

使用缓冲流实现文件的高效率复制

下面我们通过两种方式(普通文件字节流与缓冲文件字节流)实现一个文件的复制,来体会一下缓冲流的好处。

public class TestFileBufferStream {
  public static void main(String[] args) {
    long time1 = System.currentTimeMillis();
    copyFile("d:/1.jpg","d:/2.jpg");
    long time2 = System.currentTimeMillis();
    System.out.println(time2 - time1);
   }


  public static void copyFile(String source,String destination){
      //实例化节点流
    try(FileInputStream fis = new FileInputStream(source);
      FileOutputStream fos = new FileOutputStream(destination);
      //实例化处理流
      BufferedInputStream bis = new BufferedInputStream(fis);
      BufferedOutputStream bos = new BufferedOutputStream(fos)){


      int temp = 0;
      while ((temp = bis.read()) != -1){
        bos.write(temp);
       }
      bos.flush();


     }catch(IOException e){
      e.printStackTrace();
     }
   }
}

注意

  • 在关闭流时,应该先关闭最外层的包装流,即“后开的先关闭”。
  • 缓存区的大小默认是8192字节,也可以使用其它的构造方法自己指定大小。

文件字符流

前面介绍的文件字节流可以处理所有的文件,如果我们处理的是文本文件,也可以使用文件字符流,它以字符为单位进行操作。

文件字符输入流

public class TestFileReader {
  public static void main(String[] args) {
    //创建文件字符输入流对象
    try(FileReader fr = new FileReader("d:/a.txt")){
      StringBuilder sb = new StringBuilder();
    //读取文件
      int temp = 0;
      while((temp = fr.read()) != -1){
        sb.append((char)temp);
      }
      System.out.println(sb);
     }catch (IOException e){
      e.printStackTrace();
     }
   }
}

文件字符输出流

public class TestFileWriter {
  public static void main(String[] args) {
    //创建文件字符输出流对象
    try(FileWriter fw = new FileWriter("d:/aa.txt")){
      fw.write("您\r\n");
      fw.write("好\r\n");
      fw.flush();
     }catch (IOException e){
      e.printStackTrace();
     }
   }
}

缓冲字符流

BufferedReader/BufferedWriter增加了缓存机制,大大提高了读写文本文件的效率。

字符输入缓冲流

BufferedReader是针对字符输入流的缓冲流对象,提供了更方便的按行读取的方法:readLine(); 在使用字符流读取文本文件时,我们可以使用该方法以行为单位进行读取。

public class TestBufferedReader {
  public static void main(String[] args) {
      //创建文件字符输入流对象
    try(FileReader fr = new FileReader("d:/aa.txt");
      //创建字符缓冲处理流。缓冲区默认大小为8192个字符。
      BufferedReader br = new BufferedReader(fr)){


      //操作流
      String temp = "";
      //readLine():读取一行文本。 
      while((temp = br.readLine()) != null){
        System.out.println(temp);
       }


     }catch(IOException e){
      e.printStackTrace();
     }
   }
}

字符输出缓冲流

BufferedWriter是针对字符输出流的缓冲流对象,在字符输出缓冲流中可以使用newLine();方法实现换行处理。

public class TestBufferedWriter {
  public static void main(String[] args) {
      //创建文件字符输出流对象
    try(FileWriter fw = new FileWriter("d:/sxt.txt");
      //创建字符输出缓冲流对象
      BufferedWriter bw = new BufferedWriter(fw)){
      //操作缓冲流
      bw.write("您好");
      bw.write("您好O");
      //换行
      bw.newLine();
      bw.write("解忧");
      bw.newLine();
      bw.write("学堂");
      bw.flush();
     }catch (IOException e){
      e.printStackTrace();
     }
   }
}

注意

  • readLine()方法是BufferedReader的方法,可以对文本文件进行更加方便的读取操作。
  • newLine()方法BufferedWriter的方法,可以使用newLine()方法换行。

为文件中的内容添加行号

public class TestLineNumber {
  public static void main(String[] args) {
      //创建字符输入缓冲流与文件字符输入流
    try(BufferedReader br = new BufferedReader(new FileReader("d:/s.txt"));
      //创建字符输出缓冲流与文件字符输出流
      BufferedWriter bw = new BufferedWriter(new FileWriter("d:/s2.txt"))){


      String temp ="";
      //定义序号变量
      int i = 1;
      while((temp = br.readLine()) != null){
        //将读取到的内容添加序号,并输出到指定文件中。
        bw.write(i+","+temp);
        //换行处理
        bw.newLine();
        //序号变量累加
        i++;
       }
      //刷新
      bw.flush();
     }catch(IOException e){
      e.printStackTrace();
     }
   }
}

转换流

InputStreamReader/OutputStreamWriter用来实现将字节流转化成字符流。

通过转换流解决乱码

ANSI(American National Standards Institute)美国国家标准协会

public class TestInputStreamReader {
  public static void main(String[] args) {
    //创建文件字节输入流对象
    try(FileInputStream fis = new FileInputStream("d:/t.txt");
      //创建转换流(字节到字符的转换)流对象,并在该对象中指定编码。
      InputStreamReader isr = new InputStreamReader(fis,"gbk")){
      StringBuilder sb = new StringBuilder();
      //操作流对象
      int temp = 0;
      while((temp = isr.read()) != -1){
        sb.append((char) temp);
       }
      System.out.println(sb);
     }catch(IOException e){
      e.printStackTrace();
     }
   }
}

通过字节流读取文本文件并添加行号

public class TestLineNumber2 {
  public static void main(String[] args) {
      //创建字符输入缓冲流、输入字节到字符转换流、文件字节输入流对象
    try(BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("d:/sxt.txt")));
      //创建字符输出缓冲流、输出字符到字节转换流、文件字节输出流对象
      BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("d:/sxt4.txt")))){


      //操作流
      String temp = "";
      //序号变量
      int i = 1;
      //按照行读取
      while((temp = br.readLine()) != null){
        bw.write(i+","+temp);
        //换行
        bw.newLine();
        //序号累加
        i++;
       }
      //刷新
      bw.flush();
     }catch(IOException e){
      e.printStackTrace();
     }
   }
}

通过转换流实现键盘输入屏幕输出

System.in是字节流对象,代表键盘的输入。

System.out是字节流对象,代表输出到屏幕。

public class TestKeyboardInput {
  public static void main(String[] args) {
      //创建键盘输入相关流对象
    try(BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
      //创建向屏幕输出相关流对象
      BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out))){


      while(true){
        bw.write("请输入:");
        bw.flush();
        //获取键盘输入的字符串
        String input = br.readLine();
        //判断输入的内容是否含有退出关键字。
        if("exit".equals(input) || "quit".equals(input)){
          bw.write("Bye Bye !");
          bw.flush();
          break;
         }
        //将读取到键盘输入的字符串,输出到屏幕。
        bw.write("您输入的是:"+input);
        bw.newLine();
        bw.flush();
       }
     }catch(IOException e){
      e.printStackTrace();
     }
   }
}

通过转换流实现键盘输入屏幕输出

import java.io.*;


public class TestConvertStream {
    public static void main(String[] args) {
        // 创建字符输入和输出流:使用转换流将字节流转换成字符流
        BufferedReader br = null;
        BufferedWriter bw = null;
        try {
            br = new BufferedReader(new InputStreamReader(System.in));
            bw = new BufferedWriter(new OutputStreamWriter(System.out));
            // 使用字符输入和输出流
            String str = br.readLine();
            // 一直读取,直到用户输入了exit为止
            while (!"exit".equals(str)) {
                // 写到控制台
                bw.write(str);
                bw.newLine();// 写一行后换行
                bw.flush();// 手动刷新
                // 再读一行
                str = br.readLine();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭字符输入和输出流
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bw != null) {
                try {
                    bw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

字符输出流

在Java的IO流中专门提供了用于字符输出的流对象PrintWriter。该对象具有自动行刷新缓冲字符输出流,特点是可以按行写出字符串,并且可通过println();方法实现自动换行。

public class TestPrintWriter {
  public static void main(String[] args) {
    //创建字符输出流对象
    try(PrintWriter pw = new PrintWriter("d:/s.txt")){
      //调用不带换行方法完成内容的输出
      pw.print("abc");
      pw.print("def");
      //调用带有自动换行方法完成内容的输出
      pw.println("O");
      pw.println("s");
      pw.flush();
     }catch(IOException e){
      e.printStackTrace();
     }
   }
}

通过字符输出流添加行号

public class TestLineNumber3 {
  public static void main(String[] args) {
    //创建字符输入缓冲流对象与文件字符输入流对象
    try(BufferedReader br = new BufferedReader(new FileReader("d:/s.txt"));
      //创建字符输出流对象
      PrintWriter pw = new PrintWriter("d:/s.txt")){
      //操作流
      String temp = "";
      //定义序号变量
      int i = 1;
      while((temp = br.readLine()) != null){
        pw.println(i+","+temp);
        //序号累加
        i++;
       }
      //刷新
      pw.flush();
     }catch(IOException e){
      e.printStackTrace();
     }
   }
}

你可能感兴趣的:(JAVA,基础深化和提高,java,开发语言)