学习Java之day26

1. 流的概述

一、流的分类

1.操作数据单位:字节流、字符流

2.数据的流向:输入流、输出流

3.流的角色:节点流、处理流

二、流的体系结构 抽象基类 节点流(文件流) 缓冲流(处理流的一种) InputStream FileInputStream BufferedInputStream OutputStream FileOutputSream BufferedOutputStream Reader FileReader BufferedReader Wirter FileWirter BufferedWirter

 public static void main(String[] args) {
       File file1 = new File("hello.txt");//相教于当前工程
       System.out.println(file1.getAbsolutePath());//E:\java\workspace\JavaSenior\hello.txt

       File file2 = new File("day09\\hello.txt");
       System.out.println(file2.getAbsolutePath());//E:\java\workspace\JavaSenior\day09\hello.txt
  }


   /*
   将day09下的hello.txt文件内容读入程序中,并输出到控制台
   说明:
       1.对read()的理解:返回读入的一个字符。读到文件的末尾返回-1
       2.异常的处理:为了保证流资源的及时关闭。需要使用try-catch-finally处理
       3.读入的文件一定要存在,不然会报FileNotFoundException
    */
   @Test
   public void testFileReader() {
       FileReader fr = null;
       try {
           //1.实例化File类的对象,指明要操作的文件
           File file = new File("hello.txt");

           //2.提供具体的流
           fr = new FileReader(file);

           //3.数据的读入
           //方式一:
//       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 {
           //4.流的关闭
           if (fr != null) {
               try {
                   fr.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }
          }
      }

  }

   //对read()方法的操作升级,使用重载的方法
   @Test public void testFileReader1() {
       FileReader fr = null;
       try {
           //1.实例化File对象,获取到需要操作的文件
           File file = new File("hello.txt");
           //2.提供具体的流
           fr = new FileReader(file);

           //3.对数据的操作
           char[] cbuf = new char[5];
           int len;
           while ((len = fr.read(cbuf)) != -1){
               //方式一:
               //错误的写法
   //           for(int i=0; i<cbuf.length; i++){
   //               System.out.print(cbuf[i]);
   //           }

            /* 正确的写法
             for(int i=0; i<len; i++){
                   System.out.print(cbuf[i]);
               }*/


               //方式二:
               //错误的写法
               //String str = new String(cbuf);
               //System.out.print(str);

               String str1 = new String(cbuf, 0,len);
               System.out.print(str1);

          }
           //4.关闭流资源
      } catch (IOException e) {
           e.printStackTrace();
      } finally {
           if(fr != null){
               try {
                   fr.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }
          }

      }


  }

   /*
   从内存中写出数据到硬盘的文件中

   说明:
       1.输出操作,对应的文件可以不存在。不会报FileNotFoundException
       2.
           File对应的硬盘中的文件如果不存在,在输出的过程中,会自动创建此文件。
           File对应的硬盘中的文件如果存在:
               如果流使用的构造器是:FileWriter(file,false) / FileWriter(file):对原有文件的覆盖
               如果流使用的构造器是:FileWriter(file,true):不会对原有文件覆盖,而是在原有文件基础上追加内容

    */
   @Test
   public void testFileWriter() {
       FileWriter fw = null;
       try {
           //1.实例化File类的对象,指明要操作的文件
           File file = new File("dest.txt");

           //2.提供具体的流
           fw = new FileWriter(file,true);


           //3.对文件进行写入操作
           fw.write("abc");
           fw.write("hellowrold");
      } catch (IOException e) {
           e.printStackTrace();
      } finally {
           if(fw != null){
               //4.流资源的关闭
               try {
                   fw.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }
          }
      }

  }

   @Test
   public void testFileReaderFileWriter() {
       FileReader fr = null;
       FileWriter fw = null;
       try {
           //1.创建File类的对象,指明读入和写出的文件
           File srcFile = new File("hello.txt");
           File destFile = new File("hello2.txt");

           //不能使用字符流来处理图片等字节数据
//           File srcFile = new File("爱情与友情.jpg");
//           File destFile = new File("爱情与友情1.jpg");


           //2.创建输入流和输出流的对象
           fr = new FileReader(srcFile);
           fw = new FileWriter(destFile);


           //3.数据的读入和写出操作
           char[] cbuf = new char[5];
           int len;//记录每次读入到cbuf数组中的字符的个数
           while((len = fr.read(cbuf)) != -1){
               //每次写出len个字符
               fw.write(cbuf,0,len);

          }
      } catch (IOException e) {
           e.printStackTrace();
      } finally {
           //4.关闭流资源
           //方式一:
//           try {
//               if(fw != null)
//                   fw.close();
//           } catch (IOException e) {
//               e.printStackTrace();
//           }finally{
//               try {
//                   if(fr != null)
//                       fr.close();
//               } catch (IOException e) {
//                   e.printStackTrace();
//               }
//           }
           //方式二:
           try {
               if(fw != null)
                   fw.close();
          } catch (IOException e) {
               e.printStackTrace();
          }

           try {
               if(fr != null)
                   fr.close();
          } catch (IOException e) {
               e.printStackTrace();
          }

      }

  }

 

