JAVA 字符流&&Properties集合
字符流 【重点】
字节流的体系结构
字符输入流
Reader
|-InputStreamReader 转换流
|-FileReader 基本流
|-BufferedReader 缓冲流
字符输出流
Writer
|-OutputStreamWriter 转换流
|-FileWriter 基本流
|-BufferedWriter 缓冲流
编码表
什么是编码表
是一张现实中的文字符号等(字符)与计算机能识别的二进制(字节)之间对应表
现实中的 计算机能识别的
a 01100001
我 11100001 10001010
! 01001000
什么编解码
编码:字符转换为字节 a->01100001
解码:字节转换为字符 01100001->a
编解码操作一定要查询编码表
编解码操作使用的编码表必须是同一张,否则会出现乱码问题
常见的编码表
ASCII:最早的编码表,美国人和英国人的文字符号等的对应关系,不包含中文
GBK:中文码表,一个中文占2个字节,英文、数字和符号占1个字节
UTF-8:包含中文,一个中文占3个字节,英文、数字和符号占1个字节
ISO-8859-1:西欧/拉丁编码,不包含中文
"我爱java"(字符串) ->'我','爱','j','a','v','a'(字符)
'我'(1个字符) -> {-19, -29, -89}(3个字节)
字符是由字节组成的,有些是一个字节组成,有些是多个字节组成
基本流
FileReader
构造方法
FileReader(String name)
FileReader(File file)
成员方法
int read():一次读取一个字符,并返回读取到的字符,如果读取到了文件末尾,返回-1
int read(char[] chs):一次读取多个字符,并返回读取到数组中的有效字符个数,如果读取到了文件末尾,返回-1
void close()
//如果文件存在,那么就不会报错.
//如果文件不存在,那么就直接报错.
FileReader fr = new FileReader("bytestream\\a.txt");
int read = fr.read();
//一次读取一个字符,返回值就是本次读到的那个字符数据.
//也就是字符在码表中对应的那个数字.
//如果我们想要看到的是字符数据,那么一定要强转成char
System.out.println((char)read);
//释放资源
fr.close();
FileWriter
构造方法
FileWriter(String name)
FileWriter(String name, boolean append)
FileWriter(File file)
FileWriter(File file, boolean append)
成员方法
void write(int b):写出字符数据 int->char
void write(char[] b)
void write(char[] b, int off, int len)
void write(String s)
* write("\r\n") 换行
void write(String s, int off, int len)
void close()
//1.创建字符输出流的对象
//注意点:1、如果文件不存在,会帮我们自动创建出来,但是要求文件路径要存在
// 2、如果文件存在,会把文件清空,再写出到文件
3、可以写相对路径,也可以写绝对路径
4、关联的路径永远只能是文件路径,不能是文件夹路径
FileWriter fw = new FileWriter("C:\\itheima\\a.txt");
//2,写数据
// 传递一个整数时,那么实际上写到文件中的,是这个整数在码表中对应的那个字符.
fw.write(98);// 98(十进制)->00000000 00000000 00000000 01100010(int、二进制)
// -> 00000000 01100010(char、二进制) ->写入到文件中,但是文本编辑器是一个编解码
//3,释放资源
fw.close(); //告诉操作系统,我现在已经不要再用这个文件了
flush和close方法的区别
close方法
1、是先刷新,在关闭流
2、close关闭流转换就不能继续使用流
flush方法
1、只有刷新功能
2、可以多次调用,可以继续使用流
缓冲流
底层提供了缓冲区(数组),提高读写的效率
BufferedWriter
构造方法:不能直接关联写出的文件
BufferedWriter(Writer out)
写和释放资源的操作与字符基本流一模一样
BufferedReader
构造方法:不能直接关联读取的文件
BufferedReader(Reader in)
读和释放资源的操作与字符基本流一模一样
特有功能
BufferedWriter类
* void newLine():一个跨平台的换行
BufferedReader类
* String readLine():一次读取一行数据(不包含回车换行符),并返回,如果读取到文件末尾,返回null
字符缓冲流的好处:
1、提高读写的效率
2、提供了特有功能方便操作
转换流
InputStreamReader
字符流 = 字节流 + 编码表
FileReader = FileInputStream + 默认编码(UTF-8)
InputStreamReader = FileInputStream + 指定编码表
OutputStreamWriter
FileWriter = FileOutputStream + 默认编码(UTF-8)
OutputStreamWriter = FileOutputStream + 指定编码表
作用:
1、读写的过程中进行编码转换
2、将字节流转换为字符流
Properties集合 【重点】
什么是Properties?
是一个双列集合,间接实现了Map接口。
没有泛型,存储的键和值都是字符串类型
它提供和IO流相结合的方法
Properties
共性功能 【了解】
特有功能 【重点】
Object setProperty(String key, String value) 相当于put方法
String getProperty(String key) 相当于get方法 【重点】
Set<String> stringPropertyNames() 相当于keySet方法
void load(字节/字符输入流 inStream) 读取 【重点】
void store(字节/字符输出流, String comments) 写出
java中的配置方式
1、配置文件方式
.properties文件方式
.xml文件方式
2、注解配置方式
Properties的使用步骤:
1、创建Properties集合对象
2、通过load方法读取.properties文件中的配置信息(格式:键=值)
3、通过getProperty方法根据键获取我们需要的值。
// 1、创建Properties集合对象
Properties prop = new Properties();
// 2、通过load方法读取.properties文件中的配置信息(格式:键=值)
InputStream in = PropertiesDemo3.class.getClassLoader().getResourceAsStream("info.properties");
prop.load(in);
// 3、通过getProperty方法根据键获取我们需要的值。
String username = prop.getProperty("username");// zhangsan
String password = prop.getProperty("password");
其他流 - 对象操作流 【了解】
用于操作对象的流,可以将对象直接写出到文件,也可以将文件中的对象读取出来
ObjectOutputStream:对象输出流,将对象直接写出到文件
构造方法
ObjectOutputStream(OutputStream out)
* 构造方法中不能直接关联文件路径,要传递基本流对象,基本流关联文件路径
成员方法
void writeObject(Object obj)
* Object obj要写出的对象
ObjectInputStream:对象输入流,将文件中的对象读取出来
构造方法
ObjectInputStream(InputStream in)
* 构造方法中不能直接关联文件路径,要传递基本流对象,基本流关联文件路径
成员方法
Object readObject()
* 返回的是读取到的对象
序列化和反序列化的概念
序列化:将对象直接写出到文件
反序列化:将文件中的对象读取出来
Serializable:标识/标记型接口
用对象序列化流序列化了一个对象后,假如我们修改了对象所属的类文件,读取数据会不会出问题呢?
会出现问题,InvalidClassException无效的类异常
该类的序列版本号与从流中读取的类描述符的版本号不匹配(写的时候的类与读取到时候看到的类不同了)
如果出问题了,如何解决呢?
在类中定义一个serialVersionUID常量
ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;
serialVersionUID常量:序列化版本号,你可以认为这是类的版本号,读和写的时候看类是否是相同的,
就是根据serialVersionUID常量的值来判断的
如果不显式定义serialVersionUID常量,那么系统会根据类的内容去生成一个默认的serialVersionUID
如果一个对象中的某个成员变量的值不想被序列化,又该如何实现呢?
transient:瞬态关键字
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Ahir's Blog!
评论
GitalkDisqusjs