Java I/O

目录

一、File类

 二、IO流

三、Java流的分类

四、字节流

1、什么是字节流?

2、字节输出流的基类:OutputStream

3、字节输出流FileOutputStream类

4、字节输出流FileOutputStream类应用示例

5、字节输入流的基类:InputStream

6、字节输入流FileInputStream类

7、使用FileInputStream类按单字节读取数据

8、使用FileInputStream类按多字节读取数据

五、字符流

1、问题:

2、字符输出流的基类:Writer

3、字符输出流FileWriter类

4、字符输入流基类:Reader

5、字符输入流FileReader类

六、缓冲流

1、问题

2、BufferedWriter类

3、使用 BufferedWriter 写文件

4、BufferedReader类

七、数据操作流

1、数据操作流程简介

2、DataOutputStream类

3、DataInputStream类

4、使用数据操作流读写二进制文件

八、序列化与反序列化

1、使用ObjectOutputStream类实现序列化

2、使用ObjectInputStream类实现反序列化

九、IO流小结

十、本章总结


一、File类

File类是java.io包下代表操作与平台无关的文件和目录的类

实现对文件或目录的新建、删除、重命名等操作

 一个File类的对象可以代表一个文件或目录 ​

可获取与文件相关的信息,如名称、修改日期、文件大小等

语法:

public File(String pathName);//pathName:文件路径

绝对路径: 以根目录开头的完整路径

相对路径: 相对于当前目录文件的路径

“.”表示当前目录

“…”表示上级目录

注意事项: Windows文件路径名中,分隔符可以使用正斜杠“/”,也可以使用反斜杠“\”。但必须写成“\ ”,其中第一个“\”表示转义符

File类的常用方法

 二、IO流

File类能够实现对文件和目录的创建、删除等基础性操作,但是无法实现对文件的读写操作。如何读写文件?

IO流是指一连串流动的字符,以先进先出方式发送信息的通道

I:input,指读入操作

O:output,指写出操作

Java把所有流类型都封装到java.io包中,以实现输入/输出操作

三、Java流的分类

Java流的分类

按流向划分:输入流和输出流 ​

按处理单元划分:字节流和字符流 ​

按流的角色划分:节点流和处理流 ​

按流向划分:输入流和输出流

输入流

只能从中读取数据,而不能写入数据的流,实现程序从数据源中读数据

 输出流

只能从中读取数据,而不能写入数据的流,实现程序从数据源中读数据

 输入流主要由InputStream和Reader作为基类

输出流则主要由OutputStream和Writer作为基类

都是抽象类,无法直接实例化对象

注意事项

按照流的流向进行分类时,输入流完成数据读入操作,输出流完成数据写出操作,这里的“出”和“入”一定是从程序运行所在内存的角度来论述。

按处理单元划分:字节流和字符流

字节流

以8位字节为操作数据单元的流,可操作二进制数据

可细分为字节输入流、字节输出流

字符流

以16位字符为操作数据单元的流,可操作文本数据

可细分为字符输入流、字符输出流

 区别

操作的数据单元不同 ​

使用方法几乎相同

按流的角色划分:节点流和处理流

节点流

可以直接向一个特定的存储介质(如磁盘、文件)读写数据的流

使用节点流进行读写数据操作时,程序直接连接到数据源

处理流

对已存在的流进行连接和封装,通过封装后的流实现数据读写操作的流

使用处理流进行读写操作时,程序并不会直接连接到实际的数据源

使用处理流包装节点流,通过处理流执行输入和输出功能,让节点流与文件或磁盘等存储设置交互,可隐藏底层节点流的差异

四、字节流

1、什么是字节流?

具有输入和输出操作

主要操作byte类型数据

基类

字节输出流类: OutputStream ​

字节输入流类: InputStream

2、字节输出流的基类:OutputStream

是抽象类,必须使用该类的子类进行实例化对象

常用方法

 如果需要操作文件,则使用FileOutputStream实例化

3、字节输出流FileOutputStream类

使用OutputStream类的FileOutputStream子类向文本文件写入数据

常用构造方法

方法描述
FileOutputStream( File file)创建向指定File对象写数据的文件输出流 file:指定目标文件的对象
FileOutputStream( String name)创建向指定路径的文件写数据的文件输出流 name:指定目标文件的路径字符串
FileOutputStream( String name, boolean append)创建一个向指定路径的文件写入数据的文件输出流 name:指定目标文件的路径字符串 append:表示是否在文件末尾追加数据。如果为true,则表示可以在文件末尾追加数据

创建文件输出流对象的常用方式

