JavaIO流

IO流

和IO流相关的类都在 java.io 包中
IO流主要可以实现对文件的读和写操作
IO 中的 I 是 in(输入) ,O 是 out(输出)

文件File的操作

File 类 可以表示 文件 ,也可以表示 文件夹(目录)
URL: 统一资源定位系统 , 通俗的讲 就是 指的 网址
URI: 统一资源标识符
URI 包含 URL

File 的常见构造方法

 // 创建一个 目录 对象, 指向磁盘中的 某个文件夹
File file = new File("E:/EV");

// 创建一个 文件对象, 指向 磁盘中的某一个 文件
File file2 = new File("E:/EV", "19.集合框架-Set特点及基本用法.mp4");

// 此处的 file 只能表示 目录 ,不能是文件
File file3 = new File(file, "19.集合框架-Set特点及基本用法.mp4");

// URI :
File file4 = new File("file:///C:/Users/Administrator/Desktop/%E7%AC%AC%E4%B8%80%E9%98%B6%E6%AE%B5-%E6%A0%B8%E5%BF%83%E7%B1%BB%E8%80%83%E8%AF%95%E9%A2%98.docx");

File 类中的常见方法

  • exists() : 判断 file 对象是否在磁盘中存在

  • isFile() : 判断 file 对象是不是 文件

  • isDirectory() : 判断 file 对象是不是 目录

  • isHidden() : 判断 file 是不是 隐藏的

  • length() : 主要应用于 文件、获取 文件的大小、单位字节

  • canWrite() : 判断文件是否能被写入

  • canRead() : 判断文件是否能读

  • canExecute() : 判断文件是否可执行

  • getName() : 获取文件(夹)的名字

  • getAbsolutePath() : 获取 文件(夹)的绝对路径(从盘符开始)

  • getCanonicalFile() : 获取 文件(夹)的绝对路径标识的File对象

  • file.getPath(): 获取文件(夹)的路径

  • getParent() : 获取文件(夹)的上一级路径

  • getParentFile() : 获取文件(夹)的上一级路径所对应的 file 对象

  • listFiles(): 获取某个文件夹 下所有的 file(文件和文件夹)

  • listFiles(FileFilter) : 可以根据文件对象 进行过滤

  • listFiles(FilenameFilter) : 根据文件名 进行过滤

  • mkdir() : 当目录不存在的时候,创建一个目录,只能创建最后的一层目录

  • mkdirs() : 递归的创建目录

  • createNewFile() : 创建一个文件

  • delete() : 删除一个空的目录 或者 文件

获取某个目录下的所有文件
删除某一个目录

编写一个工具类ClassUtils,负责加载项目下的所有类

List<Class<?>> scanClasses(String package) ;

文件IO流

对文件进行读和写操作
输入流: 将文件的内容 读取到 Java内存中
输出流: 将 Java内存中的数据 写入到 文件

流的分类

按照流的方向: 输入流 InputStream , Reader 和 输出流 OutputStream , Writer

按照流的类型: 字符流 Reader , Writer 和 字节流 InputStream , OutputStream

按照流的功能: 节点流 和 过滤流

字符流主要读取由字符串构成的文件、例如 txt文本文件、java源代码、(能用记事本打开的文件都是字符文件)
字符文件应该由字符流(Reader、Writer)进行读取、其他文件由字节流(InputStream, OutputStream)读取
字节流原则上可以读取所有类型的文件
可以直接操作文件的流在功能上被称为节点流、过滤流不能直接操作文件,而是在节点流的基础上增强了流的增强

FileInputStream 流

输入流、字节流、节点流

常见的构造方法
  • new FileInputStream(String path) : 根据文件的路径构建一个文件输入流
  • new FileInputStream(File file): 根据文件构建一个文件输入流

实现文件的复制、粘贴

