java之IO

java之I/O

引入

  • I/O问题是任何语言都无法回避的问题,可以说I/o问题是整个人机交互的核心问题,因为I/O是机器获取和交换信息的主要渠道。大数据时代,I/O问题很突出,经常成为一个方案的技术瓶颈。
  • I/O只是人与机器或者是机器与机器交换数据的手段。

计算机对数据的输入输出

  • 助解图
    在这里插入图片描述
    可以看出所谓输入是外部数据向cpu输入,而输出是CPU将数据输出到我们可见的地方,比如文件,屏幕,而计算机通常是通过流来传递数据

    java I/O

    • 根据走向:分为输入流和输出流
    • 根据处理数据类型:字节流和字符流

    字节流和字符流的解释

    • 字节流可以处理所有类型数据,如MP3、图片、文字、视频等。在java中对应的类都以Stream结尾。
    • 字符流仅能够处理纯文本数据,如txt等。在java中都以Reader和Writer结尾。

    字节,字符,编码的区别?

    • 字节是信息单位。字符是记录信息的符号,如“1”,“a”,“#”等等。
    • 字符集又叫编码,各国有各自不同的编码,比如“GB2312”,汉子标准。

    怎样利用字节输入流和输出流进行文件读写?

    • 输入流

      public static  void fileInputTest(){
              try {
                  FileInputStream fileInputStream= new FileInputStream("C://Users//Timmy//Desktop//1234.txt");
                  byte [] b =new byte[230];
                  while (fileInputStream.read(b) != -1) {
                      fileInputStream.read(b);
                      String s = new String(b, "GB2312");
                      System.out.println(s);
                  }
                  fileInputStream.close();
              } catch (FileNotFoundException e) {
                  e.printStackTrace();
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }
      
    • 输出流

          public static void fileoutputTest(){
              try {
                  FileOutputStream fileOutputStream = new FileOutputStream("C://Users//Timmy//Desktop//1235.txt");
                  String a ="你好,你很靓丽";
                  byte[]b=a.getBytes("GB2312");
                  fileOutputStream.write(b);
                  fileOutputStream.close();
              } catch (FileNotFoundException e) {
                  e.printStackTrace();
              } catch (UnsupportedEncodingException e) {
                  e.printStackTrace();
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }
      

    千万要注意:对于输入流和输出流,使用完之后,一定用各自的close()方法将其关闭;

    怎样利用文件的输入流和输出流实现文件的拷贝?

      public static void picCopy(){
          try {
              FileInputStream fileInputStream =new FileInputStream("C:\\Users\\Timmy\\Desktop\\streamtest\\1234.JPG");
              FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\Timmy\\Desktop\\streamtest\\12345.JPG");
              byte [] b =new byte[60];
              while (fileInputStream.read(b)!=-1){
                   fileOutputStream.write(b);
              }
              fileOutputStream.close();
              fileInputStream.close();
          } catch (FileNotFoundException e) {
              e.printStackTrace();
          } catch (IOException e) {
              e.printStackTrace();
          }
      }
    

    首先说明一下:fo.read(input);返回的是整形,返回的是 从文件中读取数据到数据的字节长度;每次最多读规定数组大小个字节数据,如果没有从文件中读取到数据,则返回-1;如果文件太大,超过定义数组的字节大小,可以采用循环;

    拷贝视频也一样

    通过带有缓冲的字节流来读取数据?

    • 缓冲区

      • 计算机访问外部设备或者文件,要比直接访问内存慢得多。如果我们每次调用read()方法或者writer()方法访问外部设备或文件,cpu就要花在很多时间在等外部相应设备,而不是数据处理。为此,我们开辟一个内存缓冲区的内存区域,程序每次调用read()方法或者writer()方法都是读写在这个缓冲区中。这实际上是牺牲空间来换时间的解决方案。这样cpu的使用率就会大大增加,进而提高整个计算机系统的效率。在字符流操作中,所有的字符都是在内存中形成的,在字符流输出前都将保存在内存对的缓冲区内。
    • 缓冲流

      • 在读写数据时,使用缓冲区的流是缓冲流。这种流一此先将整个缓冲区写满再一次输入或者输出。减少对文件读写次数,提高cpu效率。

      缓冲区和缓冲流存在的原因就是为了提高cpu的效率,减少等带时间,把时间都用到处理数据上。

      比如说,家里盖房子,有一堆砖头要搬在工地100米外,单字节的读取就好比你一个人每次搬一块砖头,从堆砖头的地方搬到工地,这样可定很费时间,然后好的方法就是多叫几个小伙伴帮你一起搬砖头,这样因为人多了,每次可以搬十块砖头,但效率还是很低,这就好比我们的字节/字符数组读写操作;然而聪明的人类会用小推车,每次先搬砖头搬到小车上,再利用小推车运到工地上去,这样你或者你的小伙伴们再从小推车上取砖头是不是方便多了呀!这样效率就会大大提高,缓冲流就好比我们的小推车;给砖头暂时提供一个可存放的空间;

    • 缓冲流分为字节缓冲流和字符缓冲流。

    • 缓冲字节流:BufferInputStream,BufferOutputStream

    如何利用缓冲机制对64视频拷贝进一步优化?

    • 示例代码

          public static void videocopy(){
              try {
                  FileInputStream fileInputStream =new FileInputStream("C:\\Users\\Timmy\\Desktop\\streamtest\\12.mp4");
                  BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
                  FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\Timmy\\Desktop\\streamtest\\13.mp4");
                  BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
                  byte [] b =new byte[50];
                  while (bufferedInputStream.read(b)!=-1){
                      bufferedOutputStream.write(b);
                  }
                  bufferedOutputStream.close();
                  fileOutputStream.close();
                  bufferedInputStream.close();
                  fileInputStream.close();
              } catch (FileNotFoundException e) {
                  e.printStackTrace();
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }
      

    总是现有普通流,再有缓冲流,既然都是流,所以方法一般都一样,只不过内部实现机制不一样;但是,一般缓冲流比普通流处理文件要快得多,比如,都拷贝大约40mb的视频文件,普通流要2054ms,但是缓冲流仅需138ms(两种方案每次读写数组大小一样);

    • 优化
      • 如果将每次读的字节数扩大,那么访问文件的次数变少,那么时间也会相应变少。这也从侧面证实了在这一过程中,把大量的时间都花费在访问文件上了。
      • BufferedInputStream(InputStream in ,int size):可以通过改变缓冲区大小和每次读取字节数组大小来调整。降低磁盘访问次数,延长磁盘寿命。

    java中如何利用字节流进行文件读写?

    • 代码示例

          public static void ReaderInput(){
              try {
                  FileInputStream fileInputStream= new FileInputStream("C://Users//Timmy//Desktop//1234.txt");
                  InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream,"GB2312");
                  char []c =new char[1000];
                  while (inputStreamReader.read(c) != -1) {
                      String s = new String(c);
                      System.out.println(s);
                  }
                  inputStreamReader.close();
                  fileInputStream.close();
              } catch (FileNotFoundException e) {
                  e.printStackTrace();
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }
      
    • 错误示例

      public static void ReaderPicCopy(){
              try {
                  FileInputStream fileInputStream =new FileInputStream("C:\\Users\\Timmy\\Desktop\\streamtest\\1234.JPG");
                  InputStreamReader inputStreamReader =new InputStreamReader(fileInputStream,"GB2312");
                  FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\Timmy\\Desktop\\streamtest\\12345.JPG");
                  OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream,"GB2312");
                  char [] b =new char[60];
                  while (inputStreamReader.read(b)!=-1){
                      outputStreamWriter.write(b);
                  }
                  outputStreamWriter.close();
                  fileOutputStream.close();
                  inputStreamReader.close();
                  fileInputStream.close();
              } catch (FileNotFoundException e) {
                  e.printStackTrace();
              } catch (IOException e) {
                  e.printStackTrace();
              }
              
          }
      

      字符只能处理文本

    如何利用带有缓冲的字符流进行读写数据?

    • 字符流进行读写的时候,有些限制,一些不足之处,比如没有读取行,只能每次读取一个数组的数据,所以有设计了带有缓冲的字符流。并且,减少访问硬盘的次数;其实缓冲区一次性从硬盘提取缓冲区大小的数据量,等向外写出完之后,在从硬盘接着调取剩余的数据;而缓冲区的read等方法,只是从缓冲区往外调取数据,没有真正访问硬盘;这其实也是所有缓冲区意义所在;

    • 示例代码

          public static void ReaderBufferInput(){
              try {
                  FileInputStream fileInputStream= new FileInputStream("C://Users//Timmy//Desktop//1234.txt");
                  InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream,"GB2312");
                  BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
                  FileOutputStream fileOutputStream = new FileOutputStream("C://Users//Timmy//Desktop//12345.txt");
                  OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream,"GB2312");
                  BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);
                  //PrintWriter printWriter =new PrintWriter()
                  char []c =new char[1000];
                  while (bufferedReader.read(c) != -1) {
                      outputStreamWriter.write(c);
                      String s = new String(c);
                      //System.out.println(s);
                  }
                  bufferedWriter.close();
                  outputStreamWriter.close();
                  fileOutputStream.close();
                  bufferedReader.close();
                  inputStreamReader.close();
                  fileInputStream.close();
              } catch (FileNotFoundException e) {
                  e.printStackTrace();
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }
      

      每次读一行

          public static void ReaderBufferInputmodify(){
              try {
                  FileInputStream fileInputStream= new FileInputStream("C://Users//Timmy//Desktop//1234.txt");
                  InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream,"GB2312");
                  BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
                  FileOutputStream fileOutputStream = new FileOutputStream("C://Users//Timmy//Desktop//12345.txt");
                  OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream,"GB2312");
                  BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);
                  //PrintWriter printWriter =new PrintWriter(
                  String line;
                  while ((line=bufferedReader.readLine() )!= null) {
                      outputStreamWriter.write(line);
                     //String s = new String(c);
                      //System.out.println(s);
                  }
                  bufferedWriter.close();
                  outputStreamWriter.close();
                  fileOutputStream.close();
                  bufferedReader.close();
                  inputStreamReader.close();
                  fileInputStream.close();
              } catch (FileNotFoundException e) {
                  e.printStackTrace();
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }
      
      • 结果

        3280 10万以上  aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
        

        由于readline只是按\n分隔符来读,所以读出来的并没有包含\n字符。所以写入的新文件不会有换行。下面进行改进

            public static void ReaderBufferInputmodify(){
                try {
                    FileInputStream fileInputStream= new FileInputStream("C://Users//Timmy//Desktop//1234.txt");
                    InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream,"GB2312");
                    BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
                    FileOutputStream fileOutputStream = new FileOutputStream("C://Users//Timmy//Desktop//12345.txt");
                    OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream,"GB2312");
                   // BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);
                    PrintWriter printWriter = new PrintWriter(outputStreamWriter);
                    //PrintWriter printWriter =new PrintWriter(
                    String line;
                    while ((line=bufferedReader.readLine() )!= null) {
                        printWriter.println(line);
                       //String s = new String(c);
                        //System.out.println(s);
                    }
                    printWriter.close();
                    outputStreamWriter.close();
                    fileOutputStream.close();
                    bufferedReader.close();
                    inputStreamReader.close();
                    fileInputStream.close();
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        
        • 结果

          3280 10万以上  aaaaaaaaaaaaaaaaaaaaaaa
          aaaaaaaaaaaaaaaaaaaaaaaa
          
        • 如上做法是,在读出的不在换行符基础上,定制换行,所以考虑另外一个api–PrintWriter;

        • 有一个注意的地方,最后一次读写,如果缓冲区不被写满,是不会写入或者输出的,那么最后一次缓冲区的内容将会丢失,要用flush方法强制写入。或者初始化时设定参数,new PrintWriter(outputStreamWriter,true);保证每次内容强制输出。

        • Bufferwriter等其他输出api没有就没有对应的功能,所以只能在最后关闭前用flush()方法;

              public static void ReaderBufferInputmodify(){
                  try {
                      FileInputStream fileInputStream= new FileInputStream("C://Users//Timmy//Desktop//1234.txt");
                      InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream,"GB2312");
                      BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
                      FileOutputStream fileOutputStream = new FileOutputStream("C://Users//Timmy//Desktop//12345.txt");
                      OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream,"GB2312");
                     // BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);
                      PrintWriter printWriter = new PrintWriter(outputStreamWriter);
                      //PrintWriter printWriter =new PrintWriter(
                      String line;
                      while ((line=bufferedReader.readLine() )!= null) {
                          printWriter.println(line);
                         //String s = new String(c);
                          //System.out.println(s);
                      }
                      printWriter.flush();
                      printWriter.close();
                      outputStreamWriter.close();
                      fileOutputStream.close();
                      bufferedReader.close();
                      inputStreamReader.close();
                      fileInputStream.close();
                  } catch (FileNotFoundException e) {
                      e.printStackTrace();
                  } catch (IOException e) {
                      e.printStackTrace();
                  }
              }
          

    FileReader和FileWriter?

    • 其操作方法上和上面差不多,此处略去。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值