使用FileInputStream类按多字节读取数据//方式一:使用File对象构造对象
File file = new File("D:\\mydoc\\test.txt");
OutputStream fos = new FileOutputStream(file);
//方式二:使用文件路径构造对象
OutputStream fos = new FileOutputStream("D:\\doc\\test.txt");
//方式三:使用文件路径构造对象,且可向文件末尾追加数据
OutputStream fos = new FileOutputStream("D:\\doc\\test.txt",true);

4、字节输出流FileOutputStream类应用示例

注意事项

    创建输出流对象、执行写操作、关闭输出流时都可能会有IOException异常发生,因 此,除处理FileNotFoundException异常外,还需处理IOException异常。

5、字节输入流的基类:InputStream

从文件中读数据,与OutputStream一样,也是抽象类

常用方法

6、字节输入流FileInputStream类

使用InputStream类的FileInputStream子类实现文本文件内容的读取

常用构造方法

方法描述
FileInputStream(File file)用于创建从指定File对象读取数据的文件输入流 file:指定目标文件数据源对象
FileInputStream(String name)用于创建从指定路径的文件读取数据的文件输入流 name:指定目标文件数据源路径字符串

创建文件输入流对象的常用方式

//方式一:使用File对象构造对象
File file = new File("D:\\doc\\test.txt");
InputStream fis = new FileInputStream(file);
//方式二:使用文件路径构造对象
InputStream fis = new FileInputStream("D:\\doc\\test.txt");

从文件读取到计算机内存中的过程

 read()方法

每次读取一个字节(0~255的整数)

每次读取多个字节

读取文件中全部数据

while( (data=fis.read()) != -1 ) {
   System.out.print((char)data);
}

注意事项

  1. 按字节读取并显示数据时需进行强制类型转换

  2. 使用read()读取文件中的数据时,当返回结果为-1时,即输入流已经读到末尾

  3. 在创建输入流对象、读取数据、关闭流时必须进行异常处理

7、使用FileInputStream类按单字节读取数据

从D:/doc/test.txt文件以字节为单元读取数据,输出到控制台

8、使用FileInputStream类按多字节读取数据

结论:

文本文件保存时,采用GBK编码方式,每个中文占2个字节

read()方法一次读取1个字节(半个中文字符)

当数组长度不足时,可能导致中文乱码

五、字符流

1、问题:

一个字符占用内存的两个字节

如果用字节流处理文本文件,需要将字节转换成字符,会降低程序的执行效率,怎么办?

     当输入和输出是文本文件时,尽量使用字符流

     使用Reader类和Writer类操作字符

基类

     字符输出流类:Writer

     字符输入流类:Reader

使用字符流读写文本更合适

2、字符输出流的基类:Writer

抽象类

常用方法

方法描述
void write(String str)将str字符串中包含的字符输出到输出流中
void write(String str, int off, int len)将字符串中从off位置开始,长度为len的字符输出到输出流中
void close()关闭输出流
void flush()刷新输出流

3、字符输出流FileWriter类

概念:

FileWriter类是Writer类的子类

以字符为数据处理单元向文本文件中写数据

4、字符输入流基类:Reader

是抽象类

常用方法

方法描述
int read()从输入流中读取单个字符,返回所读取的字符数据
int read(char[] c)从输入流中最多读取c.length个字符数据,并将其存储在字符数组c中,返回实际读取的字符数
int read(char[] c, int off, int len)从输入流中最多读取len个字符的数据,并将其存储在字符数组c中 存入数组c中时,并不是从数组起点开始,而是从off位置开始,返回实际读取的字符数

5、字符输入流FileReader类

FileReader是Reader类的子类

六、缓冲流

1、问题

如何提高读写文件数据的执行效率?

     java.io包提供了缓冲流

Java缓冲流自身并不具有IO功能,只是在别的流上增加缓冲,以提高程序性能

分类

   字节缓冲流 ​

   字符缓冲流 ​

       BufferedWriter类 ​

       BufferedReader类

 这里我们以字符缓冲流为例,介绍缓冲流的用法

BufferedReader类的缓冲区(它可以先把一批数据读到缓冲区,接下来的读操作都是从缓冲区内获取数据,避免每次都从数据源读取数据进行字符编码转换,从而提高读取操作的效率)

2、BufferedWriter类

   是Writer类的子类

   带有缓冲区

   默认情况下,只有缓冲区满的时候,才会把缓冲区的数据真正写到目的地,能减少物 理写数据的次数,提高输入/输出操作的执行效率

常用的构造方法

方法描述
BufferedWriter(Writer out)创建一个缓冲字符输出流

使用FileWriter类与BufferedWriter类,可提高字符流写文本文件的效率

3、使用 BufferedWriter 写文件