2. FileInputStream和FileOutputStream的使用

测试FileInputStream和FileOutputStream的使用
结论:
1. 对于文本文件(.txt,.java,.c,.cpp),使用字符流处理
2. 对于非文本文件(.jpg,.mp3,.mp4,.avi,.doc,.ppt,...),使用字节流处理
  //使用字节流FileInputStream处理文本文件,可能出现乱码。
   @Test
   public void testFileInputStream() {
       FileInputStream fis = null;
       try {
           //1. 造文件
           File file = new File("hello.txt");

           //2.造流
           fis = new FileInputStream(file);

           //3.读数据
           byte[] buffer = new byte[5];
           int len;//记录每次读取的字节的个数
           while((len = fis.read(buffer)) != -1){

               String str = new String(buffer,0,len);
               System.out.print(str);

          }
      } catch (IOException e) {
           e.printStackTrace();
      } finally {
           if(fis != null){
               //4.关闭资源
               try {
                   fis.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }

          }
      }

  }

   /*
   实现对图片的复制操作
    */
   @Test
   public void testFileInputOutputStream() {
       FileInputStream fis = null;
       FileOutputStream fos = null;
       try {
           //
           File srcFile = new File("爱情与友情.jpg");
           File destFile = new File("爱情与友情2.jpg");

           //
           fis = new FileInputStream(srcFile);
           fos = new FileOutputStream(destFile);

           //复制的过程
           byte[] buffer = new byte[5];
           int len;
           while((len = fis.read(buffer)) != -1){
               fos.write(buffer,0,len);
          }

      } catch (IOException e) {
           e.printStackTrace();
      } finally {
           if(fos != null){
               //
               try {
                   fos.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }
          }
           if(fis != null){
               try {
                   fis.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }

          }
      }

  }

   //指定路径下文件的复制
   public void copyFile(String srcPath,String destPath){
       FileInputStream fis = null;
       FileOutputStream fos = null;
       try {
           //
           File srcFile = new File(srcPath);
           File destFile = new File(destPath);

           //
           fis = new FileInputStream(srcFile);
           fos = new FileOutputStream(destFile);

           //复制的过程
           byte[] buffer = new byte[1024];
           int len;
           while((len = fis.read(buffer)) != -1){
               fos.write(buffer,0,len);
          }

      } catch (IOException e) {
           e.printStackTrace();
      } finally {
           if(fos != null){
               //
               try {
                   fos.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }
          }
           if(fis != null){
               try {
                   fis.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }

          }
      }


  }

   @Test
   public void testCopyFile(){

       long start = System.currentTimeMillis();

       String srcPath = "C:\\Users\\Administrator\\Desktop\\01-视频.avi";
       String destPath = "C:\\Users\\Administrator\\Desktop\\02-视频.avi";


//       String srcPath = "hello.txt";
//       String destPath = "hello3.txt";

       copyFile(srcPath,destPath);


       long end = System.currentTimeMillis();

       System.out.println("复制操作花费的时间为:" + (end - start));//618

  }

3.处理流之一:缓冲流的使用

1.缓冲流: BufferedInputStream BufferedOutputStream BufferedReader BufferedWriter

2.作用:提供流的读取、写入的速度 提高读写速度的原因:内部提供了一个缓冲区

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

