目录
14、DataOutputStream和DataInputStream数据流
1、什么是IO流
I:Input 例如:从硬盘中读取数据进入CPU的内存
O:Output 例如:从CPU的内存读取数据进入硬盘
流:在管道(pipe line)中产生的一种计算模式
IO流:以内存为参照物,完成硬盘文件的读和写
2、流的分类
按流的方向分类:
- 输入内存(读Read),称为输入流
- 输出内存(写Write),称为输出流
按读取方式分类:
- 万能字节流,所有文件都是字节构成,例如:流 一次读取一个字节byte,等同于一次读取8个二进制
- 方便字符流,普通文本文件是由字符构成,例如:流 一次读取一个字符,且只能读取纯文本文件.txt,连word文件都无法读取(普通文本文件指的是能用记事本编辑器打开的文件,并不是都是.txt文件)
举例子:
万能字节流:
假设文件file1.txt,采用字节流读取
a中国bccc
第一次读:一个字节,正好读到 'a'
第二次读:一个字节,正好读到 '中' 字符的一半
第三次读:一个字节,正好读到 '中' 字符的另外一半
方便字符流:
假设文件file2.txt,采用字符流读取
a中国bccc
第一次读:一个字符,正好识别读到 'a
第二次读:一个字符,正好识别读到 '中'
第三次读:一个字符,正好识别读到 '国'
疑惑:java中的英文字符a不是应该占用两个字节吗?为什么读取的时候读一个字节就可以将英文字符a读出来,因为file1.txt属于windows操作系统的内容,在这个文件中,只是windows操作系统的普通文件
JAVA所有流都是在java.io.*这个包内
主要研究怎么new流对象,调用流对象的哪个方法是读,哪个方法是写
3、流的四大家族首领
java.io.InputStream 字节输入流
java.io.OutputStream 字节输出流
java.io.Reader 字符输入流
java.io.Writer 字符输出流
规律:
Stream结尾的类包就是代表字节流,Reader结尾的类包就是代表字符流
四大家族的首领都是抽象类(abstract class)
四大家族的首领都实现了:java.io.Closeable接口,都有close( )方法,都是可关闭的
流的本质是在管道内流通,就占用较多的系统资源,需要养成用完流之后进行关闭流的操作的习惯 ,强行刷新清空管道中剩余未输出的数据,没有flush( )可能会导致数据丢失
四大家族的首领都实现了:java.io.Flushable接口,都有flush( )方法,都是可刷新的
4、java.io.*包下需要掌握的16个流
文件流:
java.io.FileInputStream (掌握)
java.io.FileOutputStream (掌握)
java.io.FileReader
java.io.FileWriter
转换流:(将字节流转换成字符流)
java.io.InputStreamReader
java.io.OutPutStreamWriter
缓冲流:
java.io.BufferedReader
java.io.BufferedWriter
java.io.BufferInputStream
java.io.BufferedOutputStream
数据流:
java.io.DataInputStream
java.io.DataOutputStream
标准流:
java.io.PrintWriter (掌握)
java.io.PrintStream (掌握)
对象流:
java.io.ObjectInputStream (掌握)
java.io.ObjectOutputStream (掌握)
5、FileInputStream的实用方法
代码演示(从一个文件中逐个读出内容):
步骤一:新建一个文件123.txt ,复制文件路径(文件内容abc中)
步骤二:读出文件内容
package com.lbj.javase.io; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; public class FileInputStreamTest01 { public static void main(String[] args) { FileInputStream fileInputStream = null; try { //创建文件字节输入流对象 //采用绝对路径的方式:idea工具会自动把路径的单斜杠/ 转换成//双斜杠 fileInputStream=new FileInputStream("D:\\2021-2022课件\\123.txt"); //第一次开始读,每次只读一个字节 int readData=fileInputStream.read(); //看看到底读到什么东西 //这个read()方法的返回值是:读取到的“字节”本身 System.out.println(readData);//97 //第二次读 int readData2=fileInputStream.read(); System.out.println(readData2);//98 //第三次读 int readData3=fileInputStream.read(); System.out.println(readData3);//99 //第四次读 //读‘中’的1个字节 int readData4=fileInputStream.read(); System.out.println(readData4);//214 //第五次读 //读‘中’的另一个字节 int readData5=fileInputStream.read(); System.out.println(readData5);//208 //第六次读 //如果读取的是空,则返回-1 int readData6=fileInputStream.read(); System.out.println(readData6);//-1 //第七次读 //如果读取的是空,则返回-1 int readData7=fileInputStream.read(); System.out.println(readData7);//-1 } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { //在finally语句块中确保流一定要关闭 //关闭流的前提是:流不是空,避免空指针异常 if(fileInputStream!=null){ try { fileInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
代码演示(从一个文件中循环读出内容):
package com.lbj.javase.io; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; public class FileInputStreamTest02 { public static void main(String[] args) { FileInputStream f=null; try { f=new FileInputStream("D:\\2021-2022课件\\123.txt"); //循环输出读取的数据 int readData=0; while ((readData=f.read())!=-1){ System.out.println(readData); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (f!=null){ try { f.close(); } catch (IOException e) { e.printStackTrace(); } } } } } 97 98 99 214 208
代码演示(将字节数组byte[ ]读进内存):
package com.lbj.javase.io; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; public class FileInputStreamTest02 { public static void main(String[] args) { FileInputStream f=null; try { //123.txt存储的是abcdef f=new FileInputStream("D:\\2021-2022课件\\123.txt"); //定义一个byte数组,此数组一次可以存储4个字节 byte[]