java中IO流详细解释?

IO概念

IO流用来处理设备之间的数据传输,Java对数据的操作是通过流的方式 Java用于操作流的类都在IO包中,

流按流向分为两种:

输入流(读取数据) 输出流(写数据)

流按操作类型分为两种:

字节流 : 字节流可以操作任何数据,因为在计算机中任何数据都是以字节的形式存储的 字符流 : 字符流只能操作纯字符数据,比较方便。

常用的IO流类

字节流的抽象父类

InputStream OutputStream

字符流的抽象父类:

Reader Writer

InputStream & FileInputStream 文件输入流

InputStream是抽象类,表示字节输入流。

直接已知子类: ●AudioInputStream ●ByteArrayInputStream ●FileInputStream(学习文件输入流) ●FilterInputStream ●ObjectInputStream ●PipedInputStream ●SequenceInputStream ●StringBufferInputStream

FileInputStream 文件输入流

概述

FileInputStream 从文件系统中的某个文件中获得输入字节。FileInputStream 用于读取诸如图像数据之类的原始字节流。要读取字符流,请考虑使用 FileReader

构造方法

FileInputStream(File file) FileInputStream(String name)

成员方法

int read() 从此输入流中读取一个数据字节。

案例:读取一个txt文件数据(方法一)

知识点

  • 1.FileInputStream用于读取文件数据,在构造方法中传入文件对象
  • 2.构造方法,有可能抛出文件找不到的异常
  • 3.read方法是每次读取一个字节的数据,把字节转成int返回
    • 读取数据也会抛出异常,比如突然文件某部份数据损坏了
    • 读取的数据是文件编码的表值(ascii,GBK,unicode)
    • ascii是包含在GBK或者unicode中的
    • 如果读取数据到最后,会返回一个-1(代表读完数据了)
  • 4.文件不用后,要关闭输入流,避免占用资源
    package lesson10;    
   import java.io.File;    import java.io.FileInputStream;    import java.io.FileNotFoundException;    import java.io.IOException;    
   /**
    * 读取txt文件内容
    * 1.通过FileInputStream来读取txt文件内容
    * 2.读取内容通过read方法,
    *   》read方法每次读文件1个字节(byte),把byte转成int返回
         》当读到后的时候,返回-1,-1表示读取文件结束
      3.当读完文件后,这个输入流要关闭,释放资源
    *
    */
   public class Demo01 {
   
       public static void main(String[] args) throws IOException {            //FileNotFoundException fnfe;
   
           //案例:读取txt文件内容
           //1.创建一个文件对象
           File file = new File("a.txt");            
           //2.创建一个文件输入流【读取文件数据】对象
           FileInputStream fis1 = new FileInputStream(file);            
           //再创建一个文件输入 流对象
           FileInputStream fis2 = new FileInputStream("b.txt");            
           //3.读取a.txt的数据
           /**
            * 1.read方法每次读文件1个字节(byte),把byte转成int返回
            * 2.当读到后的时候,返回-1,-1读取文件结束
            */
           System.out.println(fis1.read());
           System.out.println(fis1.read());
           System.out.println(fis1.read());
           System.out.println(fis1.read());            
           //4.关闭流
           fis1.close();
           fis2.close();
   
       }
   }

案例:读取一个txt文件数据(方法二)

//1.创建一个文件对象File file = new File("abc.txt");
System.out.println(file.getAbsolutePath());                //2.创建一个文件输入流FileInputStream inputStream = new FileInputStream(file);        int b;//while循环里,每次读取字节赋值给bwhile((b = inputStream.read()) != -1){
System.out.println(b);
}

面试题:read()方法读取的是一个字节,为什么返回是int,而不是byte ?

