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

字节流

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

            }

        }

    }

结果

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,569评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,499评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,271评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,087评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,474评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,670评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,911评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,636评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,397评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,607评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,093评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,418评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,074评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,092评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,865评论 0 196
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,726评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,627评论 2 270

推荐阅读更多精彩内容