马士兵学习----IO

1、IO介绍


1.1各部分名称

I:input 输入 读取外部数据到程序内存中

O:output 输出 将程序内存中的数据输出到指定储存格式中

流:数据从源头传输到目的地这个中间的动态过程

1.2 IO操作步骤

1、确定操作 ----是输入流还是输出流

2、确定数据类型 ----是需要传输字符流还是字节流

3、找到数据源 ---- 从哪里读,写到哪里去

4、创建流对象 --- 根据上面的步骤可以知道需要一个怎样的对象

5、进行读写的过程 若是写的过程,还需要刷新

6、释放资源,关闭流

2、IO的操作


2.1数据分类

2.1.1流处理的数据单元

字符:传输的是纯文本信息,用字符接收 char

字节:传输的类型有很多,可以是文本、图片、音频、视频。以字节的形式传输

2.1.2流的功能分类

节点流:直接从源头读写数据,称为节点流

处理流:不直接连接到数据源或目的地,而是"连接"在已存在的流上,通过对数据的处理为程序提供更为强大的读写功能

根据流的数据单元和功能可以简单的分为这四种情况

2.2节点流

2.2.1字符节点流

直接从源头,以字符的形式传输数据 以读数据为例

// 找到数据源
File file = new File("E:\\javayuanwenjian\\Reborn\\IO1.txt");
// 创建一个读数据的对象,引用刚刚找到的数据源
FileReader fr = new FileReader(file);//这里表明从当前地址去找内容
// 现在开始进行读数据  
fr.read();
// 关闭流
fr.close();