因为字节输入流可以操作任意类型的文件,比如图片音频等,这些文件底层都是以二进制形式的存储的,如果每次读取都返回byte,有可能在读到中间的时候遇到111111111 那么这11111111是byte类型的-1,我们的程序是遇到-1就会停止不读了,后面的数据就读不到了,所以在读取的时候用int类型接收,如果11111111会在其前面补上 24个0凑足4个字节,那么byte类型的-1就变成int类型的255了这样可以保证整个数据读完,而结束标记的-1就是int类型


image


package lesson12;public class Demo01 {   public static void main(String[] args) {        //面试题:read()方法读取的是一个字节,为什么返回是int,而不是byte ?
       //如果使用FileInputStream读取图片数据
       /**
        * 00010111 00010111 00010111 00010111
        * 00010111 11111111 00010111 00010111
        *
        * byte:11111111 表示的-1
        * int:00000000 00000000 00000000 11111111  byte转成int 补0 了不是-1   因此往后读数据
        *
        * 为什么11111111是表示-1?
        * 因为计算机是以补码的方式计算
        * 补码: 11111111 (-1)
        * 反码: 11111110
        * 原码:  10000001
        *
        * 假如使用FileInputStream读取图片的时候,
        * 图片中间有一段数据刚好是 11111111,这八个一表示的-1,用byte接收
        * java程序如果读取的是-1,后面的数据就不读取
        * 如果把8个1转成int,那就是00000000 00000000 00000000 11111111,这个表示255,
        * 就不是-1,归避后面数据没有读取问题
        *
        */
   }
}

OutputStream & FileOutputStream 文件输出流

  • 文件输出流是用于将数据写入 File 的输出流。
  • FileOutputStream 用于写入诸如图像数据之类的原始字节的流。
  • 查看文档的构造方法和成员方法
  • 案例:往一个abc.txt文件写数据(知识点)
    • new FileOutputStream(file)这种构造方法,会把以前的内容都删除
    • new FileOutputStream(file,true);这种构造方法能追加内容
    • FileNotFoundException是IOException的子类
    • write(int b),写数据
   package lesson13;    
   import java.io.File;    import java.io.FileOutputStream;    import java.io.IOException;    import java.io.OutputStream;    
   public class Demo01 {    
       public static void main(String[] args) throws IOException {            // TODO Auto-generated method stub
   
   /*      FileOutputStream:表示文件输出流,用于往文件写内容
    *      
    *      构造方法
    *      FileOutputStream(String name)
    *      FileOutputStream(File file)
    *      
    *      方法
    *      write(int b);//每次写一个字节
    *      write(byte[] b) ;//一次写多个字节
    * */
           
           //案例:往b.txt 写个内容
           //1.创建文件输出流对象
           //FileOutputStream fos = new FileOutputStream("b.txt");
           OutputStream fos = new FileOutputStream("b.txt");//多态写法
           
           //2.写数据
   //      fos.write(97);//a
   //      fos.write(98);//b
   //      fos.write(99);//c
           
           //一次性写多个字节
           byte[] bytes = {97,98,99,100,101};
           fos.write(bytes);            //3.关闭流
           fos.close();
       }
   
   }

案例:拷贝图片和音频

  • 原理,使用输入流读取数据,使用输出流写数据
  • 画图讲原理和性能 每次都读一次字节,太慢,效率太低

image


package lesson14;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;public class Demo01 {    public static void main(String[] args) throws IOException {        
       //案例:拷贝图片
       /**
        * 目的:结合输入流和输出流使用
        *
        * 图片路径:C:\Users\10301\Desktop\a\cm.jpg
        */
       
       //1.先创建输入流对象和输出流对象
       FileInputStream fis = new FileInputStream("C:/Users/10301/Desktop/a/cm.jpg");
       FileOutputStream fos = new FileOutputStream("C:/Users/10301/Desktop/a/cm2.jpg");        
       //2.通过输入流读取图片的数据
       int b = 0;        while( (b = fis.read()) != -1){            //3.通过输出流写入图片数据
           fos.write(b);
       }        
       //4.关闭流
       fos.close();
       fis.close();
       System.out.println("图片拷贝成功");
   }
}

