初步了解JAVA的IO

本文详细介绍了JAVA的IO系统,从File类的使用到字节流、字符流的操作,包括FileOutputStream、FileInputStream、Reader、Writer等类的使用方法。还涉及到了缓冲流、字符编码、序列化和反序列化以及打印流和TCP通信的基础知识。通过实例展示了文件的读写、数据传输和异常处理等关键概念。
摘要由CSDN通过智能技术生成

File类

  • 是文件和目录路径名的抽象表示,主要用于文件和目录的创建、查找和删除等操作。
  • 是一个与系统无关的类,任何操作系统都可以使用这个类中的方法。

静态成员变量

  • String pathSeparator 与 char pathSeparatorChar。与系统有关的路径分隔符(两个类型不一样)windows;分号,linux:冒号。
  • String separator 与 char separatorChar。与系统有关的默认名称分隔符。windows \ 反斜杠,linux / 正斜杠。

绝对路径和相对路径

  • 绝对路径:从盘符开始的路径,这是一个完整的路径。
  • 相对路径:相对于项目目录的路径,这=是一个便捷的路径。
  • 注意:路径不区分大小写,文件名称分隔符windows使用反斜杠,反斜杠是转义字符,两个反斜杠代表一个普通的反斜杠。

文件过滤器

  • File类中有两个ListFiles重载的方法,方法的参数传递的就是过滤器。
  • File[] listFiles(FileFilter filter):java.io.FileFilter接口:用于抽象路径名(File对象)的过滤器。包含抽象方法:boolean accept(File pathname) 。参数:File pathname:使用ListFiles方法遍历目录,得到的每一个文件对象。
  • File[] listFiles(FilenameFilter filter):java.io.FilenameFilter 接口:实现此接口的类实力可用于过滤文件名。抽象方法:boolean accept(File dir, String name) 。参数:File dir,File构造方法中传递的被遍历的目录;String name,使用ListFiles方法遍历目录,获取的每一个文件/文件夹的名称。
  • 注意:两个过滤器接口都没有实现类,需要自己写实现类,重写过过滤方法accept,在里面定义过滤规则。

过滤器原理

  • File对象调用listFiles方法做了3件事,一:对构造方法中传递的目录进行遍历,获取目录中的每一个文件/文件夹,封装为File对象;二:调用参数传递的过滤器中的方法accept;三:把遍历得到的每一个File对象,传递进accpet方法的参数pathname。
  • accpet方法返回值是布尔值。为true则会把传递过来的File对象保存到File数组中;为false则不会保存到File数组中。

IO分类

  • 输入流 :把数据从 其他设备 上读取到 内存 中的流。
  • 输出流 :把数据从 内存 中写出到 其他设备 上的流。
  • 字节流 :以字节为单位,读写数据的流。
  • 字符流 :以字符为单位,读写数据的流。

顶级父类

*输入流输出流
字节流字节输入流 InputStream字节输出流 OutputStream
字符流字符输入流 Reader字符输出流 Writer

OutputStream字节输出流

  • 是抽象类,表示字节输出流的所有类的超类,将指定的字节信息写出到目的地。
  • 写入数据(内存到硬盘)原理:java程序–>JVM–>os(操作系统)–>os调用写数据方法–>把数据写入到文件中

FileOutputStream类

OutputStream其中一个子类。文件字节输出流。
使用步骤

  • 创建一个FileOutputStream对象,构造方法中传递写入数据的目的地。
  • 调用FileOutputStream对象中的write方法,把数据写入到文件中。
  • 释放资源。(流使用会占用一定的内存,使用完毕要把内存清空,提供程序的效率)

注意

  • 写数据的时候会把十进制的整数转化为二进制的整数。硬盘中存储的数据都是字节,1字节=8比特位(10101010)。
  • 字符串中方法getBytes()可以快速获取字节数组。
  • 如果读写流都在,先释放写的,后关闭读的。如果写完了,肯定读取完毕了。

数据追加续写
构造方法中存在参数boolean append,true表示追加数据, false 表示清空原有数据。
换行写
Windows系统里,换行符号是 \r\n 。linux里 /n。mac里 /r。

InputStream字节输入流

  • 是抽象类,表示字节输入流的所有类的超类,可以读取字节信息到内存中。
  • 写入数据(硬盘到内存)原理:java程序–>JVM–>os(操作系统)–>os调用读取数据方法–>读取文件

