JAVA IO流基础
File类概述和构造方法
- File是文件和目录路径名的抽象表示
- 对于File而言,其封装的并不是一个真正存在的文件,仅仅只是一个路径名而已,它是可以存在的也是可以不存在的,将来是要通过具体的操作把这个路径的内容转换成具体存在的
File类创建功能
- 如果文件不存在,则创建文件返回true,如果文件存在,则返回false
- 如果目录不存在,则创建目录返回true,如果目录存在,则返回false
File类删除功能
- 绝对路径:完整的路径名,不需要任何其他信息就可以定位它所表示的文件,例如D:\java study\java.txt
- 相对路径:必须使用取自其他路径名的信息进行解释,例如:myFile\java.txt
- 删除目录时,如果一个目录中有内容(目录,文件),不能直接删除,应该先删除目录中的内容,最后才删除目录
- 如果目录下有一堆文件,就用list()获得当前目录下的所有文件,通过判断是文件还是目录,继续循环删除就行了
File类判断和获取功能
递归
- 以编程的角度来看,递归指的是方法定义中调用方法本身的现象
递归解决问题的思路:
- 把一个复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解
- 递归策略只需少量的程序就可以描述出解题过程中所需要的多次重复运算
递归解决问题要找到两个出口:
- 递归出口:否则会出现内存溢出
- 递归规则,与原问题相似的规模较小的问题
递归遍历目录
字节流
IO流概述和分类
- IO:输入/输出(Input/Output)
- 流:是一种抽象概念,是对数据传输的总称,也就是说数据在设备间的传输称为流,流的本质是数据传输
- IO流就是用来处理设备间数据传输问题的
- 常见的应用:文件复制,文件上传,下载
- IO流分类
- 按照数据的流向
- 输入流:读数据
- 输出流:写数据
- 按照数据类型来分
- 字节输入流;字节输出流
- 字符输入流;字节输出流
- 一般来说IO流的分类是按照数据类型来分的
- 如果数据通过window自带的记事本打开,可以读懂里面的内容就是用字符流,否则就使用字节流,如果你不知道该使用哪种类型的流,就使用字节流
字节流写数据
- 字节流抽象基类
- InputStream:这个抽象类是表示输入流的所有类的父类
- OutputStream:这个抽象类表示输出流的所有类的父类
- 子类名都是以其父类名作为其后缀
- FileOutputStream:文件输出流用于将数据写入File
- FileOutputStream(String name):创建一个文件输出流,用指定的名称写入文件。
- 使用字节输出流写数据额步骤
- 创建字节输出流对象(
- 调用字节流输出对象的写数据方法
- 释放资源
字节流写数据的3种方法
write(int b)
将指定的字节写入该文件输出流中。一次写一个字节数据write(byte[] b)
写b.length
字节从指定的字节数组来此文件输出流。一次写一个字节数组数据write(byte[] b, int off, int len)
写len
字节指定字节数组中的起始偏移off
此文件输出流。 一次写一个字节数组的部分数据
字节流写数据的两个小问题
- 字节流写完数据如何换行?
- 写完数据后,追加输入换行符
- windows:\r\n或\n
- linux:\n
- mac:\r
- 字节流写数据如何实现追加输入呢?
- 创建字节流文件时,在后面追加boolean判定true
字节流写数据加异常处理
- finally:在异常处理时提供finally块来执行所有清楚操作,比如说IO流中的释放资源
- 特点:被finally控制的语句一定会执行,除非JVM退出
字节流读数据(一次读一个数据)
- FileInputStream类:从文件系统中的文件获取输入字节
- 构造方法:
FileInputStream(String name)
打开一个连接到一个实际的文件创建一个FileInputStream
,文件由文件系统中的路径名name
命名。 - 使用字节输入流读数据的步骤
- 1,创建字节输入流对象
- 2,调用字节输入流对象的读数据方法
- 3,释放资源
字节流复制文本文件
字节流读数据(一次读一个字节数组数据)
复制图片
字节缓冲流
- 构造方法
BufferedInputStream(InputStream in)
创建一个BufferedInputStream
和保存它的参数,输入流in
,供以后使用。 当BufferedInputStream
创建,内部缓冲区创建数组。从流中读取字节或跳过,内部缓冲区将根据需要从包含的输入流重新填充,一次很多字节。 - 构造方法
BufferedOutputStream(OutputStream out)
创建一个新的缓冲输出流,将数据写入到指定的基本输出流中。 通过设置这样的输出流,应用程序可以向底层输出流写入字节,而不必为写入的每个字节导致底层系统的调用 - 输出目标的输出流将缓冲区中的内容输出到输出目标中,从而相比我们直接使用 OutputStream 的代码减少了该类中向输出流写入数据的相关方法的调用,提高了程序的性能和读写效率
- 这里指的就是计算机组成缓冲区的知识,简略而说每次读写数据需要cpu进行服务,能不能先把数据写入缓冲区再一次性输出,缓冲区就是buffer
- 字节缓冲流只仅仅提供缓冲区,而真正的读写数据还是得依靠基本的字节流对象进行操作
字节流复制视频
字符流
为什么会出现字符流
- 一个汉字存储
- 如果是GBK编码,占用2个字节
- 如果是UTF-8编码,占用3个字节
- String类的对象方法getBytes默认使用UTF-8编码来获取汉字的字节,但无论哪种编码储存第一个字节都为负数,所以在使用字节流读取字节并拼接时系统会根据编码类型来判断负数为汉字,GBK2个字节一拼,UTF-8三个字节一拼
- 但由于字节流操作中文不是特别方便,所以java提供了字符流
- 字符流 = 字节流 + 编码表(底层还是字节流)
编码表
- 计算机中储存的信息都是用二进制表示,看到的汉字英文等字符都是二进制转换后的结果
- 按照某种规则将字符存储到计算机中,称之为编码,反之按照某种规则解析显示为解码
,按照A编码存储就必须按照A编码解析,如果不按指定编码解析,则会出现乱码
- 字符集
- 是一个系统支持的所有字符的集合,包括各个国家文字,标点符号,图形符号,数字等
- 计算机要准确的存储和识别各种字符集符号,就需要进行字符编码,一套字符集必然至少有一套字符编码,常见字符集有ASCII字符集,GBXXX字符集,Unicode字符集
- ASCII字符集
- 美国信息交换标准代码,基于拉丁字母的一套电脑编码系统,主要显示现代英文,用7位表示一个字符,共128字符,扩展字符集用8位表示一个字符,共256字符,方便支持欧洲常用字符,是一个系统支持的所有字符的集合
- GBXXX字符集
- GB2312:简体中文码表,小于127的字符意义与原来相同,但大于127的字符连在一起就表示一个汉字,包含了7000多个简体汉字,此外数学符号,罗马希腊的字母,日文的假名等都编进去了,连在ASCII里本来就有的数字标点字母等都通通编了两个字节长的编码,这就是常说的“全角”字符,原来在127号以下的叫“半角”字符
- GBK:最常用的中文码表,在GB2312的标准基础上的扩展规范,使用了双字节的编码方案,共收录了21003个汉字,完全兼容GB2312标准,同时支持繁体汉字以及日韩汉字等
- GB18030:最新的中文码表,收录汉字70244个,采用多字节编码,每个字可以由1个,2个或者4个字节组成,支持中国国内少数民族的文字,同时支持繁体汉字和日韩汉字
- Unicode字符集
- 为表达任意语言的任意字符而涉及,是业界的一种标准,标准万国码,他最多使用4个字节的数字来表达每个字符,符号,或者文字,有三种编码方案,UTF-8,UTF-16和UTF32,最常用的为UTF-8编码
- UTF-8编码:可以用来表示Unicode标准中的任意字符,它是电子邮件,网页以及其他储存或传输文字的应用中,优先采用的编码,互联网工程工作小组(IEIT)要求所有的互联网协议都必须支持UTF-8编码,它使用1-4个字节为每个字符编码
- 128个US-ASCII字符,只需要一个字节编码
- 拉丁文等字符,需要2个字节编码
- 大部分常用字(含中文),使用3个字节编码
- 其他极少使用的Unicode辅助字符,使用4字节编码
- 小结:采用何种规则字符编码,就要采用对应规则解码,否则就会出现乱码
字符串中的解码编码问题
字符流中的编码解码问题
- 字符流抽象父类
- Reader:字符输入流的抽象类
- Writer:字符输出流的抽象类
- 字符流中编码解码问题相关的两个类
- InputStreamReader
- 是字节流到字符流的桥梁,它读取字节,并使用指定的charset将其解码为字符,它使用的字符集可以由名称指定
- OutputStreamWriter
- 是字符流到字节流的桥梁,使用默认或指定的charset将写入的字符编码为字节
字符流写数据的5种方式
- 补充
- flush() :刷新流,还可以写数据
- close():关闭流,释放资源,但是在关闭前会先刷新流,一旦关闭,就不能再写数据
字符流读数据的两种方法
字符流复制java文件以及改进版
若是无编码转码的需求则可以使用更简洁的字符流读写类
- FileReader(String fileName)
- FileWriter(String fileName)
数据源:xxx.java----读数据----Reader(由于是抽象类)----InputStreamReader(自带编码解码转换)----FileReader(无编码解码需求则可以使用更加简洁)
目的地:xxxcopy.java----写数据----Writer(由于是抽象类)----OutputStreamWriter(自带编码解码转换)----FileWriter(无编码解码需求则可以使用更加简洁)
字符缓冲流
字符缓冲流复制文件可将上面的普通字符流复制代码加入缓冲流即可
字符缓冲流特有功能
复制java文件(使用字符缓冲流特有功能改进)
IO流小结
- 由于这两个流都是抽象类,我们使用以下各两种的子类
- 接下来是字符流