字节数组拷贝之available()方法

package lesson01;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;public class Demo01 {    public static void main(String[] args) throws IOException {        //案例:拷贝图片【优化一、这种方式在大文件下不建议使用】
       /**
        * 前面拷贝图片问题:每次只读一个字节,写入的时候也是一个字节一个字节写
        *                  如果有10W个字节,就要读10W次,写10W次
        *
        * 字节数组拷贝之available()方法
        */
       //1.文件输入流
       FileInputStream fis = new FileInputStream("C:/Users/10301/Desktop/a/cm.jpg");        int size = fis.available();//是返回文件的长度【字节为单位】
       System.out.println("文件的大小:" + size);        
       //2.现在一次读文件大小的字节
       //2.1定义一个字节数组
       byte[] bytes = new byte[size];//相当于现在是一个空杯子
       //2.2 把数据读到字节数组中
       int r = fis.read(bytes);//这个方法的返回值读取到的实际长度
       System.out.println("r:" + r);        
       //3.把字节数组一次性写入到文件
       //3.1 输出流
       FileOutputStream fos = new FileOutputStream("C:/Users/10301/Desktop/a/cm-副本.jpg");        //3.2 写数据
       fos.write(bytes);        
       //4.关闭流
       fis.close();
       fos.close();
   }
}

案例:正确的拷贝文件的方法(杯子思想、缓冲思想)

1.输入流读取数据的方法: read(byte[] b) 读取指定字节数的数据 2.输出流写数据的方法: write(byte[] b) write(byte[] b, int off, int len)写出有效的字节个数


image


package lesson02;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;/**
* 杯子思想,缓冲思想
* @author gyf
*
*/public class Demo01 {    public static void main(String[] args) throws IOException {        //案例:拷贝图片【优化二、这种方式开发中建议经常使用】
       /**
        * 1.每次只读一个字节,又觉得太慢
        * 2.一次性读一个文件的所有数据,又怕内存装不下
        *   内存只有2G,视频3G,这样就会内存溢出
        *
        * 3.最终解决方法:折中,定义每次读8KB
        *
        */
       
       //1.输入流
       FileInputStream fis = new FileInputStream("C:/Users/10301/Desktop/a/cm.jpg");        //2.输出流
       FileOutputStream fos = new FileOutputStream("C:/Users/10301/Desktop/a/cm-副本2.jpg");        
       //3.定义个8kb字节数组,也叫缓冲区流
       byte[] bytes =  new byte[1024 * 8];        
       int len = 0;        int i = 0;        while( (len = fis.read(bytes)) != -1){
           i++;            //4.写入文件
           fos.write(bytes,0,len);
       }
       
       System.out.println("读取的次数:" + i);        
       //5.关闭流
       fis.close();
       fos.close();
   }
}

BufferedInputStream和BufferOutputStream

  • 这两个流是内置了缓冲区流,也就是说内部有一个 字节数组
  • 缓冲思想 字节流一次读写一个数组的速度明显比一次读写一个字节的速度快很多, java本身在设计的时候,加入了数组这样的缓冲区效果, 也考虑到了这样的设计思想(装饰设计模式后面讲解),所以提供了字节缓冲区流
  • BufferedInputStream BufferedInputStream内置了一个缓冲区(数组) 从BufferedInputStream中读取一个字节时 BufferedInputStream会一次性从文件中读取8192个(8Kb), 存在缓冲区中, 返回给程序 程序再次读取时, 就不用找文件了, 直接从缓冲区中获取 直到缓冲区中所有的都被使用过, 才重新从文件中读取8192个
  • BufferedOutputStream BufferedOutputStream也内置了一个缓冲区(数组) 程序向流中写出字节时, 不会直接写到文件, 先写到缓冲区中 直到缓冲区写满, BufferedOutputStream才会把缓冲区中的数据一次性写到文件里

案例:使用缓冲输入输出流拷贝文件


image


