美文网首页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();
                    }
    
                }
    
            }
    
        }
    

    结果

    相关文章

      网友评论

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

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