Java-IO

20 篇文章 1 订阅

一、src

  1. 抽象实际上不是抽象的物体,而是抽象的物体以及这个物体的行为。平时创建1个dog、car的类,直觉上好像抽象的是静态的物体,其实这个类里面是有run、say等方法的。
    流就是典型的抽象,它封装的是数据源 + 输入行为目的地 + 输出行为

  2. 流的作用就是把数据源的数据复制到另一个地方。此时会有如下的痛点:

    1. 数据源和目的地有多种不同的类型
    2. 虽然底层都是字节,但在文本场景下,有时为了方便和效率,需要提供字符传输的接口,而这必然会有编码问题
    3. 为了避免频繁读写,就需要设置buffer,就会有buffer大小和flush的问题

    当然,这些问题都已经得到了解决

二、comprehending/process

1. 明确要操作的数据是数据源还是数据目的(也就是要读还是要写)

源:
InputStream Reader
目的:
OutputStream Writer

2. 明确流的来源设备

源设备
硬盘:文件 File开头
内存:数组,字符串
键盘:System.in
网络:Socket
对象:1个保存有序列化java对象的文件。ObjectInputStream
目的设备
硬盘:文件 File开头
内存:数组,字符串
屏幕:System.out
网络:Socket
对象:文件,用来保存java对象

3. 明确要操作的设备上的数据是字节还是文本

是否需要设置转换流,是否设置编码

4. 明确是否需要缓冲增加效率

5. 明确是否需要封装好的功能

比如专注于java基本类型写的DataOutputStream,专注于格式化写的PrintWriter

三、usage

须知:

  1. File对象包括目录和文件
  2. mkdir只能创建一级目录,如果输入的多级目录超过1个不存在,则创建失败。mkdirs可以创建多级目录
  3. Writer.write方法可以自动创建文件,注意是文件,如果上级目录不存在,会报FileNotFoundException: E:\test (拒绝访问。)
  4. createNewFile只会创建文件,而且是空的。不能创建目录,如果输入的多级目录中目录不存在,会报错。
  5. 字节流close时,自动flush,但字符流close时却不会,需要手动flush。???总之,不管字节字符流,别忘了flush

1. 转换流:InputStreamReader

名称分2部分:AB,意思是把A转成B
InputStreamReader。java没有提供ReaderInputStream,但第三方有,比如guava

2. 缓冲流:BufferedReader、BufferedWriter

https://blog.csdn.net/qq_21808961/article/details/81561464

{1} 为了批量读写,br可以直接使用nextLine以行为单位读,bw可以用newline()来插入\n。注意在idea中只输入buffer不会给出提示,要输全。example如下:

String line = ""
while((line = br.readLine()) != null)
int num = 0
while((num = br.nextLine()) != -1)

3. 格式化、便利、打印流:PrintStream|Writer

用来快速方便的进行写操作的类,可以直接传入1个文件,也可以装饰其他字节、字符流。可以简便的获取带缓存、刷新、可指定字符集、自动创建不存在的文件的1个字符输出流对象。但不能设置缓冲区大小,如果想指定,就要传入用缓冲流包装的流对象。

注意:是输出流,输入流没有类似的便利流

BigTrap

不设置autoFlush的情况下,如果最后没有close,最后部分的数据会出现不完整的情况,如果是小数据,会出现结果文件为空的情况。
那是因为PW还没flush程序就结束了。要么设置autoFlush,生成依据写入依据,效率低;要么在最后close。可close是基本规范,所以为了效率和规范,还是不设置autoFlush,在最后close

{1} 创建

  1. 可直接根据File和String创建。也可以设置编码。
  1. args1为true时,执行println、printf、format会自动触发flush(),但这样可能效率低,可以插入一定数量后批量flush。
    在这里插入图片描述

{2} 写

可以直接用println等方法写入到文件中。也可以方便的使用newLine来插入回车\n
在这里插入图片描述

example:hdfs写入时用PW装饰。这样就不需要每个字符串都显式转成字节数组了。
val fs = FileSystem.get(new Configuration())
val outputStream = fs.create(new Path("test"))
//pw 不提供(流,编码)的构造器,只能通过OutputStreamWriter设置
val pw = new PrintWriter(new OutputStreamWriter(outputStream,"UTF-8"))
val line = "xxx"
pw.println(line)

4. 序列化流

src

java对象也是数据,也可以映射到文件,也需要在网络之间传输。这就需要把java的class文件序列化成字节数组,然后像其他数据一样在不同节点间传输。
注意,是对象序列化,不是类,类不需要序列化。直接把类代码发给对方即可。

此时有2个问题:

  1. 如果1个java对象序列化成文件后,这个文件发生了修改,那就意味着数据发生了损坏,显然这是不允许的,所以jdk给需要序列化的类提供了1个版本号,序列化之前将这个版本号写入,返序列化时,如果发现目标节点上,这个类的序列化号和反序列化的对象的序列化号不一致,那就会报InvalidClassException错。
  2. jdk为了安全,默认不允许对象传输,一个对象要想序列化,必须满足两个条件:
    1. 该类必须实现java.io.Serializable 接口,Serializable 是一个标记接口,不实现此接口的类将不会使任何状态序列化或反序列化,会抛出NotSerializableException 。
    2. 该类的所有属性必须是可序列化的。如果有一个属性不需要可序列化的,则该属性必须注明是瞬态的,使用transient 关键字修饰,在scala中加@transient注解。

四、Properties类

1. src

  1. 这个类本身是个map,提供了简便的同java指定格式的properties或xml交互的API。用来操作kv格式的配文。可以简便完成配文《==》java变量 的切换。
  2. Properties文件是java最常用的配文,后缀为.properties,格式是键=值,通过回车分割,用#注释。比如jdbc的配文:
    driver=com.mysql.jdbc.Driver 
    jdbcUrl=jdbc:mysql://localhost:3306/user 
    user=root 
    password=451535 
    

2. usage/api

{1} 加载配文

load(InputStream inStream) 
load(Reader reader) 
loadFromXML(InputStream in) 

{2} 获取和设置属性

Properties pro=new Properties();
//设置
pro.setProperty("driver", "com.mysql.jdbc.Driver");
//获取
pro.getProperty("driver");

{3} 将Properties对象保存为配文,可设置编码

store(OutputStream out, String comments) 
store(Writer writer, String comments) 
storeToXML(OutputStream os, String comment) 
storeToXML(OutputStream os, String comment, String encoding) 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值