package lesson03;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;public class Demo01 {    public static void main(String[] args) throws IOException {        // TODO Auto-generated method stub       //1.创建文件输入流
       FileInputStream fis = new FileInputStream("C:/Users/10301/Desktop/a/ghsy.mp3");        
       //2.创建文件输出流
       FileOutputStream fos = new FileOutputStream("C:/Users/10301/Desktop/a/ghsy-副本.mp3");        
       //3.输入流读数据、输出流写数据
       int b = 0;        while( (b = fis.read()) != -1){
           fos.write(b);
       }        
       //4.关流
       fis.close();
       fos.close();
       
       System.out.println("音频拷贝完成...");
       
   }    private static void test1() throws FileNotFoundException, IOException {        /*  BufferedInputStream和BufferedOutputStream
           >这两个流是内置了缓冲区流,也就是说内部有一个字节数组
           >这个两个类没有前面我们写的好用,因为它内部每次读8kb字节,如果想读80kb,没办法
   */
           //案例:拷贝音频文件
           //1.创建缓冲输入流
           FileInputStream fis = new FileInputStream("C:/Users/10301/Desktop/a/ghsy.mp3");
           BufferedInputStream bis = new BufferedInputStream(fis);            
           //2.创建缓冲输出流
           FileOutputStream fos = new FileOutputStream("C:/Users/10301/Desktop/a/ghsy-副本.mp3");
           BufferedOutputStream bos =new BufferedOutputStream(fos);            
           //3.输入流读数据、输出流写数据
           
           int b = 0;            // bis.read()方法,内部会读8kb数据
           while( (b = bis.read()) != -1){
               bos.write(b);//内部会写8kb数据
           }            
           //4.关流,只需要关缓冲流,文件流不用关
           bis.close();//【内部会关文件流输入流】
           bos.close();//【内部会关文件流输出流】
           
           System.out.println("音频拷贝完成...");
   }}

带Buffered的流和自己写的数组缓冲对比

自己写 的数组的读写和带Buffered的读取哪个更快? 自己写数组会略胜一筹,因为读和写操作的是同一个数组 而Buffered操作的是两个数组

BufferOutputStream的flush和close方法的区别

  • flush()方法 用来刷新缓冲区的,刷新后可以再次写出
  • close()方法 用来关闭流释放资源的的,如果是带缓冲区的流对象的close()方法,不但会关闭流,还会再关闭流之前刷新缓冲区,关闭后不能再写出
    package lesson05;    
   import java.io.BufferedInputStream;    import java.io.BufferedOutputStream;    import java.io.FileInputStream;    import java.io.FileOutputStream;    import java.io.IOException;    
   public class Demo01 {    
       public static void main(String[] args) throws IOException {            //BufferedOutputStream的flush和close方法的区别
       /*  flush()方法
               1.用来刷新缓冲区的,刷新后可以再次写出
           close()方法
               2.用来关闭流释放资源的
               3.如果是带缓冲区的流对象的close()方法,不但会关闭流,还会再关闭流之前刷新缓冲区,关闭后不能再写出
       */
           
           //案例:把a文件的内容拷贝到b文件
           
           //1.输入流
           FileInputStream fis = new FileInputStream("a.txt");
           BufferedInputStream bis = new BufferedInputStream(fis);            
           //2.输出流
           FileOutputStream fos = new FileOutputStream("b.txt");
           BufferedOutputStream bos = new BufferedOutputStream(fos);            
           //3.读写操作
           int b = 0;            while( (b = bis.read()) != -1){
               bos.write(b);
           }
           
           bos.flush();
           bos.write(97);            //bos.flush();
           //4.关闭流
           bis.close();
           bos.close();
           
           
       }
   
   }

字节流读写中文乱码问题

字节流读取中文: 字节流读取中文的问题 字节流在读中文的时候有可能会读到半个中文,造成乱码