4、BufferedReader类

   BufferedReader类是Reader类的子类

   带有缓冲区,提高文件读取的效率

   把一批数据读到缓冲区

   从缓冲区内获取数据

常用构造方法

方法描述
BufferedReader(Reader in)创建一个缓冲字符输入流

    readLine()方法

      按行读取文件中数据

七、数据操作流

1、数据操作流程简介

数据操作流主要实现对二进制文件读写操作

分类

    DataOutputStream类

         OutputStream类的子类

         与FileOutputStream类结合使用写二进制文件

使用DataOutputStream类写二进制文件的实现步骤与FileOutputStream类写文本文件相似 DataInputStream类

         InputStream类的子类

         与FileInputStream类结合使用读取二进制文件

使用DataInputStream类读取二进制文件的实现步骤与FileInputStream类读取文本文件相似

2、DataOutputStream类

按照与平台无关的方式向流中写入基本数据类型的数据

        如int、float、long、double和boolean等

使用writeUTF()方法能写入采用utf-8字符编码的字符串

FileOutputStream out1 = new FileOutputStream("D:\\doc\\test.txt");
BufferedOutputStream out2 = new BufferedOutputStream(out1);
DataOutputStream out = new DataOutputStream(out2);
out.writeByte(1);
out.writeLong(2);
out.writeChar('c');
out.writeUTF("hello");

3、DataInputStream类

按照与平台无关的方式从流中读取基本数据类型的数据

      如int、float、long、double和boolean等

使用readUTF( )方法能读取采用utf-8字符编码的字符串

FileInputStream in1 = new  FileInputStream("D:\\doc\\test.txt");
BufferedInputStream in2 = new BufferedInputStream(in1);
DataInputStream in = new DataInputStream(in2);
System.out.println(in.readByte());
System.out.println(in.readLong());
System.out.println(in.readChar());
System.out.println(in.readUTF());

4、使用数据操作流读写二进制文件

八、序列化与反序列化

问题:

   为每个对象属性一一编写读写代码,过程很繁琐且非常容易出错,如何解决?

方案:

   使用序列化和反序列化,方便数据传输和存储

概念:

   序列化是将对象的状态存储到特定的存储介质中的过程,

   反序列化是将特定的存储介质中数据重新构建对象的过程

 对象输出流( ObjectOutputStream ):实现序列化

对象输入流( ObjectInputStream):实现反序列化

1、使用ObjectOutputStream类实现序列化

序列化的对象所属类须为可序列化的类

一个类实现java.io.Serializable接口,该类的对象是可序列化的

//一个标识接口
public interface Serializable{}

JDK1.8类库中,有些类实现了java.io.Serializable接口

    如:String类、包装类和日期时间类等

创建一个Person类,并标记该类的对象是可序列化的

import java.io.Serializable;
public class Person implements Serializable {
    private String name;
    private int age;
    private String sex;
    //省略getter/setter
    public void print() {
        System.out.println("姓名:"+this.name+",年龄:"+this.age+",性别:"+this.sex+"。");
    }
}

常用方法

方法描述类型
ObjectOutputStream(OutputStream out)创建对象输出流对象构造方法
final void writeObject(Object obj)将指定对象写入流实例方法

如何解决序列化和反序列化的版本不一致问题?

引入serialVersionUID常量

serialVersionUID常量为long类型

JVM在编译时自动生成serialVersionUID常量,也可显式定义

在Person类中显式定义serialVersionUID常量

import java.io.Serializable;
public class Person implements Serializable {
    //serialVersionUID常量
    private static final long serialVersionUID=1L;
    
    private String name;
    private int age;
    private String sex;
    public void print() {
        System.out.println("姓名:"+this.name+",年龄:"+this.age+",性别:"+this.sex+"。");
    }
}

2、使用ObjectInputStream类实现反序列化

使用对象输出流ObjectInputStream可以还原序列化的对象

常用方法

方法描述类型
ObjectInputStream(InputStream in)创建对象输入流对象构造方法
final Object readObject()从指定位置读取对象实例方法

readObject() 返回一个Object类型的对象,如果确定该Object对象的真实类型,则可以将该对象强制转换成其真实类型

九、IO流小结

Java常用IO流有哪些?

  •     所有的基类都是抽象类,无法直接创建实例,需要借助其实现类
  •    所有输出流实现写数据,所有输入流实现读数据
  •   输入和输出是相对程序而言
  •   所有的文件流直接与存储介质关联,需指定物理节点

经验:

  1. 在操作文本文件时,应使用字符流 ​
  2. 字节流可以处理二进制数据,它的功能比字符流更强大 ​
  3. 如果是二进制文本,应考虑使用字节流

十、本章总结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值