FileInputStream类

InputStream其中一个子类。文件字节输入流。
使用步骤

  • 创建FileInputStream对象,构造方法中绑定要读取的数据源。
  • 使用FileInputStream对象中的read方法,读取文件。
  • 释放资源。

注意
read方法读取到-1表示结束。

// 循环读取
while ((b = fis.read())!=‐1) {
	System.out.println((char)b);
}

Reader字符输入流

  • 是抽象类,表示用于读取字符流的所有类的超类,可以读取字符信息到内存中。
  • 字节流遇到中文字符时,可能不会显示完整的字符,因为一个中文字符可能占用多个字节存储。字符流类,以字符为单位读写数据,专门用于处理文本文件。

FileReader类

InputStreamReader的子类,InputStreamReader继承Reader。文件字符输入流。
使用步骤

  • 创建FileReader对象,构造方法中绑定要读取的数据源。
  • 调用FileReader对象中的read方法,读取文件。
  • 释放资源。

Writer字符输出流

是抽象类,表示用于写出字符流的所有类的超类,将指定的字符信息写出到目的地。

FileWriter类

OutputStreamWriter的子类,OutputStreamWriter继承Writer。文件字符输出流。
使用步骤

  • 创建FileWriter对象,构构造方法中绑定要写入数据的目的地。
  • 调用FileWriter对象中的write方法,把数据写入到内存缓冲区中。(字符转换为字节的过程)
  • 使用FileWriter中的flush方法,把内存缓冲区中的数据刷新到文件中。
  • 释放资源。(会先把内存缓冲区中的数据刷新到文件中)

关闭和刷新

  • flush :刷新缓冲区,流对象可以继续使用。
  • close :先刷新缓冲区,然后通知系统释放资源。流对象不可以再被使用了。

IO异常的处理

JDK1.7之前使用 try…catch…finally 代码块处理

// 声明变量
FileWriter fw = null;
try {
	//创建流对象
	fw = new FileWriter("fw.txt");
	// 写出数据
	fw.write("程序员");
} catch (IOException e) {
	e.printStackTrace();
} finally {
	try {
		if (fw != null) {
			fw.close();
		}
	} catch (IOException e) {
		e.printStackTrace();
	}
}

JDK7优化后的 try-with-resource 语句

try (创建流对象语句,如果多个使用';'隔开) {
	// 读写数据
} catch (IOException e) {
	e.printStackTrace();
}

JDK9中 try-with-resource 的改进,对于引入对象的方式,支持的更加简洁。

A a = new A();
B b = new B();
try(a, b) {
	// 可能产生异常的代码
}

属性集

  • java.util.Properties 继承于 Hashtable,实现了Map接口。
  • Properties 表示一个持久的属性集。可保存在流中或者从流中加载。
  • Properties 每个键及其对应值都是一个字符串。

基本方法

  • Object setProperty(String key, String value) : 保存一对属性。相当于put方法。
  • String getProperty(String key) :通过key找到value值。相当于get(key)方法。
  • Set<String> stringPropertyNames() :所有键的名称的集合。相当于keySet()方法。

与流相关的方法

  • Properties 集合是唯一一个和IO流相结合的集合。
  • 可以使用Properties集合中的stroe方法,把集合中的临时数据,持久化写入到硬盘中存储。
  • 可以使用Properties集合中的load方法,把硬盘中保存的文件(键值对),读取到集合中使用。
  • void stroe(流,String comments):comments注释,不能使用中文会产生乱码。中文文件,流建议使用字符流。
  • void load(流):加载的文件中,键值对形式,默认的链接符号可以使用=,空格或其他符号;可以使用#进行注释;键与值默认都是字符串,不需要再加引号。

缓冲流

  • 缓冲流,也叫高效流。基本原理是在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO次数,从而提高读写的效率。
  • 字节缓冲流: BufferedInputStream ,BufferedOutputStream
  • 字符缓冲流: BufferedReader , BufferedWriter

BufferedOutputStream类

字节缓冲输出流BufferedOutputStream继承OutputStream。
使用步骤

  • 创建FileOutputStream对象,构造方法中绑定要输出的目的地。
  • 创建BufferedOutputStream对象,构造方法中传递FileOutputStream对象,提高FileOutputStream对象的效率。
  • 使用BufferedOutputStream对象中的write方法,把数据写入到内部缓冲区中。
  • 使用BufferedOutputStream对象中的flush方法,把内部缓冲区的数据刷新到文件中。
  • 释放资源。(会先调用flush方法刷新数据,上一步可以省略)