常见的方法
  • read() : 一次读取一个字节、返回读取到 Unicode编码值, 如果返回 -1, 则代表文件读取完成
  • read(byte[] bytes) : 一次读取指定长度的字节数, 返回值 代表读取的长度,读取的内容直接放到了byte[]中,如果返回 -1, 代表文件读取完成
  • readAllBytes() : 更适合于小文件的一次性读取,如果是大文件,不推荐使用,因为太占用内存了,大文件推荐使用 边读编写
FileOutputStream 流

输出流、字节流、节点流

常见的构造方法
  • new FileOutputStream(String path) : 根据文件的路径构建一个文件输出流

  • new FileOutputStream(File file) : 根据文件构建一个文件输出流

  • new FileOutputStream(file, boolean append) : 构建一个输出流、是否向里面追加内容

常见的方法
  • write(int a) : 一次写入一个字节、 a 代表 Unicode编码值,写入到文件中,会转成字符

  • write(byte[]) : 将一个byte数组中存储的内容直接写入到文件中

  • write(byte[], offset, len) : 将一个 byte[] 中 从 offset位置开始 写入 len 长度

try-with-resource 释放资源

try-with-resource : 可以处理异常、相当于 try-catch-finally , 也可以自动释放资源, 如果不处理异常、相当于 try-finally
如果没有需要释放的资源,则不能使用 try-with
如果一个对象 实现了 Closeable 接口, 那么就可以使用 try-with 自动释放该资源

字符流 Reader , Writer

擅长读取字符文件(可以用记事本打开的文档)

FileReader 类 常用的构造方法

  • new FileReader(String path) : 根据文件路径构建一个字符输入流
  • new FileReader(File file) : 根据文件构建一个字符输入流
  • new FileReader(file, Charset) : 创建一个字符输入流、并设置读取数据的编码方式
StandardCharsets.UTF_8 
Charset.forName("GBK")

常见的方法

  • read() : 一次读取一个字符、当返回 -1 的时候,代表读取完成
  • read(char[]) : 一次读取指定个数的字符、返回读取的长度、当返回 -1 的时候,代表已经读取完成

FileWriter 类

构造方法支持 路径、文件、追加、编码

常见的方法
  • write(int n) : 将 n(码点) 对应的字符写入到文件中
  • write(char[], offset, len) : 将一个 char[] 写入到文件中
  • write(str) : 将一个字符串直接写到文件中

字符流 默认调用 write 无法直接将数据写入到文件中,只有当调用了 close() 或者 flush() 才能将数据写入文件

桥接流

将 字节流 转换成 字符流

  • InputStreamReader : 将 字节输入流 转成 字符输入流
  • OutputStreamWriter: 将 字节输出流 转成 字符输出流
和 byte[] 相关的流
  • ByteArrayInputStream : 可以将一个 byte[] 转成 流
  • ByteArrayOutputStream : 可以返回一个 byte[] 数组
    • toByteArray: 负责返回byte[]

其他用法参考FileInputStream和FileOutputStream

过滤流

在节点流的基础上进行了装饰、比节点流功能上更加强大
不能直接操作文件 ,只能操作 节点流

常见的过滤流
  • BufferedInputStream
  • BufferedOutputStream
  • BufferedReader
  • BufferedWriter
BufferedReader
  • readLine() : 一次读取一行数据,返回读取到的一行字符串,如果返回 null, 说明文件读取完成
BufferedWriter
  • newLine() : 写入一个换行字符、实现内容的换行

PrintWriter

是一个字符输出流、内置了大量的print方法,主要操作字符串
既可以直接操作文件、也可以操作流。 所以从功能来看 既是节点流又是过滤流
可以将一个字节流转成 PrintWriter

PrintStream

是一个字节输出流、内置了大量的print方法、可以操作任意类型
既是节点流又是过滤流

System.out返回的就是一个PrintStream, 默认向控制台输出内容,如果需要向文件中输出内容,可以通过System.setOut(out)修改输出源

