IO流:存储和读取数据的解决方案
内存内存储数据的特点:不能永久化存储数据,程序停止,数据丢失
File表示系统中的文件或者文件夹的路径:可以获取文件的信息,判断文件的类型,创建文件/文件夹,删除文件/文件夹
只能对文件本身进行操作,不能对文件内的数据进行操作
IO流 用于读写文件中的数据(可以读写文件或者网络中的数据)
写出数据:output
加载数据/读取数据:input
以程序/内存为参照物,写文件就是程序向外写出文件,就是程序往外输出文件,所以是output,读文件就是将程序外的文件加载到程序内部,也就是input
IO流分类
流的方向:输入流 输出流
操作文件的类型:字节流 ->可以操作所有类型的文件,字符流->只可以操作纯文本文件 word不是纯文本文件
纯文本文件的定义:Windows自带的记事本打开能读懂
IO流的体系
字节流:字节输入流 InputStream 字节输入流 OutputStream
FileInputStream BuffInputStream ObjectInputStream
字符流:Reader 字符输入流 Writer 字符输出流
FileOutputStream:操作本地文件的字节输出流,可以吧程序中的数据写到本地文件中
步骤:
1.创建字节输出流对象
2.写数据
3.释放资源/绝大部分流的资源都要释放
FileOutputStream fos = new FileOutputStream(new File(“”),append);
append默认值为false,如果不写或者不声明,都是false,修改为true之后就再原来的文件内部的数据追加,而不会把原有的内容删除,
1.参数是字符串表示的路径或者是File对象都是可以的
2.如果文件不存在会创建一个新的文件,但是要保证父级路径是存在的
3.如果文件已经存在,则会清空文件
write:
1.writer(int b)方法的参数是整数,但是实际上写到本地文件中的整数在ASCII上对应的字符
writer (int b) / (byte[] b) / (byte[] b //存放数据的数组, int off //起始索引 , int len //个数 )
getBytes(); 返回值是将要输入的对象转化为数组类型
FileInputStream:操作本地文件的字节输入流,可以把本地文件中的数据读取到程序中;
Input是以程序为参照物,将程序外部的数据写入到程序内部
read的返回值是int类型的(通过读到的数据在ASCII表内对应的数据)
read方法读取数据时,读到结尾后继续读取的返回值是-1;
FileInputStream细节:
创建字节输入流对象:
1.当文件不存在直接报错?
输出流:当文件不存在会创建
输入流:当文件不存在,寻找不到数据直接报错
文件读取到文件末,read方法返回-1
read方法读取一次数据就移动一次指针,并不会保存,
循环读取:
len = fis.read() 将读取到的数据赋给len len用来保存读取到的数据
FileInputStream的读取问题
read(数组) 一次读一组数据 每次尽可能给数组装满(每次读取到的数据写入到数组之中,只是覆盖原来数组内的数据,没有涉及到的数据,并不会被清空)
read返回值为-1 当且仅当读取数据时的起始位置为文件内数据结尾,才会返回-1, 否则还返回被部分重新读取到的数据覆盖后的数组 并不会返回-1
try..catch finally里面的代码一定被执行,除非虚拟机停止
AutoCloseable:在特定情况下,可以自动释放资源
实现了AutoCloseable接口的方法,可以再try后面加(),()内在JDK7时可以创建流对象,在JDK9时可以直接放流对象
计算机存储规则:任和数据都是以二进制的形式来存储的
高位字节二进制一定是1开头,转成十进制后就是一个负数
英文补位是以0补位,中文是以1补位,为了与英文区分开来
UTF -8 :用1-4个字节保存 不是一个字符集,是Unicode字符集的一种编码方式
1.一个英文占一个字节,二进制第一位是0,转成十进制是正数
2.一个中文占三个字节,二进制第一位是1,第一个字节转成十进制是负数
乱码的原因:
1.读取数据时未读完整个汉字
2.编码和解码时的方式不统一
不要用字节流读取文本文件
字节流读取中文会乱码,但是为什么拷贝不会?
java中编/解吗的方法 getBytes() 编码方式 无参是默认编码方式,带参是指定的方式编码
字符流:字节流+字符集
IO流体系
字节流:InputStream OutputStream
字符流:Reader Writer
read() 无参方法:
底层也是字节流,默认也是一个字节一个字节的读取,如果遇到中文,就会一次读取多个
读取之后方法的底层还会进行解码并转成十进制
最终把这个十进制作为返回值,十进制就表示在字符集上的数字
FileReader:操作本地文件的字符输入流 writer同理
BuffereReader:操作缓冲区的字符输入流 writer同理
LineNumberReader:带有行号的字符输入流 writer同理
read()有参方法:
读取数据,解码,强转;
空参的read + 强制类型转换
参数为char类型的,
默认关闭续写
FileWriter(File file) 创建字符输出流关联本地文件
FileWriter(String pathname) 创建字符输出流关联本地文件
显式开启续写
FileWriter(File file , boolean append) 穿件字符输出流关联本地文件 , 续写
FileWriter(String pathname , boolean append)
write方法可以写出字符,字符串,字符数组
如果write方法的参数是整数,但实际上写到本地文件中的是整数在字符集上对应的字符
字符流底层 字节流没有缓冲区
会在内存中创建一个缓冲区,大小为8192个字节的数组,首先判断缓冲区内是否有数据可以被读取,会先将读取到的数据放置在缓冲区中,每次读取数据都是从缓冲区读取数据,减少每次都从内存中读取的数据
FileReader
创建字符输入流对象:1.关联文件,并创建缓冲区 读取数据 1.判断缓冲区中是否有数据可以被读取, 2.缓冲区没有数据,就从文件中获取数据,装到缓冲区内,每次尽可能装满缓冲区,如果文件中也没有数据,并返回-1
如果缓冲区有数据,空参read方法,一次读取一个字节,遇到中文就读多个字节,把字节解码并转成十进制返回,有参的read方法,把读取自己,解码,强转三步合并了,强转之后的字符放到数组中
read方法会自动保证中文的完整性
FileWriter写文件会首先清空文件
FileWriter:字符流先把数据写入到内存中的缓冲区内,当缓冲区被存满了之后,则将数据自动保存到内存中,或者自己手动flush()。
写方法需要显式调用flush()才可以将数据真正写入到内存中去,如果不显式调用flush方法,就一定要关流,以保证数据真正写入到内存中去,
字节流可以拷贝任意类型的文件
字符流只能拷贝纯文本文件
拷贝文件夹:
^异或运算
两边相同为false 两边不同为true
如果是数字,则会转换为二进制,然后进行同位比较,0为false , 1 为true
那么经过运算后,得到的二进制数字再转换为十进制,随后输出结果
如果一个数字,^同一个数字两次,得到的还是结果本身
IO流体系
字节流 InputStream,OutputStream
字符流 Reader,Writer
以程序为参照物,分为输入和输出
Buffered(缓冲区,缓冲流,可以提高效率,但是字符的基本类型中已经有了缓冲区)
缓冲流,转换流,序列化流,打印流,压缩流,Commons-io
字节缓冲输入/出流,底层自带了长度为8192的缓冲区提高性能,
read(bytes) 表示把读取到的数据放到bytes数组内,并返回一个整数类型的len,表示本次读取到了多少个字节,
字节缓冲流提高效率的原理
read和write方法不再是从内存中进行读取数据,而是直接在内存中的缓冲区中去读取数据随后将数据写入到输出流的缓冲区内,然后将缓冲区内的数据刷新至目的地,真正提升效率的时间在硬盘之间读写的时间,正常的数据流,都是从硬盘中读取一个数据 然后写一次数据到硬盘中,使用了缓冲流之后,尽可能的减少和硬盘交互的时间,而是尽可能和内存交互。
如果之定义了一个len,那么len即充当交互数据的介质,也充当最后返回读取数据的长度返回值,如果定义了一个数组之后,那么数组将作为交互数据的介质,而len只负责接收此次传输数据的长度即可。
int len;用于接收和传输数据,最后将会给len赋一个此次共读取到多少个数据的int类型的值,
字节缓冲流:底层缓冲去的大小是8k
字符缓冲流:底层的缓冲区是16k
底层自带了长度为8192的缓冲区提高性能:
readLine() 读取一行数据,如果没有数据可以读,就返回null,此时返回的null不是字符串类型的,而是null;遇到回车换行,读取结束,但是不会把回车换行读取到内存中去,如果直接输出,则会没有换行
newLine() 跨平台换行,方法的底层会先判断是那个操作系统,同时对应执行换行操作,newLine是BufferedWriter独有的方法
续写参数需要写在newFilewriter方法的参数内
输出流在关联文件的时候会把文件清空,所以在创建对象的时候,尽可能在那个地方使用,就在那个地方创建
转换流,是字符流和字节流之间的桥梁
InoutStreamReader/OutputStreamWriter
读取数据首先要有一个数据源,将数据读取到内存中去,当创建了一个转换流对象的时候,实际上需要包装一层字节输入流,在包装之后,字节流就变为字符流对象,拥有字符流的特性,读取数据不会乱码,可以根据字符集一次读取多个字节,
输出流是将字符流转换为字节流,
作用:1.指定字符集读写 2.字节流想要使用字符流中的方法
FileReader/FileWriter 可以直接读取和写入的读取规则,以那种形式
序列化流属于字节流的一种//对象操作输出流//把基本流包装成高级流
前提要先让需要写出的对象实现Serializable
一旦实现了这个接口,表明当前这个类可以被序列化
可以将java中的对象写到本地文件中
ObjectInputStream// 反序列化流 readObject
此时read方法不用再循环读取,而是调用了方法之后,直接使用Object对象来接收即可,也可以强转成自己需要的类型
如果某个对象的属性值,不想序列化到本地文件
transient表示被修饰的变量不参加序列化过程
ObjectOutputStream// 序列化流 writeObject
解压缩流/压缩流->zip后缀
压缩包里面的每个文件都是属于ZipEntry对象(文件夹和文件都是)
解压就是把每个ZipEntry对象按照层级拷贝到本地另一个文件夹中
解压缩:读取压缩包中的文件,读,属于输入流,
压缩流:将文件中的数据写到压缩包中:属于输出流
压缩流:将每个文件写入到压缩包内
Commons-io:提高IO效率
StringUtils字符串工具类
NumberUtil数字工具类
ArrayUtils数组工具类
RandomUtils随机数工具类
DateUtils日期工具类
StopWatch秒表工具类
ClassUtils反射工具类
SystemUtils系统工具类
MapUtils集合工具类
Beanutils bean工具类
IO io工具类
使用步骤:
1.在项目中创建一个文件夹:lib
2.将jar包复制粘贴到lib文件夹
3.Add as Library
4.在类中导包使用
FileUtils
copyFile(src, dest) 复制文件
copyDirectory(src, dest) 复制文件夹 // 将目标文件拷贝到目的地文件夹路径下
copyDirectoryToDirectory(src , dest) 复制文件夹
deleteDirectory(dir) 删除文件夹
cleanDirectory(dir) 清空文件夹
readFileToString(file , encoding) 读取文件中的数据变成字符串
write(file,data,encoding) 写出数据
IOUtils
copy(InputStream input ,OutputStream output) 复制文件
copyLarge(Reader input ,Writer output)复制大文件
readLines(Reader input) 读取数据
write(String data , output) 写出数据
Hutool工具包
DateUtil 日期时间工具类
TimeInterval 计时器工具类
StrUtil 字符串工具类
HexUtil 16进制工具类
HashUtil hash算法类
ObjectUtil 对象工具类
ReflectUtil 反射工具类
TypeUtil 泛型类型工具类
PageUtil 分页工具类
NumberUtil 数字工具类
IO工具类