一、概述
流:代表任何有能力产出数据的数据源对象或者是有能力接受数据的接收端对象 ;其作用是为数据源和目的地建立一个输送通道。
IO流:是程序中一套用于数据传输的机制。IO流是Input流和Output流的简称。流的输入输出是以程序为参照物。
1、输入流
数据从外部流向程序。例如读取文件,就是从外部流入程序。
2、输出流
数据从程序流向外部。例如将程序中的数据写入到文件中。
二、输入输出流的分类
1、根据方向可分为:输入流和输出流
2、根据形式:分为字符流(字符类型文件:txt、java、html等)和字节流(图片、视频、音频等)。
3、四大基本流都是抽象类,都不能直接创建对象。
4、数据的来源/目的地:磁盘、网络、内存和外部设备。
三、文件字符流
1、从文件中读取数据:FileReader类
FileReader类时Reader的一个实现子类。FileReader对象中常用的是read方法,返回读取的字符串个数。
不传入数组,源码中会自动创建一个长度为1的数组,将读取值放入到数组中,返回读取到的字符值;传入数组,底层会将读取到的字符放入到对应数组中,并返回读取到的字符个数。
示例如下:
//1.每次读取一个字符
//创建了一个输入流对象指向D盘下的a.txt //文件字符输入流没有缓冲区 FileReader reader = new FileReader("D:\\a.txt"); //读取数据 //每次只读取一个字符,所以返回值也就是表示读取到的这个字符 // int i1 = reader.read(); // System.out.println(i1); //定义一个变量记录每次读取的字符 int i; //读取到末尾会返回 -1 //这种写法是错误的,表示读一个跳一个 // while((i = reader.read()) != -1) { // System.out.println(reader.read()); // } // while((i = reader.read()) != -1) { System.out.println(i); } //关流 reader.close(); //2.每次读取多个字符
FileReader reader = new FileReader("D:\\a.txt"); //定义一个字符数组作为缓冲区 char[] cs = new char[5]; //将数据读取到缓冲区 // reader.read(cs); // System.out.println(new String(cs)); //返回值表示本次读取到的字符个数 //定义一个变量记录读取的个数; //文件中一共有11个字符 //第一次读取的时候,读取到了5个字符,所以len的值为5 //第二次读取的时候,读取到了5个字符,所以len的值为5 //第三次读取的时候,读取到了1个字符,所以len的值为1 //第四次读取的时候,读取到了文件末尾,所以len的值为-1 int len; //将读取到的数据放到数组中,而返回值表示王数组中放的字符个数 while((len = reader.read(cs)) != -1) { //String(value, offset, len) //从value数组的第offset为开始,将len个元素转为字符串 System.out.println(new String(cs, 0 , len)); } reader.close();
2、向txt文件中写入字符串 --FileWriter
FileWriter类时Writer的一个实现子类。FileWriter对象中常用的是write方法,表示将数据写入到文件中。
示例如下:
//创建一个新文件 //如果原文件不存在,则操作创建的这个新文件 //如果源文件已存在,则利用新文件覆盖源文件 FileWriter writer = new FileWriter("D:\\a.txt"); //写出数据 //在写数据的时候,这个数据并不直接写到文件中而是先写到缓冲区中 //当缓冲区写满了之后,再将缓冲区中的数据写入到文件中 //在缓冲区没有写满的时候,程序就已经结束 //结果导致数据死在了缓存区 writer.write("detgagf"); //冲刷缓冲区 //将数据从缓冲区中冲到文件中 writer.flush(); //关闭流 //为了释放文件以允许别的流来操作这个文件 //流一旦关闭,就不能再次开启 //close之前,流自动进行一次flush操作,以避免有数据死在缓冲区 writer.close(); //清空引用将其标记为垃圾对象 writer = null;
四、文件字节流
1、文件字节输入流 FileInputStream
FileInputStream类时InputStream的一个实现子类。FileInputStream对象中常用的是write方法,表示将数据写入到文件中。 文件字节流没有缓冲区,可定义字节数组作为缓冲区。示例如下
FileInputStream in = new FileInputStream("D:\\b.txt"); //读取到的是字节 //定义一个字节数组作为缓冲区 byte[] bs = new byte[10]; int len; while((len = in.read(bs)) != -1) { System.out.println(new String(bs, 0 , len)); } in.close();
2、文件字节输出流 FileOutputStream
FileOutputStream类时OutputStream的一个实现子类。FileOutputStream对象中常用的是write方法,表示将数据写入到文件中。可以定义一个字节数组作为缓冲区。
示例如下:
FileOutputStream fs = new FileOutputStream("D:\\b.txt"); //写出数据 //字节输出流没有缓冲区 fs.write("abc".getBytes()); //关流 fs.close();
五、缓冲流
1、字符输入缓冲流 BufferedReader
在构建的时候需要传入一个Reader对象。真正读取数据依靠的是传入的这个Reader对象,BufferedReader从Reader对象中获取数据提取到缓冲区。其本质是FileReader的一个包装类。省去了程序员人为为FileReader提供数组缓冲区的步骤。
示例如下:
//真正读取文件的是FileReader //FileReader本身没有缓冲区 FileReader reader = new FileReader("D:\\a.txt"); //BufferedReader将FileReader读取的数据进行缓冲 //BufferedReader提供缓冲区 BufferedReader br = new BufferedReader(reader); //读取一行 //String str = br.ReadLine(); // System.out.println(str); //定义一个变量用来记录读取的每一行数据 String str; //如果读取到末尾,返回的是null while((str = br.readLine()) != null) { System.out.println(str); } //关流 只关闭外层流就行 br.close();
2、字符输出缓冲流 --BufferedWriter
提供了一个更大的缓冲区,其中提供了一个newLine()方法,用于进行换行操作,以屏蔽不同操作系统的差异性。
示例如下:
//真正向文件中写数据的流是FileWirter //BufferedWriter提供了一个更大的缓冲区 BufferedWriter writer = new BufferedWriter(new FileWriter("D:c.txt")); writer.write("sdsakj"); //在Windows中,换行一般用\r\n //在linux中,换行只用\n //进行换行,屏蔽不同操作系统的差异性 writer.newLine(); writer.write("4564561"); writer.close();
六、流中的异常处理
1、无论流操作成功与否,关流操作都得发生,所以需要将关流操作放到finally代码块中。
2、为了让流对象在finally依然能够使用,所以需要将流对象放在try之外声明,并且要赋值为null,然后放在try之内进行实际的初始化过程。
3、在关流之前要判断对象是否初始化成功,实际上就是判断流对象是否为null;
4、因为关流有可能失败,此时流会依然占用文件,所以需要将流对象置为null,标记为垃圾对象进行强制回收以释放内存;
5、如果流有缓冲区,那么为了防止关流失败导致没有进行自动冲刷,所以需要手动冲刷一次,以防止有数据死在缓冲区而产生数据丢失。
流异常处理实例如下:
//2.需要将流对象放在try之外声明并且赋值为null FileWriter writer = null; try { // 2.将流对象放在try之内进行初始化 writer = new FileWriter("F:\\a.txt"); writer.write("积分圣诞节"); //5.为了防止关流失败没有自动flush而导致数据产生丢失 writer.flush(); } catch (IOException e) { e.printStackTrace(); } finally { //3.在关流之前要判断对象是否初始化成功,实际上就是判断流对象是否为null if(writer != null) { try {
//1.无论写流成功还是失败,都需要关流 writer.close(); } catch (IOException e) { e.printStackTrace(); } finally { //4.如果关流失败,将该流标记为垃圾对象,强制回收 //如果关流成功,将该流标记为垃圾对象,释放内存 writer = null; } } }