BufferedInputStream类

字节缓冲输入流BufferedInputStream继承InputStream。
使用步骤

  • 创建FileInputStream对象,构造方法中绑定要读取的数据源。
  • 创建BufferedInputStream对象,构造方法中传递FileInputStream对象,提高FileInputStream对象的效率。
  • 使用BufferedInputStream对象中的read方法,读取文件。
  • 释放资源。

BufferedWriter类

字符缓冲输出流BufferedWriter继承Writer。
特有方法
void newLine():写入一个行分隔符,会根据不同操作系统,获取不同的行分隔符。
使用步骤

  • 创建字符缓冲输出流BufferedWriter对象,构造方法中传递字符输出流FileWriter。
  • 使用字符缓冲输出流BufferedWriter对象中的write方法,把数据写入到内存缓冲区中。
  • 使用字符缓冲输出流BufferedWriter对象中的flush方法,把内存缓冲区的数据刷新到文件中。
  • 释放资源。

BufferedReader类

字符缓冲输入流BufferedReader继承Reader。
特有方法

  • String readLine():读取一个文本行。读取一行数据。
  • 行的终止符:通过下列字符之一即可任维某行已终止:换行(‘\n’)、回车(‘\r’)或回车后直接跟着换行(\r\n)。
  • 返回值:包含该行内容的字符串,不包含任何终止符,如果已到达流末尾,则返回null。

使用步骤

  • 创建字符缓冲输入流BufferedReader对象,构造方法中传递字符输入流FileReader。
  • 使用字符缓冲输入流BufferedReader对象中的read/readLine方法读取文本。
  • 释放资源。

字符编码和字符集

  • 字符编码 Character Encoding : 就是一套自然语言的字符与二进制数之间的对应规则。
  • 字符集 Charset :也叫编码表。是一个系统支持的所有字符的集合,包括各国家文字、标点符号、图形符号、数字等。常见字符集有ASCII字符集、GBK字符集、Unicode字符集等。

编码引出的问题
于Windows系统的默认是GBK编码,用UTF-8 编码读取就会出现乱码。所以使用转换流来解决。

OutputStreamWriter类

  • 转换流OutputStreamWriter继承Writer,直接已知子类是FileWriter。
  • 是从字符流到字节流的桥梁。使用指定的字符集将字符编码为字节。(编码)

使用步骤

  • 创建OutputStreamWriter对象,构造方法中传递字节输出流FileOutputStream和指定的编码表名称。(不指定编码表名称默认是UTF-8)
  • 使用OutputStreamWriter对象中的write方法,把字符转换为字节存储缓冲区中。(编码)
  • 使用OutputStreamWriter对象中的flush方法,把内存缓冲区的字节刷新到文件中。(使用字节流写字节的过程)
  • 释放资源。

InputStreamReader类

  • 转换流InputStreamReader继承Reader,直接已知子类是FileReader。
  • 是从字节流到字符流的桥梁。读取字节,并使用指定的字符集将其解码为字符。(解码)

使用步骤

  • 创建InputStreamReader对象,构造方法中传递字节输入流FileInputStream和指定的编码表名称。(不指定编码表名称默认是UTF-8)
  • 使用InputStreamReader对象中的read方法读取文件。
  • 释放资源。

注意
构造方法中指定的编码表名称要和文件的编码相同,否则会发生乱码。

序列化

  • 对象序列化的机制。用一个字节序列可以表示一个对象,该字节序列包含该对象的数据、对象的类型和对象中存储的属性等信息。字节序列写出到文件之后,相当于文件中持久保存了一个对象的信息。
  • 反序列化。 对象的数据、对象的类型和对象中存储的数据 信息,都可以用来在内存中创建对象。

ObjectOutputStream类

对象的序列化流,继承OutputStream。把对象意流的方式写入到文件中保存。

特有成员方法
void writeObject(Object obj):将指定的对象写入ObjectOutputStream。

使用步骤

  • 创建ObjectOutputStream对象,构造方法中传递字节输出流FileOutputStream。
  • 使用ObjectOutputStream对象中的writeObject方法,把对象写入到文件中。
  • 释放资源。