package lesson06;import java.io.FileInputStream;import java.io.IOException;public class Demo06 {    public static void main(String[] args) throws IOException {        //字节流读写中文乱码问题       //1.读数据
       //创建文件输入流
       FileInputStream fis = new FileInputStream("a.txt");        //读
       //定义字节数组[杯子思想,缓冲区思想]
       /**
        * 在UTF-8编码表中,一个中文占3个字节,一个英文占1个字节
        * 在GBK编译中,一个中文占2个字节
        */
       byte buf[] = new byte[3];        int len = 0;        while( (len = fis.read(buf)) != -1){
           System.out.println("len:" + len );            //把字节转成字符串
           String s = new String(buf, 0, len);
           System.out.println("s:" + s);
       }
   }
}

字节流写入中文的问题 字节流直接操作的字节,所以写出中文必须将字符串转换成字节数组 写出回车换行 write("\r\n".getBytes());

package lesson07;import java.io.FileOutputStream;import java.io.IOException;public class Demo01 {    public static void main(String[] args) throws IOException {
       //案例:往a.txt文件写中文
       
       //1.输出流
       FileOutputStream fos = new FileOutputStream("a.txt");        
       //2.写中文
       String s = "你好,Gosling最近好吗?";        
       //把字符转成字节数组
       //byte[] bytes = s.getBytes();
       
       /**
        * charsetName 字符编码 UTF-8(Unicode),GBK,ASCII
        */
       byte[] bytes = s.getBytes("UTF-8");
       fos.write(bytes);        
       //3.关流
       fos.close();
       
   }}

流的标准处理异常代码1.6版本及其以前

package lesson08;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;public class Demo01 {    public static void main(String[] args) throws IOException{        //流的标准处理异常代码-jdk1.6版本及其以前
       //案例:a.txt的内容拷贝到b.txt
       
       FileInputStream fis = new FileInputStream("a.txt");
       FileOutputStream fos = new FileOutputStream("b.txt");        
       try {            //读写数据会抛出
           int b = 0;            while((b = fis.read()) != -1){
               fos.write(b);
           }
       } catch (IOException e) {
           e.printStackTrace();
       }finally {            //关流
           try {
               fis.close();
           }finally {
               fos.close();
           }
       }
   }    public static void test1() throws FileNotFoundException {       FileInputStream fis = new FileInputStream("a.txt");
       FileOutputStream fos = new FileOutputStream("b.txt");        
       try {            //读写数据会抛出
           int b = 0;            while((b = fis.read()) != -1){
               fos.write(b);
           }
       } catch (IOException e) {
           e.printStackTrace();
       }finally {            //关流
           try {
               fis.close();
           } catch (IOException e) {
               e.printStackTrace();
           }            
           try {
               fos.close();
           } catch (IOException e) {
               e.printStackTrace();
           }
       }
   }
}

流的标准处理异常代码1.7以上版本

原理:在try()中创建的流对象必须实现了AutoCloseable这个接口,如果实现了,在try后面的{}(读写代码)执行后就会自动调用,流对象的close方法将流关掉

package lesson09;import java.io.FileInputStream;import java.io.FileOutputStream;public class Demo01 {    public static void main(String[] args)throws Exception {        //流的标准处理异常代码1.7版本
       /**
        * 1.把流对象的声明放在try() 括号里面
        * 2.操作流【读写数据】的代码放在花括号里面
        * 3.这样写不用关闭流,java自动关闭流
        * 4.在try的括号里的对象,必须是实现AutoCloseable的接口
        */
       try(
           FileInputStream fis = new FileInputStream("a.txt");
           FileOutputStream fos = new FileOutputStream("b.txt");            //Person p = new Person();
           //声明一个自己输入流
           MyInputStream myis = new MyInputStream();
       ){            int b = 0;            while((b = fis.read()) != -1){
               fos.write(b);
           }
       }
   }
}class Person{
   
}class MyInputStream implements AutoCloseable{    @Override
   public void close() throws Exception {
       System.out.println("我的输入流关闭了...");
   }
}

练习:图片加密