/*
 实现非文本文件的复制
  */
   @Test
   public void BufferedStreamTest() throws FileNotFoundException {
       BufferedInputStream bis = null;
       BufferedOutputStream bos = null;

       try {
           //1.造文件
           File srcFile = new File("爱情与友情.jpg");
           File destFile = new File("爱情与友情3.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[10];
           int len;
           while((len = bis.read(buffer)) != -1){
               bos.write(buffer,0,len);

//               bos.flush();//刷新缓冲区

          }
      } 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();
              }

          }
           //说明:关闭外层流的同时,内层流也会自动的进行关闭。关于内层流的关闭,我们可以省略.
//       fos.close();
//       fis.close();
      }



  }

   //实现文件复制的方法
   public void copyFileWithBuffered(String srcPath,String destPath){
       BufferedInputStream bis = null;
       BufferedOutputStream bos = null;

       try {
           //1.造文件
           File srcFile = new File(srcPath);
           File destFile = new File(destPath);
           //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();
              }

          }
           //说明:关闭外层流的同时,内层流也会自动的进行关闭。关于内层流的关闭,我们可以省略.
//       fos.close();
//       fis.close();
      }
  }

   @Test
   public void testCopyFileWithBuffered(){
       long start = System.currentTimeMillis();

       String srcPath = "C:\\Users\\Administrator\\Desktop\\01-视频.avi";
       String destPath = "C:\\Users\\Administrator\\Desktop\\03-视频.avi";


       copyFileWithBuffered(srcPath,destPath);


       long end = System.currentTimeMillis();

       System.out.println("复制操作花费的时间为:" + (end - start));//618 - 176
  }


   /*
   使用BufferedReader和BufferedWriter实现文本文件的复制

    */
   @Test
   public void testBufferedReaderBufferedWriter(){
       BufferedReader br = null;
       BufferedWriter bw = null;
       try {
           //创建文件和相应的流
           br = new BufferedReader(new FileReader(new File("dbcp.txt")));
           bw = new BufferedWriter(new FileWriter(new File("dbcp1.txt")));

           //读写操作
           //方式一:使用char[]数组
//           char[] cbuf = new char[1024];
//           int len;
//           while((len = br.read(cbuf)) != -1){
//               bw.write(cbuf,0,len);
//   //           bw.flush();
//           }

           //方式二:使用String
           String data;
           while((data = br.readLine()) != null){
               //方法一:
//               bw.write(data + "\n");//data中不包含换行符
               //方法二:
               bw.write(data);//data中不包含换行符
               bw.newLine();//提供换行的操作

          }


      } catch (IOException e) {
           e.printStackTrace();
      } finally {
           //关闭资源
           if(bw != null){

               try {
                   bw.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }
          }
           if(br != null){
               try {
                   br.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }

          }
      }

  }

4. 处理流之二:转换流的使用

1.转换流:属于字符流 InputStreamReader:将一个字节的输入流转换为字符的输入流 OutputStreamWriter:将一个字符的输出流转换为字节的输出流

2.作用:提供字节流与字符流之间的转换

  1. 解码:字节、字节数组 --->字符数组、字符串 编码:字符数组、字符串 ---> 字节、字节数组

4.字符集 ASCII:美国标准信息交换码。 用一个字节的7位可以表示。 ISO8859-1:拉丁码表。欧洲码表 用一个字节的8位表示。 GB2312:中国的中文编码表。最多两个字节编码所有字符 GBK:中国的中文编码表升级,融合了更多的中文文字符号。最多两个字节编码 Unicode:国际标准码,融合了目前人类使用的所有字符。为每个字符分配唯一的字符码。所有的文字都用两个字节来表示。 UTF-8:变长的编码方式,可用1-4个字节来表示一个字符。

 


/*
  此时处理异常的话,仍然应该使用try-catch-finally
  InputStreamReader的使用,实现字节的输入流到字符的输入流的转换
   */
   @Test
   public void test1() throws IOException {

       FileInputStream fis = new FileInputStream("dbcp.txt");
//       InputStreamReader isr = new InputStreamReader(fis);//使用系统默认的字符集
       //参数2指明了字符集,具体使用哪个字符集,取决于文件dbcp.txt保存时使用的字符集
       InputStreamReader 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);
      }

       isr.close();

  }

   /*
   此时处理异常的话,仍然应该使用try-catch-finally

   综合使用InputStreamReader和OutputStreamWriter
    */
   @Test
   public void test2() throws Exception {
       //1.造文件、造流
       File file1 = new File("dbcp.txt");
       File file2 = new File("dbcp_gbk.txt");

       FileInputStream fis = new FileInputStream(file1);
       FileOutputStream fos = new FileOutputStream(file2);

       InputStreamReader isr = new InputStreamReader(fis,"utf-8");
       OutputStreamWriter osw = new OutputStreamWriter(fos,"gbk");

       //2.读写过程
       char[] cbuf = new char[20];
       int len;
       while((len = isr.read(cbuf)) != -1){
           osw.write(cbuf,0,len);
      }

       //3.关闭资源
       isr.close();
       osw.close();


  }

