工作总结
工作内容
本周工作内容主要是1.根据角色权限进行数据脱敏(后续会出一篇根据注解形式进行数据脱敏的判断)2.对接客户二维码接口。本周来回顾总结一下Java的IO流。
技术探索
1.浅谈Java IO流
1.1“流”的概念与作用
流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。(通俗来说:数据传输是需要通道的,而IO流就是数据传输的通道。IO流可以形象的比喻为运送货物的传输带。)
IO流的分类
- 根据操作数据类型的不同可以区分为:字符流与字节流
- 根据流向的不同可以区分为:输入流与输出流(根据程序为中心,可以将程序读取的数据称之为输入流,程序输出的数据称之为输出流)
IO流结构图
1.2 字节流与字符流
字符流的由来: 因为数据编码的不同,而有了对字符进行高效操作的流对象。本质其实就是基于字节流读取时,去查了指定的码表。
1.2.1字符流与字节流的区分
- 读写单位不同:字节流以字节8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。
- 处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。
- 读写量不同:字节流:一次读入或读出是8位二进制,字符流:一次读入或读出是16位二进制。(字节是占1个Byte,即8位;而字符是占2个Byte,即16位。而且,需要注意的是,java的字节是有符号类型,而字符是无符号类型!)
(总结:设备上的所有文件都是以二进制的形式存储的,计算机中的最后数据单位就是字节,所有文件最终都是以一个8位的数据单员进行体现,所以字节流可以处理设备上所有的数据。只有操作纯文本数据的时候需要优先考虑字符流,其他都使用字节流)
1.3 输入流与输出流
输入流只能进行读操作,输出流只能进行写操作,程序中需要根据待传输数据的不同特性而使用不同的流。(输入流:InputStream/Reader 文件到程序输出流:OutputStream/Writer从程序到文件)
输入流
- InputStream 是所有的输入字节流的父类,它是一个抽象类。
- ByteArrayInputStream、StringBufferInputStream、FileInputStream 是三种基本的介质流,它们分别从Byte 数组、StringBuffer、和本地文件中读取数据。
- PipedInputStream 是从与其它线程共用的管道中读取数据,与Piped 相关的知识后续单独介绍。
- ObjectInputStream 和所有FilterInputStream 的子类都是装饰流(装饰器模式的主角)。
输出流
- OutputStream 是所有的输出字节流的父类,它是一个抽象类。
- ByteArrayOutputStream、FileOutputStream 是两种基本的介质流,它们分别向Byte 数组、和本地文件中写入数据。
- PipedOutputStream 是向与其它线程共用的管道中写入数据。
- ObjectOutputStream 和所有FilterOutputStream 的子类都是装饰流。
BufferedInputStream与BufferedOutputStream
BufferedInputStream和BufferedOutputStream这两个类分别是FilterInputStream和FilterOutputStream的子类,作为装饰器子类,使用它们可以防止每次读取/发送数据时进行实际的写操作,代表着使用缓冲区。
为什么需要缓冲区:不带缓冲的操作,每读一个字节就要写入一个字节,由于涉及磁盘的IO操作相比内存的操作要慢很多,所以不带缓冲的流效率很低。带缓冲的流,可以一次读很多字节,但不向磁盘中写入,只是先放到内存里。等凑够了缓冲区大小的时候一次性写入磁盘,这种方式可以减少磁盘操作次数,提高效率。
- BufferedInputStream 是缓冲输入流。它继承于FilterInputStream。
- BufferedInputStream 的作用是为另一个输入流添加一些功能,例如,提供“缓冲功能”以及支持mark()标记和reset()重置方法。
- BufferedInputStream 本质上是通过一个内部缓冲区数组实现的。例如,在新建某输入流对应的BufferedInputStream后,当我们通过read()读取输入流的数据时,BufferedInputStream会将该输入流的数据分批的填入到缓冲区中。每当缓冲区中的数据被读完之后,输入流会再次填充数据缓冲区;如此反复,直到我们读完输入流数据位置。
InputStreamReader与OutputStreamWriter
InputStreamReader: 是字符流Reader的子类,是字节流通向字符流的桥梁。你可以在构造器重指定编码的方式,如果不指定的话将采用底层操作系统的默认编码方式,例如 GBK 等。要启用从字节到字符的有效转换,可以提前从底层流读取更多的字节,使其超过满足当前读取操作所需的字节。一次只读一个字符。
OutputStreamWriter: 是字符流Writer的子类,是字符流通向字节流的桥梁。每次调用 write()方法都会导致在给定字符(或字符集)上调用编码转换器。在写入底层输出流之前,得到的这些字节将在缓冲区中累积。一次只写一个字符。
1.4 代码校验
1.4.1FileInputStream类
代码
public static void readFile(String filePath) {
FileInputStream fis=null;
try{
//根据文件地址实例化一个文件输入流的对象
fis=new FileInputStream(filePath);
//返回字节可以被读取的字节量
int size = fis.available();
byte[] btyes = new byte[size];
//读取数据到数组中
fis.read(btyes);
String s = new String(btyes);
System.out.println(s);
}catch (FileNotFoundException e){
e.printStackTrace();
}catch (IOException e){
e.printStackTrace();
} finally{
if (fis!=null){
try {
fis.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
}
结果:
1.4.2FileOutputStream类
public static void writeFile(String filePath){
FileOutputStream fos=null;
try{
fos=new FileOutputStream(filePath);
String s="新增数据123456789";
byte[] bytes = s.getBytes();
fos.write(bytes);
}catch (FileNotFoundException e){
e.printStackTrace();
}catch (IOException e){
e.printStackTrace();
}finally {
if (fos!=null){
try {
fos.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
}
结果:
代码(通过 FileInputStream、FileOutputStream实现文件复制以及迁移)
public static void copyFile(String filePath,String newFilePath) {
FileInputStream fis=null;
FileOutputStream fos=null;
try{
//根据文件地址实例化一个文件输入流的对象
fis=new FileInputStream(filePath);
//返回字节可以被读取的字节量
int size = fis.available();
byte[] btyes = new byte[size];
//读取数据到数组中
fis.read(btyes);
fos = new FileOutputStream(newFilePath);
fos.write(btyes);
}catch (FileNotFoundException e){
e.printStackTrace();
}catch (IOException e){
e.printStackTrace();
} finally{
if (fis!=null){
try {
fis.close();
}catch (IOException e){
e.printStackTrace();
}
}
if (fos!=null){
try {
fos.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
}
1.4.3BufferedInputStream与BufferedOutputStream类
public static void copyFile(String filePath,String newFilePath){
InputStream is=null;
OutputStream os=null;
BufferedInputStream bis=null;
BufferedOutputStream bos=null;
try{
is=new FileInputStream(filePath);
bis=new BufferedInputStream(is);
os = new FileOutputStream(newFilePath);
bos=new BufferedOutputStream(os);
byte[] bytes = new byte[1024];
int length=0;
while ((length=bis.read(bytes))!=-1){
bos.write(bytes,0,length);
}
//缓冲区内容写入文件
bos.flush();
}catch (Exception e){
e.printStackTrace();
}
if (bos!=null){
try{
bos.close();
}catch (IOException e){
e.printStackTrace();
}
}
if (bis!=null){
try{
bis.close();
}catch (IOException e){
e.printStackTrace();
}
}
if (is!=null){
try{
is.close();
}catch (IOException e){
e.printStackTrace();
}
}
if (os!=null){
try{
os.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
1.4.4InputStreamReader与OutputStreamWriter类
private static void copyFile(String filePath,String newFilePath){
InputStream inputStream = null ;
InputStreamReader inputStreamReader = null ;
OutputStream outputStream = null ;
OutputStreamWriter outputStreamWriter = null ;
try {
inputStream = new FileInputStream( filePath ) ; //创建输入流
inputStreamReader = new InputStreamReader( inputStream ) ; //创建转换输入流
outputStream = new FileOutputStream( newFilePath ) ; //创建输出流
outputStreamWriter = new OutputStreamWriter( outputStream ) ; //创建转换输出流
int result = 0 ;
while( (result = inputStreamReader.read()) != -1){ //一次只读一个字符
outputStreamWriter.write( result ); //一次只写一个字符
}
outputStreamWriter.flush(); //强制把缓冲写入文件
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}finally{
if ( outputStreamWriter != null) {
try {
outputStreamWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if ( inputStreamReader != null ) {
try {
inputStreamReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
以上有关异常的内容是阅读了,该文章的学习总结。
总结
1、本周对Java得IO流进行了回顾在平时使用工具类比较多,所有有所忽略IO流的实现过程
relax--zwx