package lesson10;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;public class Demo01 {    public static void main(String[] args)throws IOException {        // TODO Auto-generated method stub
       //练习:图片加密
       
       //1.输入输出流
       FileInputStream fis = new FileInputStream("C:/Users/10301/Desktop/a/cm2.jpg");
       FileOutputStream fos = new FileOutputStream("C:/Users/10301/Desktop/a/cm.jpg");        
       //2.读写数据
       /**
        * 加密操作
        * 解密操作
        *
        * 一个数异或2次,数据不变
        */
       int b = 0;        while((b = fis.read()) != -1){
           fos.write(b ^ 5);
       }        
       //3.关流
       fis.close();
       fos.close();       System.out.println("图片加密完成");
   }}

练习:根据用户输入的文件拷贝文件到当前项目目录

package lesson11;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.util.Scanner;public class Demo01 {    public static void main(String[] args) throws IOException {        //练习:根据用户输入的文件[图片]拷贝文件到当前项目目录
       //C:/Users/10301/Desktop/a/cm2.jpg
       
       //1.获取用户输入的文件路径
       Scanner scanner = new Scanner(System.in);
       System.out.println("请输入一个文件的路径[请不要输入文件夹路径]:");
       String path = scanner.nextLine();        
       //2.判断这个路径是否为文件
       File file = new File(path);        if(file.isDirectory()){
           System.out.println("您输入的路径不是一个文件");            return;
       }        
       //3.如果是文件就拷贝
       //3.1 输入流
       FileInputStream fis = new FileInputStream(path);        
       //3.2输出流
       FileOutputStream fos = new FileOutputStream(file.getName());        
       //3.3读写【性能】
       byte[] buf = new byte[8 * 1024];        
       int len = 0;        while((len = fis.read(buf)) != -1){
           fos.write(buf, 0, len);
       }        
       //3.4关流
       fis.close();
       fos.close();
       
       System.out.println("文件拷贝完成...");
       
   }
}

练习:录入数据拷贝到文件

      /**
         * 根据用户在键盘中输入的内容,然后写到一个文件中去
        *
        */package lesson12;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.util.Scanner;public class Demo01 {    public static void main(String[] args) throws IOException {        //练习:录入数据拷贝到文件       
       //1.创建一个文件输出流
       FileOutputStream fos = new FileOutputStream("new.txt");        
       //2.创建一个Scanner对象
       Scanner scanner = new Scanner(System.in);
       System.out.println("请输入需要录入内容...输入quit代表退出");        
       //3.通过死循环来获取用户输入【当输入quit,代表不录入】
       while(true){            //获取用户的输入
           String line = scanner.nextLine();            
           //退出循环
           if(line.equals("quit")){                break;
           }            
           //写入文件
           fos.write(line.getBytes());            //换行
           fos.write("\r\n".getBytes());
       }        
       //4.关流
       fos.close();   }
}

BufferedReader的readLine()&BufferedWriter的newLine()方法

package lesson03;import java.io.BufferedReader;import java.io.FileNotFoundException;import java.io.FileReader;import java.io.IOException;public class Demo01 {    public static void main(String[] args) throws IOException {        //BufferedReader的readLine()&BufferedWriter的newLine()方法
       /**
        * 1.readLine(),每次读取一行数据
        */
       
       
       //1.创建Reader
       FileReader fr = new FileReader("a.txt");
       BufferedReader br = new BufferedReader(fr);        
       //2.读一行数据/*      System.out.println(br.readLine());
       System.out.println(br.readLine());
       System.out.println(br.readLine());
       System.out.println(br.readLine());
       System.out.println(br.readLine());
       System.out.println(br.readLine());*/
       String line = null;        while((line = br.readLine()) != null){
           System.out.println(line);
       }        
       //3.关流
       br.close();
   }
}

BufferedWriter的newLine()方法