ObjectInputStream 和 ObjectOutputStream

专门用来将 对象 进行 读操作 和 写操作
是过滤流,不能直接操作文件

ObjectOutputStream

对象的序列化操作: 将一个对象写入到磁盘的过程
通过 writeObject方法,将一个对象进行序列化操作
被序列化的对象必须实现 Serializable 接口

ObjectInputStream

对象的反序列化操作: 将磁盘中存储的被序列化的对象 读取到内存中
反序列操作在 构建对象的时候,不会调用构造方法
反序列化操作的JDK版本必须和 序列化的JDK版本保持一致
为了保证序列化操作和反序列操作的一致性、通常会在序列化的类上添加一个 序列化版本号

Idea配置 Serializable 序列化版本号
File -> Settings -> Editor -> Inspections 
右侧搜索框内搜索 serial ... 关键字,找到 Serializable class without serialVersionUID 勾上,并保存
在 类上,通过 ALT + 回车 即可 自动添加 序列化版本号 
深拷贝技术

通过程序拷贝一个对象、拷贝出来的东西和原东西在内容在表现一摸一样,但却是2个独立的完全不相干的对象

浅拷贝技术

拷贝一个对象、将对象中的 基本类型、包装类型、字符串类型等 进行深拷贝、其他类型只拷贝对应的地址

如果一个对象,要实现浅拷贝技术,只需要让这个对象的类实现 Cloneable 接口
Cloneable 没有任何方法,但如果想要实现克隆,那么必须重写 Object类中 clone方法

深拷贝实现的方式
  1. 递归的使用浅拷贝、每一层都进行浅拷贝 (代码编写比较复杂)
  2. 对象序列化 (对象序列化是Java语言特有的、不能跨语言、性能比较差)
  3. JSON序列化 (重点要求掌握的)
JSON 是什么???

是一种轻量级的数据格式、简洁、清晰、非常方便在互联网中进行数据传输。
[ … ]格式 : 在java语言中,可以用 数组 或者 Collection集合 表示
{ … }格式: 在java语言中,可以用 对象 或者 Map集合表示

{
  "name": "张三", 
  "sex" : "男" ,
  "age": 18, 
  "teacher": {
      "name": "李四" ,
      "age": 30
  }, 
  "hobby": [
    "游泳", 
    "爬山"
  ]
}

Map<String, Object>

[
  {
  "name": "张三",
  "sex" : "男" ,
  "age": 18
  },
  {
  "name": "张三",
  "sex" : "男" ,
  "age": 18
  }
] 

List<Map<String,Object>>

JSON 序列化的库
  • FastJson (阿里巴巴提供的处理JSON的库)
  • Gson (谷歌)
  • Jackson
Fastjson 序列化
  • JSON序列化操作 : 将一个 JSON格式的对象(Map, 实体类、List)转成JSON格式的字符串
JSONArray.toJsonString(obj,  SerializerFeature...)

配置 SerializerFeature
  • SerializerFeature.WriteMapNullValue : 如果序列化的对象的值是空,默认不显示属性/键, 可以通过设置该属性,让 null对应的 属性/键 显示

  • SerializerFeature.PrettyFormat : 美化序列化后的结果

  • SerializerFeature.WriteDateUseDateFormat : 使用日期格式化

定制 SerializerConfig
SerializeConfig config = SerializeConfig.getGlobalInstance();

// 将处理日期的类型单独进行配置
config.put(LocalDate.class, (JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int var5)-> {

    DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");

    String format = dateTimeFormatter.format((LocalDate) object);

    SerializeWriter out = serializer.out;
    out.writeString(format);
}) ;

config.put(LocalDateTime.class, (JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int var5)-> {

    DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");

    String format = dateTimeFormatter.format((LocalDateTime) object);

    SerializeWriter out = serializer.out;
    out.writeString(format);
}) ;

JSON 反序列化

将一个 JSON格式的字符串 转成 Java中的对象