在使用字符节点流对数据进行处理时,是一个一个数据进行读取的,读取速度很慢,而且不知道什么时候能读完,这里需要一个控制方法 ------- `fr.read() 返回的是一个int类型,表明读取的实际内容,若读取的数据后面没有内容时,返回的结果为-1。所以这里可以进行控制判断。改进的代码为:

//需要用一个整形变量来控制是否继续打印
int num = 0;
  // 注:返回的是ASCII字节码  若给一个char数组,read方法会把读取的内容放在char数组里面
while((num=fr.read())!=-1){
    System.out.print((char)num); // 返回的是ASCII字节码,所以这里需要进行一个强转
}
// 关闭流
fr.close();

虽然是一个一个的读取,但我们也可以用一个临时的字符数组来接收数据,然后一次性传输

// 定义一个整形变量 控制循环    再定义一个字符数组接收
int count = 0; 
char[] cs = new char[3];  // 数字是接收的个数
while((count = fr.read(cs))!=-1){ // 这里就加上了数组,读取的内容会放在cs数组里
    System.out.print(Arrays.toString(cs));  // 打印出数据,但这打印出的内容是数组格式
    String str = new String(cs,0,count,"UTF8"); // 把cs数组的内容以字符串的形式进行打印,后面0表示偏移量,count表示打印的个数,最后是转换时数组的文本格式
    System.out.print(str);
}
// 最后关闭流
fr.close();
2.2.2字节节点流

字节节点流是直接从源头,以字节的形式传输数据的

同样的也需要找到一个位置 这里以传输数据为例

// 找到数据源
File file = new File("E:\\javayuanwenjian\\Reborn\\W.txt");
// 创建一个写数据的对象,引用刚刚找到的数据源
FileOutputStream fos = new FileOutputStream(file); //这里表明的是把写好的数据放到我们给定的地址中去,若文件不存在,则会创建一个该文件
byte[] bt = new byte[]{3,5,8,9,7,6,4}; // 字节流 需要的是字节数组
//开始读写数据进去
fos.write(bt);  // 括号里需要参数,可以是整数类型或者字节数组。所以需要先定义一个整形变量或者字节数组  
// 这的输出内容只能是整数类型或者字节数组   若要录入非字节数组内容的话,还需要把格式转化位字节数组的格式
// String str = "abcdef";
// byte[] bs = str.getBytes();
// 刷新书写的内容
fos.flush();
// 关闭流
fos.close();

2.3处理流

处理流可以是加强传输数据的速度,可以是加多传输数据的类型,也可以是让字符字节进行转换。它们必须要套在节点流上传输数据

2.3.1缓冲处理流

缓冲理解:创建内部缓冲区数组,用一个数组来接收读写数据。导致起读写效率大大提升。

根据数据单位可分为:

缓冲字符流:BufferedReader和BufferedWriter

缓冲字节流:BufferedInputStream和BufferedOutputStream

缓冲字符流和节点流大同小异,但在声明一个缓冲处理流后,最后还是需要节点流来进行实现

注:缓冲处理流不能进行多态

2.3.1.1缓冲字符流
// 创建一个缓冲字符输入流
// 从最里层往外理解:找到一个目标文件地址-->创建一个文件输入对象-->创建一个缓冲字符输入对象
BufferedReader br = new BufferedReader(new FileReader(new File("E:\\javayuanwenjian\\Reborn\\IO1.txt")));
//在读取数据前,要先声明一个计数器--用于控制循环以及打印数据,声明一个字符数组,用于临时储存数据
int num = 0;
char[] cs = new char[6]; // 以6个字符进行接收
// 开始进行读取数据,让数据读取完,进行循环。
while((num = br.read(cs))!=-1){
    System.out.print(new String(cs,0,num))
}
System.out.println();
// 关闭流
br.close()
// 创建一个缓冲字符输出流
// 从里层往外:找到一个目标文件地址进行录入-->创建一个文件输出对象-->创建一个缓冲字符输出对象
BufferedWriter bw = new BufferedWriter(new FileWriter(new File("E:\\javayuanwenjian\\Reborn\\IO2.txt")));
// 因为需要用到的是缓冲字符 所以一定需要一个char类型的数组,用来接收数据
char[] cw = new char[6];//设定每次接收的字符,因为这里是直接输入内容。不需要这个字符数组
// 输入内容
String str = "张子枫你好啊";
// 录入
bw.write(str);
// 刷新
bw.flush();
// 关闭
bw.close();

字符的输入和输出相较于字节要简便很多,而且字符的输入输出是不能去改写文本的格式的,但如果文本格式不同时,就要考虑使用字节输入输出,去更改相匹配的格式。

// 创建一个缓冲字节输入流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("E:\\javayuanwenjian\\Reborn\\IO2.txt")));
// 声明计数器
int num = 0;
// 声明字节数组
byte[] bs = new byte[1024];
// 循环读取数据
while((num = bis.read(bs))!=-1){
new String(bs,0,num); // 直接把字节数组转化成字符串,0是偏移量,num是转化个数
}
// 关闭流
bs.close();
2.3.1.2缓冲字节流

字节输出流在进行数据输出的时候要注意到:若传送的数据是字符串,需要把字符串转成字节数组,然后再进行输出。不然输出的数据会是乱码,另:数据的文本格式要和输出的文本格式保持一致。

// 用缓冲字节输出流录入字符串 
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File("E:\\javayuanwenjian\\Reborn\\IO2.txt")));
// 声明一个字符串
String str = "abcdefghijk";
// 把这个字符串转换为字节数组
byte[] bt = str.getBytes();
// 开始读取
bos.write(bt);
// 刷新
bos.flush();
// 关闭流
bos.close();
2.3.2 转换处理流

提供了字节和字符之间的转换 实际上:把字节流转换为字符流

类:

InputStreamReader 转换输入流

OutputStreamWriter 转换输出流

2.3.2.1转换输入流

转换输入流 是把字节流转换为字符流 所以InputStreamReader 本质上还是可以看成是一个字符流。

所以这里还是用字符去进行读取的,创建临时储存数据应该用字符数组。

这是支持多态的,但是不能使用readLine()方法

// 读取文件
File file = new File("E:\\javayuanwenjian\\Reborn\\IO2.txt");
// 先创建一个字节输出流
InputStream is = new FileInputStream(file);
// 对流进行转换
Reader isr = new InputStreamReader(is,"UTF8"); //这里可以设置格式,这个格式是表示字节和字符之间的转换会以怎样的格式进行
// 准备空间和计数器
int num = 0;
char[] cs = new char[6];
// 循环读取数据
while((num = isr.read(cs))!=-1){
    System.out.print(new String(cs,0,num));
}
System.out.println();
// 关闭流
isr.close();
2.3.2.2转换输出流

转换输出流是把字节流转换为字符流,OutputStreamWriter 实际上是一个输出字符流 使用方式和输入流大同小异,注意在输出时刷新。

// 创建文件
File file = new File("E:\\javayuanwenjian\\Reborn\\IO2.txt");
// 创建一个输出字节流,选择把数据输出的位置
OutputStream os = new FileOutputStream(file);
// 把输出字节流转换为输出字符流
Writer osw = new OutputStreamWriter(os,"UTF8");
String str = "bed bed good good good 挺好的 世界很好";
osw.write(str); //这里虽然有用字节流,但是实际上还是用字符流在进行读取,所以可以直接读取汉字
// 刷新
osw.flush();
// 关闭
osw.close();

2.4数据处理流

如果把某些特定的数据类型输入在储存文件中,输出时可能就不是自己想要的类型。这个时候需要用到我们的数据处理流。数据处理流的作用是保留数据的类型,但必须是先写后读。而且输入顺序和输出顺序必须保持一致。类分别为:DataInputStream 数据输入流 DataOutputStream 数据输出流 是字节流的子类。

2.4.1数据输出流 ---写
// 目标文件地址
File file = new File("E:\\javayuanwenjian\\Reborn\\IO3.txt");
// 创建一个数据输出流
DataOutputStream dos = new DataOutputStream(new FileOutputStream(file));
// 定义一个成员变量,并把他输出在文件上
int i = 1;
// 输出这个i
dos.writeInt(i);
// 刷新
dos.flush();
// 关闭流
dos.close();
2.4.2数据输入流 ---读
// 创建一个数据输入流 目标文件地址直接
DataInputStream dis = new DataInputStream(new FileInputStream("E:\\javayuanwenjian\\Reborn\\IO3.txt"));
// 这里不能直接去接收,应该按照类型来接收
dis.readInt();
// 关闭流
dis.close();

好处:可以保留录入的数据类型。

缺点:在输出的时候一定要按照相对应的数据类型输出,否则不会保留格式。

2.5对象处理流

2.5.1序列化

序列化:用ObjectOutputStream类保存基本类型数据或对象的机制

反序列化:用ObjectInputStream类读取基本类型数据或对象的机制

序列化步骤:

1、首先需要一个类实现了Serializable接口

2、创建一个ObjectOutputStream

3、调用ObjectOutputStream对象的writeObject(对象)方法输出可序列化对象

4、写一次,需要刷新一次

2.5.2对象处理流
class Student implements Serializable{
    private static final long serialVersionUID = -5187227321050332651L;// 序列号
    // 有了这个序列号以后,在接收读取文件时,主要看序列号是否有发生改变
    // 这个类的属性增加或者改变不会影响计算机的判断
    private String name;
    private Integer age;
    public String toString(){
        return "Student{"+"name="+name+'\''+",age="+age'}';}
    public Student(){}
    public Student(String name,Integer age){
        this.name = name;
        this.age = age;
    }
}
public class ObjectStreamTest{
    public static void main(String[] args){
        //录入一个学生对象 首先需要创建一个对象输出流
        ObjectOutputStream oos = new ObjectOutpurStream(new FileOutputStream("E\\src\\student.txt"))
        // 实例化一个学生对象
        Student s1 = new Student("张子枫",18);
        // 录入该学生对象
        oos.writeObject(s1);
        // 刷新
        oos.flush();
        //关闭对象输出流
        oos.close();       
    }
}

对象输入流 方式一样

// 创建一个对象输入流
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("E\\src\\student"));
//这里要注意,我们是用Object直接去读取的,读取的对象会是一个Object对象,但内容本身是一个Student。输出内容也是Student  可以用instanceof 进行判定,然后再强转。也可以不用管,直接接收结果
Object o = new Object;
o = ois.readObject();
// 关闭流
ois.close();

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值