package lesson04;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.FileNotFoundException;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;public class Demo01 {    public static void main(String[] args) throws IOException {        //BufferedWriter的newLine()方法
       // newLine()换行
       
       //往b.txt写a.txt文件的内容【一行一行拷贝,读一行写一行】
       //1.创建Reader
       FileReader fr = new FileReader("a.txt");
       BufferedReader br = new BufferedReader(fr);        
       //2.创建writer
       FileWriter fw = new FileWriter("b.txt");
       BufferedWriter bw = new BufferedWriter(fw);        
       //3.读一行写一行
       String line = null;        while((line = br.readLine()) != null){
           bw.write(line);            /**
            * 当使用readline读取一行数据时,不会读回车换行"\r\n"字符
            */
           //bw.write("\r\n");
           bw.newLine();//换行
       }        
       //4.关流
       br.close();
       bw.close();
   }
}

案例:使用带缓冲的字符流拷贝文件

**BufferedReader的readLine()&BufferedWriter的newLine()方法 **

  1. BufferedReader的readLine()方法可以读取一行字符(不包含换行符号)
  2. BufferedWriter的newLine()可以输出一个跨平台的换行符号"\r\n"

案例:将文本反转

一个文本文档上的文本反转,第一行和倒数第一行交换,第二行和倒数第二行交换

package lesson05;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.FileNotFoundException;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;import java.util.ArrayList;import java.util.List;/**
* 掌握思想:
* 1.for循环的倒序遍历
*/public class Demo01 {   public static void main(String[] args) throws IOException {        //案例:将文本反转写入另一个文件
       
       //1.把文本每一行内容读取出来存在List<String> 集合
       //1.1 集合对象
       List<String> list = new ArrayList<String>();        
       //1.2一行行读取文件
       BufferedReader br = new BufferedReader(new FileReader("a.txt"));
       String line = null;        while((line = br.readLine()) != null){            list.add(line);
       }
       
       System.out.println(list);        
       //2.当我们要写入文件时,倒序保存List集合中的内容到文件中
       BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));        for(int i = list.size() - 1 ; i>=0; i--){
           bw.write(list.get(i));
           bw.newLine();//换行
       }        
       //3.关闭流
       br.close();
       bw.close();
       System.out.println("finish....");
   }
}

编码转换流图解

image

练习:获取文本上字符出现的次数

package lesson08;import java.io.BufferedWriter;import java.io.FileNotFoundException;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;import java.util.HashMap;import java.util.Map;import java.util.Map.Entry;/**
* 掌握:当键盘敲 enter键,两个字符\r\n : 回车换行
*
*/public class Demo01 {   public static void main(String[] args) throws IOException {        //练习:获取文本上字符出现的次数,把数据写入文件/*      思路:
       1.遍历文本每一个字符
       2.字符出现的次数存在Map中
       *//**
        * Map<Character,Integer> map = new HashMap<Character,Integer>();
        * map.put('a',18);
        * map.put('你',2);
        *//*
       3.把map中的数据写入文件*/
       
       //==================================
       //1.创建Map集合
       Map<Character,Integer> map = new HashMap<Character,Integer>();        //System.out.println(map.get('a'));
       
       //2.遍历每一个字符,每一个字符出现的次数放到map中
       FileReader reader = new FileReader("a.txt");        int c = 0;        while((c = reader.read()) != -1){            //int 还原 char
           char ch = (char)c;            // 判断char是否在map中第一次出现
           if(map.get(ch) == null){                map.put(ch, 1);
           }else{                map.put(ch, map.get(ch) + 1);
           }
       }        
       //3.把map中数据存在文件count.txt
       //3.1 创建Writer
       BufferedWriter bw = new BufferedWriter(new FileWriter("count.txt"));        
       //3.2 遍历map,再写入数据
       for(Entry<Character, Integer> entry :map.entrySet()){            switch (entry.getKey()) {            case ' ':
               bw.write("空格=" + entry.getValue());                break;            case '\t'://\t表示tab 键字符
               bw.write("tab键=" + entry.getValue());                break;            case '\r'://
               bw.write("回车=" + entry.getValue());                break;            case '\n'://
               bw.write("换行=" + entry.getValue());                break;            default:
               bw.write(entry.getKey() + "=" + entry.getValue());                break;
           }
           bw.newLine();
       }        
       //4.关流
       reader.close();
       bw.close();
   }
}