注意

  • 对象类需实现Serializable接口以启用其序列化功能。未实现此接口将无法使其任何方法序列化或反序列化。
  • Serializable接口也叫标记型接口,进行序列化和反序列化的时候,检测类上有这个标记才会进行,没有就会抛出NotSerialzableException异常。

ObjectInputStream类

对象的反序列化流,继承InputStream。将序列化的原始数据恢复为对象。

特有成员方法
Object readObject():从ObjectOutputStream读取对象。

使用步骤

  • 创建ObjectOutputStream对象,构造方法中传递字节输入流FileInputStream。
  • 使用ObjectOutputStream对象中的readObject方法读取保存对象的文件。
  • 释放资源。
  • 使用读取出来的对象

注意

  • readObject()方法声明抛出ClassNotFoundException(class文件找不到异常)。反序列化前提是,类必须实现Serializable;必须存在类对应的class文件。
  • 反序列化时,能找到class文件,但class文件再序列化对象之后发生了修改,也会反序列化失败,抛出 InvalidClassException 异常。
  • 修改序列化对象解决:手动添加一个序列号,无论是否对类进行修改,都不生成新的序列号。如:修饰符 static final long serialVersionUID = 1L;

transient关键字
瞬态关键字,修饰的成员变量不能被序列化。

static关键字
静态关键字,静态优先于非静态加载到内存中(静态优先于对象进入到内存中)。被static修饰的成员变量不能被序列化,序列化的都是对象。

打印流

能够方便地打印各种数据类型的值,是一种便捷的输出方式。

PrintStream类

继承OutputStream。

特点

  • 只负责数据的输出,不负责数据 的读取。
  • 与其他输出流不同,PrintStream永远不抛出IOExcption。
  • 特有方法print,println 输出任意类型的值。

注意

  • 使用继承自父类的write方法写数据,那么查看输出时候会查询编码表。
  • 使用自己特有的方法print,println写数据,写的数据原样输出。
  • System.out.println() 输出再控制台。使用System.setOut(PrintStream) 方法,会改变输出语句的目的地,改为参数中传递的打印流的目的地。

TCP通信程序

  • TCP通信能实现两台计算机之间的数据交互,通信的两端,要严格区分为客户端(Client)与服务端(Server)。
  • 服务端程序,需要事先启动,等待客户端的连接。
  • 客户端主动连接服务器端,连接成功才能通信。服务端不可以主动连接客户端。

Socket类

该类实现客户端套接字,套接字指的是两台设备之间通讯的端点。包含了IP地址和端口号的网阔单位。

实现步骤

  • 创建一个客户端Socket对象,构造方法方法绑定服务器的IP地址和端口号。
  • 使用Socket对象中的方法getOutputStream()获取网络字节输出流OutputStream对象。
  • 使用网络字节输出流OutputStream对象中的write方法,给服务器发送数据。
  • 使用Socket对象中的方法getInputStream()获取网络字节输入流InputStream对象。
  • 使用网络字节输入流InputStream对象中的read方法,读取服务器回写的数据。
  • 释放资源。(Socket)

注意

  • 客户端与服务器端进行交互,必须使用Socket中提供的网络流,不能使用自己创建的流对象。
  • 创建客户端对象Socket的时候,会去请求服务器和服务器进行3次握手建立连接通路。如果服务器没有启动,就会抛出异常;如果服务器已经启动,可以进行交互。

阻塞状态

  • 当服务器网络字节输入流InputStream对象中read方法一直未读取到结束标记,就会进入阻塞状态。
  • 需要在客户端,使用Socket对象的shutdownOutput()方法,禁用此套接字的输出流。

ServerSocket类

该类实现了服务器套接字。接受客户端的请求,读取客户端发送的数据,回写数据给客户端。

实现步骤

  • 创建服务器ServerSocket对象和系统要指定的端口号。
  • 使用ServerSocket对象中accept方法,获取请求的客户端对象Socket。
  • 使用Socket对象中getInputStream()方法获取网络字节输入流InputStream对象。
  • 使用网络字节输入流InputStream对象中read方法,读取客户端发送的数据。
  • 使用Socket对象中getOutputStream()方法获取网络字节输出流OutputStream对象。
  • 使用网络字节输出流OutputStream对象中write方法,给客户端回写数据。
  • 释放资源。(Socket,ServerSocket)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值