// 返回一个 T类型的对象 
JSONArray.parseObject(String json , Class<T> clz) 

// 返回一个 List<T> 类型的对象
JSONArray.parseArray(String json , Class<T> clz) 

// 返回一个 List<Map<String,Object>> 
JSONArray.parseObject(json, new TypeReference<List<Map<String,Object>>>(){}.getType());

GSON 序列化与反序列化

// 创建一个 gson对象
Gson gson = new GsonBuilder().create() ; 

gson.toJson(obj) : 将一个对象转成 字符串 

gson.fromJson(json, Class<T>) : 将json格式的字符串转成 T 类型,适用于单条记录 

gson.fromJson(json, new TypeToken<List<T>(){}.getType) : 将 json格式的字符串转成List<T> 类型,适合多条记录


GSON 处理新LocalDate 新日期API
 // 创建一个 gson对象, 支持新版日期api
Gson gson = new GsonBuilder()
        .registerTypeAdapter(LocalDate.class,
                (JsonSerializer<LocalDate>) (localDate, type, jsonSerializationContext) ->
                        jsonSerializationContext.serialize(DateTimeFormatter.ofPattern("yyyy/MM/dd")
                                .format(localDate), String.class))

        .registerTypeAdapter(LocalDate.class,
                (JsonDeserializer<LocalDate>) (jsonElement, type, jsonDeSerializationContext) -> {
                    String deserialize = jsonDeSerializationContext.deserialize(jsonElement, String.class);
                    return LocalDate.parse(deserialize, DateTimeFormatter.ofPattern("yyyy/MM/dd"));
                })
        .registerTypeAdapter(LocalDateTime.class,
                (JsonSerializer<LocalDateTime>) (localDate, type, jsonSerializationContext) ->
                        jsonSerializationContext.serialize(DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss")
                                .format(localDate), String.class))
        .registerTypeAdapter(LocalDateTime.class,
                (JsonDeserializer<LocalDateTime>) (jsonElement, type, jsonDeSerializationContext) -> {
                    String deserialize = jsonDeSerializationContext.deserialize(jsonElement, String.class);
                    return LocalDateTime.parse(deserialize, DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"));
                })
        .serializeNulls()
        .setPrettyPrinting()
        .create();

IO流工具包

  • commons-io 第三方依赖库封装了和 IO相关的工具类
常用的工具类
  • FileUtils : 和文件相关操作的工具类

  • IOUtils :和文件没有直接关系的操作工具类

具体方法自己完成测试即可

Zip压缩与解压缩

  • ZipOutputStream (压缩文件)

  • ZipInputStream (解压缩文件)

装饰模式

是Java类进行扩展的一种非常有效的方式
装饰类 和 目标类 必须拥有相同的父类(推荐使用接口)
在装饰类中 维护一个 目标类的 属性、并提供有参构造
在装饰类中 提供自己的方法,让自己比目标类更加强大

import java.util.regex.Pattern;

public class TMString implements CharSequence {

  private CharSequence target;

  public TMString(CharSequence target) {
    this.target = target;
  }


  public int length() {
    return this.target.length();
  }
  // 其他重写方法忽略...

  // 装饰类扩展的方法
  public boolean isTel() {
    return Pattern.matches("1[3-9]\\d{9}", this.target);
  }

}

调用代码片段

// 使用代码片段
String  s = "13312345678" ;

TMString str = new TMString(s) ;

str.isTel(); // true

ing implements CharSequence {

private CharSequence target;

public TMString(CharSequence target) {
this.target = target;
}

public int length() {
return this.target.length();
}
// 其他重写方法忽略…

// 装饰类扩展的方法
public boolean isTel() {
return Pattern.matches(“1[3-9]\d{9}”, this.target);
}

}

调用代码片段

// 使用代码片段

String  s = "13312345678" ;

TMString str = new TMString(s) ;

str.isTel(); // true
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值