5. 其他流的使用

1.标准的输入、输出流 2.打印流 3.数据流

 

  /*
 1.标准的输入、输出流
 1.1
 System.in:标准的输入流,默认从键盘输入
 System.out:标准的输出流,默认从控制台输出
 1.2
 System类的setIn(InputStream is) / setOut(PrintStream ps)方式重新指定输入和输出的流。

 1.3练习:
 从键盘输入字符串,要求将读取到的整行字符串转成大写输出。然后继续进行输入操作,
 直至当输入“e”或者“exit”时,退出程序。

 方法一:使用Scanner实现,调用next()返回一个字符串
 方法二:使用System.in实现。System.in ---> 转换流 ---> BufferedReader的readLine()

  */
   public static void main(String[] args) {
       BufferedReader br = null;
       try {
           InputStreamReader isr = new InputStreamReader(System.in);
           br = new BufferedReader(isr);

           while (true) {
               System.out.println("请输入字符串:");
               String data = br.readLine();
               if ("e".equalsIgnoreCase(data) || "exit".equalsIgnoreCase(data)) {
                   System.out.println("程序结束");
                   break;
              }

               String upperCase = data.toUpperCase();
               System.out.println(upperCase);

          }
      } catch (IOException e) {
           e.printStackTrace();
      } finally {
           if (br != null) {
               try {
                   br.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }

          }
      }
  }

   /*
   2. 打印流:PrintStream 和PrintWriter

   2.1 提供了一系列重载的print() 和 println()
   2.2 练习:



    */

   @Test
   public void test2() {
       PrintStream ps = null;
       try {
           FileOutputStream fos = new FileOutputStream(new File("D:\\IO\\text.txt"));
           // 创建打印输出流,设置为自动刷新模式(写入换行符或字节 '\n' 时都会刷新输出缓冲区)
           ps = new PrintStream(fos, true);
           if (ps != null) {// 把标准输出流(控制台输出)改成文件
               System.setOut(ps);
          }


           for (int i = 0; i <= 255; i++) { // 输出ASCII字符
               System.out.print((char) i);
               if (i % 50 == 0) { // 每50个数据一行
                   System.out.println(); // 换行
              }
          }


      } catch (FileNotFoundException e) {
           e.printStackTrace();
      } finally {
           if (ps != null) {
               ps.close();
          }
      }

  }

   /*
   3. 数据流
   3.1 DataInputStream 和 DataOutputStream
   3.2 作用:用于读取或写出基本数据类型的变量或字符串

   练习:将内存中的字符串、基本数据类型的变量写出到文件中。

   注意:处理异常的话,仍然应该使用try-catch-finally.
    */
   @Test
   public void test3() throws IOException {
       //1.
       DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt"));
       //2.
       dos.writeUTF("刘建辰");
       dos.flush();//刷新操作,将内存中的数据写入文件
       dos.writeInt(23);
       dos.flush();
       dos.writeBoolean(true);
       dos.flush();
       //3.
       dos.close();


  }
   /*
   将文件中存储的基本数据类型变量和字符串读取到内存中,保存在变量中。

   注意点:读取不同类型的数据的顺序要与当初写入文件时,保存的数据的顺序一致!

    */
   @Test
   public void test4() throws IOException {
       //1.
       DataInputStream dis = new DataInputStream(new FileInputStream("data.txt"));
       //2.
       String name = dis.readUTF();
       int age = dis.readInt();
       boolean isMale = dis.readBoolean();

       System.out.println("name = " + name);
       System.out.println("age = " + age);
       System.out.println("isMale = " + isMale);

       //3.
       dis.close();

  }

 

posted @ 2022-01-18 17:04  天覆者  阅读(141)  评论(0)    收藏  举报