面试题:找bug

定义一个文件输入流,调用read(byte[] b)方法,将a.txt文件中的内容打印出来(byte数组大小限制为5)

package lesson02;import java.io.ByteArrayOutputStream;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;public class Demo01 {    public static void main(String[] args) throws IOException {        // TODO Auto-generated method stub/*      面试题:找bug
       定义一个文件输入流,调用read(byte[] b)方法,
       将a.txt文件中的内容打印出来(byte数组大小限制为5)*/       //1.文件输入流
       FileInputStream fis = new FileInputStream("a.txt");        
       //2.字节数组输出流
       ByteArrayOutputStream baos = new ByteArrayOutputStream();        
       //3.字节数组【缓冲区思想,杯子思想】
       byte[] arr = new byte[5];        int len;        while((len = fis.read(arr)) != -1) {            //通过字节缓冲数组写入
           baos.write(arr, 0, len);            
           //把字节转成字符串
           /**
            * 中文乱码问题
            */
           System.out.println(new String(arr,0,len));
       }        
       //内部会调用toString方法,把字节数组转成字符串
       System.out.println(baos);
       
       fis.close();
   }
}

对象操作流ObjecOutputStream& ObjecInputStream (了解)

捋一捋IO流

package lesson12;public class Demo01 {   public static void main(String[] args) {        // TODO Auto-generated method stub       //捋一捋IO流
       
       /**
        * 一、IO流-输入输出流
        * I:input
        * O:out
        * IO流 操作文件,读取文件内容,往文件写内容
        *
        * 二、字节流
        *
        * >InputStream
        *  -FileInputStream 文件输入流,读的单位是字节
        *  -BufferedInputStream 缓冲输入流,内部有个byte[]字节数组
        *  -SequenceInputStream 序列流,把多个字节流整合成一个流
        *  -ObjectInputStream 对象输入流,直接从文件中读取一个对象,这个对象要实现serilazable接口
        *  -Sytem.in 标准输入流-指键盘
        *  -DataInputStream 数据输入流,按基本数据类型的大小(long) 读取文件
        *  
        * >OutputStream
        *  -FileOutputStream 文件输出流,写的单位是字节
        *  -BufferedOutputStream 缓冲输出流,内部有个byte[]字节数组
        *  -ByteArrayOutputStream 字节数组输出流,把数据读取到内存中,这个类不需要关联文件
        *  -ObjectOutputStream 对象输出流,直接把一个对象存入文件,
        *  -PrintStream 打印流,把内容打印到控制台
        *  -System.out 标准输出流-指控制台
        *  -DataOutputStream 数据输出流,按基本数据类型的大小(long) 写入文件
        *  
        * 三、字符流
        * >Reader
        *  -FileReader 文件读取流,读取的单位是字符
        *  -BufferedReader 缓冲读取流,内部有个char[] 字符数组
        *  -InputStreamReader 指定字符编码读取文件
        *
        * >Writer
        *  -FileWriter 文件写入流,写入的单位是字符
        *  -BufferedWriter,缓冲写入流,内部有个char[] 字符数组
        *  -OutputStreamWriter 指定字符编码写入文件
        *  -PrintWriter 打印流,把内容打印一个文件
        *  
        *  
        * RandomAccessFile 随机访问流,特点:读和写都在一个类中
        *
        * Properties 相当于Map一样使用,这个类把数据存在一个后缀名为.properties文件
        */
   }}

觉得文章不错,记得转发分享给更多同学哦~

原文发布于微信公众号 - 技术从心(gh_d845efe513db)

原文发表时间:2019-01-29

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券