美文网首页Java学习笔记Java学习笔记
Java IO 流之字节流以及字节流,字符流转换

Java IO 流之字节流以及字节流,字符流转换

作者: 向日花开 | 来源:发表于2016-12-22 11:31 被阅读800次

字节流

  • InputStream 输入字节流
  • OutputStream 输出字节流

输入字节流----InputStream

InputStream 是所有的输入字节流的父类,它是一个抽象类。同样的来看它的子类。

FileInputStream 继承自InputStream

构造方法:
 //传一个文件路径(字符串)
 public FileInputStream(String var1) throws FileNotFoundException {
        this(var1 != null?new File(var1):null);
    }//如:FileInputStream in=new FileInputStream(String path);

  //传一个文件
 public FileInputStream(File var1) throws FileNotFoundException {
    ....
    }//如:FileInputStream in=new FileInputStream(new File(String path));

  //不常用
 public FileInputStream(FileDescriptor var1) {
     ...
    }
主要方法
  • int read();//返回值int,若返回值为-1,则代表已经读完,是不是和字符流很像,但每次读一个字节,并打印,如果存在中文,可能会乱码

  • int read(byte[] bytes);//每次读bytes字节

代码演示:

    /**
     * 需求:控制台输出本文件内容
     */
    public class Demo {
        //文件地址
        public static final String PATH = "/Volumes/huang/studyfromGitHub/JavaForAndroid/JavaForAndroid/series11/src/main/java/com/example/Demo1.java";
        //文件名
        public static final String NAME = "copyTest1.java";

        public static void main(String[] args) {
            //  read();//测试InputStream 的read()方法
            reads();
        }

        /**
         * 测试read(byte[] bytes)
         * 可以控制字符集
         */
        private static void reads() {
            FileInputStream inputStream = null;
            try {
                inputStream = new FileInputStream(PATH);
                byte[] bytes = new byte[inputStream.available()];//inputStream.available()获取文件长度
                //读取的字节长度
                int len = inputStream.read(bytes);//将数据一次性读取到字节数组中
                System.out.println("读取长度" + len + "\n" + new String(bytes, "utf-8"));
            } catch (Exception e) {
                e.printStackTrace();
            }

        }

        /**
         * 测试read()
         * 每次读一个字节,并打印,如果存在中文,可能会乱码
         */
        private static void read() {
            FileInputStream inputStream = null;
            try {
                inputStream = new FileInputStream(PATH);
                int len = 0;
                while ((len = inputStream.read()) != -1) {
                    System.out.print((char) len);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

结果----read(),出现了乱码.

结果----read(byte[]bytes),设置了字符集,没出现乱码.


有没有觉得都差不多.

输出字节流----OutputStream

OutputStream 是所有的输入字节流的父类,它是一个抽象类。同样的来看它的子类。

FileOutStream 继承自OutputStream

构造方法:
    //是不是和FileWriter很像,第一个参数目的是创建一个向指定 File 对象表示的文件中写入数据的文件输出流。如果第二个参数为 true,则将字节写入文件末尾处,而不是写入文件开始处。
    public FileOutputStream(String var1) throws FileNotFoundException {
            ....
        }

    public FileOutputStream(String var1, boolean var2) throws FileNotFoundException {
            .....
        }

    public FileOutputStream(File var1) throws FileNotFoundException {
            this(var1, false);
        }

    public FileOutputStream(File var1, boolean var2) throws FileNotFoundException {
          ......
        }

    public FileOutputStream(FileDescriptor var1) {
          .....
        }
主要方法
  • void write(byte[]bytes);//写字节数组

写纯文本文件-----案例

  • Config类代码:(通用案例1,2,3)

      public class Config {
          public static final String PATH="/Volumes/huang/studyfromGitHub/JavaForAndroid/JavaForAndroid/series11/src/main/java/files";
      }
    
  • 主要代码

             private static final String fileName = "testOutput.java";
         /**
           *
           */
          private static void write() {
              FileOutputStream outputStream = null;
              try {
                  outputStream = new FileOutputStream(Config.PATH + fileName);
                  outputStream.write("你好啊,美女".getBytes());
              } catch (Exception e) {
                  e.printStackTrace();
              }finally {
                           try {
                               outputStream.close();
                           } catch (IOException e) {
                               e.printStackTrace();
                           }
                       }
          }
    
  • 结果

拷贝纯文本文件-----案例(读,写)

  • 代码

      /**
           * 拷贝本类文件
           */
          private static void copyFile() {
              String copyName = "copy.java";
              String sourcePath = "/Volumes/huang/studyfromGitHub/JavaForAndroid/JavaForAndroid/series11/src/main/java/com/example/Demo2.java";
    
              FileInputStream inputStream = null;
              FileOutputStream outputStream = null;
    
              try {
                  inputStream = new FileInputStream(sourcePath);
                  outputStream = new FileOutputStream(Config.PATH + copyName);
                  byte[] bytes = new byte[inputStream.available()];
                  inputStream.read(bytes);
                  outputStream.write(bytes);
    
              } catch (Exception e) {
                  e.printStackTrace();
              } finally {
                  try {
                      inputStream.close();
                      outputStream.close();
                  } catch (IOException e) {
                      e.printStackTrace();
                  }
              }
          }
    
  • 结果


拷贝图片-----案例(读,写)

  • 代码

      /**
         * 拷贝图片step1.png
         */
        private static void copyPicture() {
            String picSource = "/Volumes/huang/studyfromGitHub/JavaForAndroid/JavaForAndroid/series11/src/main/java/images/step1.png";
            String copyName = "copyPic.png";
    
            FileInputStream inputStream = null;
            FileOutputStream outputStream = null;
    
            try {
                inputStream = new FileInputStream(picSource);
                outputStream = new FileOutputStream(Config.PATH + copyName);
    
                //定义缓冲区--字节数组
                byte[] bytes=new byte[1024]; //每次最多读取1K节字
                int len=-1;  //每次读取的字节长度
    
                while((len=inputStream.read(bytes))!=-1){ //-1代表的是文件结尾标识
                    outputStream.write(bytes, 0, len);
                }
    
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    inputStream.close();
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
  • 结果


同样的,字节流也有带缓冲的,基本都是一样的,当读写纯文本的时候优先考虑字符流,读写非纯文本的时候用字节流。下面我们继续看带缓冲的字节流,基本一样。
带缓冲的字节流读写案例(BufferedInputStream 读,BufferedOutputStream 写)没有关闭的流你们自行关闭。
  • Config 类

      public class Config {
          public static final String PATH="/Volumes/huang/studyfromGitHub/JavaForAndroid/JavaForAndroid/series11/src/main/java/files";
      }
    
  • 测试类

      /**
       * 带缓冲的字节流
       * <p>
       * 需求:使用带缓冲的字节流拷贝文件
       */
      public class Demo3 {
    
          //纯文本源文件路径
          private static final String txtPath = "/Volumes/huang/studyfromGitHub/JavaForAndroid/JavaForAndroid/series11/src/main/java/com/example/Demo2.java";
          //拷贝后的纯文本文件名
          private static final String txtName = "copy.java";
    
          //图片源文件路径
          private static String picPath = "/Volumes/huang/studyfromGitHub/JavaForAndroid/JavaForAndroid/series11/src/main/java/images/step1.png";
          //拷贝后的图片名
          private static String picName = "copyPic.png";
    
          public static void main(String[] args) {
              //copy(txtPath, txtName);
              copy(picPath, picName);
          }
    
          /**
           * 拷贝文件
           * Config.PATH 是上面提到的
           *
           * @param sourcePath 源路径
           * @param targetName 文件名
           */
          private static void copy(String sourcePath, String targetName) {
              //申明变量
              FileInputStream inputStream = null;
              BufferedInputStream bufferedInputStream = null;
    
              FileOutputStream outputStream = null;
              BufferedOutputStream bufferedOutputStream = null;
    
              //实例化变量
              try {
                  inputStream = new FileInputStream(sourcePath);
                  bufferedInputStream = new BufferedInputStream(inputStream);
    
                  outputStream = new FileOutputStream(Config.PATH + targetName);
                  bufferedOutputStream = new BufferedOutputStream(outputStream);
                  byte[] bytes = new byte[2048];//大小可以自己指定,但不要非常非常大。
                  int len = 0;
                  while ((len = bufferedInputStream.read(bytes)) != -1) {
                      bufferedOutputStream.write(bytes, 0, len);//向缓冲区中写入指定长度的数据
                      bufferedOutputStream.flush();//将数据从内存中写入到文件中
                  }
              } catch (Exception e) {
                  e.printStackTrace();
              } finally {
                  try {
                      bufferedInputStream.close();//关闭流(处理流),其中的包装流会自动关闭
                      bufferedOutputStream.close();
                  } catch (IOException e) {
                      e.printStackTrace();
                  }
              }
    
          }
      }
    

结果

都是一样的。

InputStram 绑定System.in 案例

    public class Demo4 {

        /**
         * 打印从键盘输入的字母,直到输入exit结束程序
         * @param args
         */
        public static void main(String[] args) {
            InputStream inputStream = System.in;
            int num = -1;
            StringBuilder sb = new StringBuilder();
            while (true) {
                try {
                    num = inputStream.read();
                    //判断字符是否换行
                    if (num == '\n') {
                        String line = sb.toString().trim();//去除两边的空格

                        if (line.equalsIgnoreCase("over")) {
                            break;
                        }
                        System.out.println(line); //打印输入的一行数据(字母是大写)
                        //重置字符串变量的内容
                        sb.delete(0, sb.length());
                    }
                    sb.append((char) num);
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        }
    }

结果


可是兄弟们,你们看到打印字符串乱码了吗,字节流不能操作Unicode字符,由于Java采用16位的Unicode字符,
所以要使用基于字符的输入输出操作。所以有了字符流,以提供直接的字符输入输出的支持。而字节流怎么转成字符流呢,Java为我们提供了两个类,InputStreamReader,
OutputStreamWriter。作为字节流和字符流的桥接,并可以设置字符编码.

  • InputStreamReader 构造方法

           //来自源码
          // 接收一个字节流实例
          public InputStreamReader(InputStream var1) {
              super(var1);
    
              try {
                  this.sd = StreamDecoder.forInputStreamReader(var1, this, (String)null);
              } catch (UnsupportedEncodingException var3) {
                  throw new Error(var3);
              }
          }
           //接受一个字节流实例和一个String 类型的参数,再深入看代码可猜测var2和字符集(charset)有关系
          public InputStreamReader(InputStream var1, String var2) throws UnsupportedEncodingException {
              super(var1);
              if(var2 == null) {
                  throw new NullPointerException("charsetName");
              } else {
                  this.sd = StreamDecoder.forInputStreamReader(var1, this, var2);
              }
          }
           //同
          public InputStreamReader(InputStream var1, Charset var2) {
              super(var1);
              if(var2 == null) {
                  throw new NullPointerException("charset");
              } else {
                  this.sd = StreamDecoder.forInputStreamReader(var1, this, var2);
              }
          }
           //基本一样
          public InputStreamReader(InputStream var1, CharsetDecoder var2) {
              super(var1);
              if(var2 == null) {
                  throw new NullPointerException("charset decoder");
              } else {
                  this.sd = StreamDecoder.forInputStreamReader(var1, this, var2);
              }
          }
    
  • OutputStreamWriter 构造方法(实参var2作用同InputStreamReader)

      public OutputStreamWriter(OutputStream var1, String var2) throws UnsupportedEncodingException {
              super(var1);
              if(var2 == null) {
                  throw new NullPointerException("charsetName");
              } else {
                  this.se = StreamEncoder.forOutputStreamWriter(var1, this, var2);
              }
          }
    
          public OutputStreamWriter(OutputStream var1) {
              super(var1);
    
              try {
                  this.se = StreamEncoder.forOutputStreamWriter(var1, this, (String)null);
              } catch (UnsupportedEncodingException var3) {
                  throw new Error(var3);
              }
          }
    
          public OutputStreamWriter(OutputStream var1, Charset var2) {
              super(var1);
              if(var2 == null) {
                  throw new NullPointerException("charset");
              } else {
                  this.se = StreamEncoder.forOutputStreamWriter(var1, this, var2);
              }
          }
    
          public OutputStreamWriter(OutputStream var1, CharsetEncoder var2) {
              super(var1);
              if(var2 == null) {
                  throw new NullPointerException("charset encoder");
              } else {
                  this.se = StreamEncoder.forOutputStreamWriter(var1, this, var2);
              }
          }
    

案例优化,接收打印中文字符

    /**
     * 字节流,字符流转换
     */
    public class Demo5 {
        public static void main(String[] args) {
            //输入流绑定键盘输入
            InputStream inputStream = System.in;
            //字符输入流声明
            InputStreamReader inputStreamReader = null;
            try {
                //实例化带有编码格式的字符流
                inputStreamReader = new InputStreamReader(inputStream, "utf-8");
                //包装
                BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
                String line = null;
                while (true) {
                    //判断读取
                    line = new String(bufferedReader.readLine());
                    if (line.trim().equalsIgnoreCase("exit")) {
                        break;
                    }
                    //打印输出
                    System.out.println(line);

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

结果

持续深入

    /**
     * 需求:接收键盘输入的内容,并打印到文件里去
     */
    public class Demo6 {

        public static void main(String[] args) {
    //1. 通过转换流,获取到读取键盘的字符输入流
            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
            String fileName = "copy.txt";//文件名
            //涉及到了System.in,System.out,System.setOut(...),PrintWriter

            //设置控制输出的数据位置--保存到文件中
            try {
                //File.separator分隔符
                System.setOut(new PrintStream(Config.PATH + File.separator + fileName));
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }

            //2. 通过转换流,将控制台的字节流转换成缓冲的字符流
            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));

            //3. 开始读取数据
            String line = null;
            while (true) {
                try {
                    line = reader.readLine().trim();
                    if (line.equalsIgnoreCase("exit")) {
                        break;
                    }
                    writer.write(line);
                    writer.newLine();
                    writer.flush();
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }

        }

    }

结果

相关文章

  • No.16 转换流InputStreamReader/Outpu

    简介 在java.io除了字节流/字符流之外,还存在一组字节流-字符流的转换类。1.OutputStreamWri...

  • Java IO流的使用

    下面部分内容是参考Oubo的博客——Java IO流学习总结 Java流操作有关的类或者接口: 字符流和字节流 字...

  • IO流

    一、IO流的概述: 二、IO流的分类: 三、字节缓冲流: 四、字符缓冲流: 五、转换流(把字节流转换为字符流): ...

  • Java I/O 输入输出流(四)——字节流之文件输入流File

    字节流之文件输入流FileInputStream-1 它就是IO流(输入流、输出流) 又分为字节流,字符流 字节流...

  • Java基础之IO流

    1.IO流 Java中有几种类型的流 答:字节流,字符流。字节流继承于InputStream、OutputStre...

  • 5-Java IO-装饰模式

    1.Java IO分类节点流-过滤流输入流-输出流字节流-字符流 2.InputStream,节点输入字节流的祖宗...

  • Android面试之Java基础笔试题

    Java IO流 按照数据流的方向不同可以分为:输入流和输出流。 按照处理数据单位不同可以分为:字节流和字符流。字...

  • java io之字节流

    java的IO流按照流向可分为输入流、输出流 按照处理方式 字节流、字符流本文主要记载字节流 字节流 inpu...

  • Java | 两个IO实例demo

    套路:.字节流(如InputStream )转换成字符流(如InputStreamReader),字符流转成缓冲字...

  • IO流简介

    io流的作用:读写设备上的数据,硬盘文件、内存、键盘、网络.... io流分类:输入流和输出流,字节流和字符流 字...

网友评论

    本文标题:Java IO 流之字节流以及字节流,字符流转换

    本文链接:https://www.haomeiwen.com/subject/tswcvttx.html