目录
Properties
是已经被淘汰的Hashtable<K,V>的子类,但是是唯一和IO相结合的集合
Properties类表示了一个持久的属性集。Properties可以保存在流中或从流中加载。属性列表中每个建及其对应的值都是一个字符串
可以使用Properties集合中的方法store,把集合中的临时数据,持久化写入到硬盘中存储
可以使用load方法把硬盘中保存的文件(键值对),读取到集合中使用
属性列表中每个键及其对应值都是一个字符串
Properties集合是一个双列集合,key和value默认都是字符串
演示及方法:
/*
Properties集合中有一些操作字符串的特有方法
Object setProperty(String key,String value)调用Hashtable的方法put
String getProperty(String key)通过key找value,相当于Map集合中的get(key)方法、
set<String> stringPropertyName()返回此属性列表中的键值,其中该键值及其对应值是字符串,此方法相当于Map集合中的keySet方法
*/
public static void main(String[] args) {
Properties prop=new Properties();
prop.setProperty("1","name1");
prop.setProperty("2","name2");
prop.setProperty("3","name3");
//存储到set集合
Set<String> set = prop.stringPropertyNames();
//遍历
for (String s : set) {
System.out.println(s+"="+prop.getProperty(s));
}
//store方法
/*
void store(OutputStream out,String comments)
void store(Write write,String comments)
参数:
out:字节输出流,不能写中文
write:字符输出流可以写中文
comments:注释,用来说明保存的文件是做什么用的,默认用Unicode编码不能用中文,一般用空字符串
使用步骤:
1、创建Properties对象,添加数据
2、创建字节/字符输出流对象,构造方法中绑定目的文件
3、使用Properties中的store,把集合中的临时数据,写入到硬盘中存储
4、释放资源
*/
try(FileWriter fw=new FileWriter("src\\io\\properties_demo\\test.txt")){
prop.store(fw,"");
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void test1() throws IOException {
//load方法
/*
void load(InputStream inStream)
void load(Reader reader)
参数:
InputStream inStream:字节输入流,不能读取含有中文的键值对
Reader reader:字符输入流,能读取含有中文的键值对
使用步骤:
1、创建Properties集合对象
2、使用Properties集合对象中的方法load读取保存键值对的文件
3、遍历Properties集合
注意:
1、存储键值对的文件中,键与值默认的连接符号可以使用=或空格(其他符号)
2、存储键值对的文件中,可以使用#进行注释,被注释的键值对不会被读取
3、键与值默认都是字符串,不用再加引号
*/
Properties properties=new Properties();
properties.load(new FileReader("D:\\program testing\\javatest\\JavaHHHLevel\\src\\io\\properties_demo\\test.properties"));
Set<String> set = properties.stringPropertyNames();
for (String s : set) {
System.out.println(s+"="+properties.getProperty(s));
}
}
字节缓冲流
![](https://i-blog.csdnimg.cn/blog_migrate/fe9ff0476c49c98a6ddc6a61e2c0d1ff.png)
BufferedOutputStream字节缓冲输出流 extends OutputStream
构造方法:
BufferedOutputStream(OutputStream out)创建一个新的缓冲输出流,以将数据写入指定的底层输出流。
BufferedOutputStream(OutputStream out,int size)创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入底层输出流
参数:
out:字节输出流,可以传入FileOutputStream
size:指定缓冲流内部缓冲区的大小,不指定默认
步骤:
1、创建FileOutputStream对象
2、创建BufferedOutputStream对象,构造方法中传递fos对象
3、使用BufferedOutputStream中的方法write,写入内部缓冲区
4、使用BufferedOutputStream中的方法flush,把内部缓冲区中的数据,刷新到文件中
5、释放资源(会自动调用flush)
*/
public class Demo1 {
@Test
public void test1() throws IOException {
FileOutputStream fos=new FileOutputStream("D:\\program testing\\javatest\\JavaHHHLevel\\src\\io\\bufferede\\test.txt");
BufferedOutputStream bos=new BufferedOutputStream(fos);
bos.write("我将数据写入内部缓冲区中".getBytes());
bos.flush();
bos.close();
}
}
/*
字节缓冲输入流BufferedInputStream extends InputStream
构造方法除了名字是BufferedInputStream,其他跟输出流一样
步骤:
1、创建FileInputStream对象
2、创建BufferedInputStream对象,构造方法中放入fis
3、使用bis的read方法
4、释放资源
*/
@Test
public void test2() throws IOException {
FileInputStream fis=new FileInputStream("D:\\program testing\\javatest\\JavaHHHLevel\\src\\io\\bufferede\\test.txt");
BufferedInputStream bis=new BufferedInputStream(fis);
int len=0;
/* while ((len=bis.read())!=-1){
System.out.println(len);
}*/
//read(byte[] b)从输入流中读取一定数量的字节并存储在缓冲区b中
byte[] bytes=new byte[3];
while ((len=bis.read(bytes))!=-1){
System.out.print(new String(bytes,0,len));
}
bis.close();
}
到现在为止,最快的就是缓冲流+缓冲数组一起用
字符缓冲流
/*
BufferedWrite:字符缓冲输出流 extends Write
构造方法:
BufferedWrite(Write out)创建一个使用默认缓冲区的缓冲字符输出流
BufferedWrite(Write out,int sz)创建一个使用指定缓冲区的缓冲字符输出流
参数:同字节缓冲流,可以传FileWrite
特有的成员方法:newline():写入一个行分隔符,会根据不同的系统,获取不同的行分隔符
使用步骤和缓冲字节流一样
*/
@Test
public void test1() throws IOException {
BufferedWriter bw=new BufferedWriter(new FileWriter("D:\\program testing\\javatest\\JavaHHHLevel\\src\\io\\bufferede\\test.txt"));
bw.write("写一个啥呢?,我换个行吧");
bw.write("\r\n");
bw.write("我还想换个行");
bw.newLine();//换行方法
bw.write("换行成功了");
bw.flush();
bw.close();
System.out.println();
}
其中println也调用了newLine
![](https://i-blog.csdnimg.cn/blog_migrate/913d2c02b18de19764269fae4949d984.png)
/*
字符缓冲输入流:BufferedReader extends Reader
构造方法:BufferedReader(Reader in,int sz)
同样是一个默认缓冲区,一个指定缓冲区
可以传递FileReader
特有的成员方法
String readLine()读取一个文本行。就是读一行数据
有下列字符之一就认为是换行,\n,\r,\r\n
返回:
包含该行内容的字符串,不包含任何终止符,如果已达末尾,则返回null
使用步骤都差不多
*/
public class Demo3 {
@Test
public void test1() throws IOException {
BufferedReader br=new BufferedReader(new FileReader("D:\\program testing\\javatest\\JavaHHHLevel\\src\\io\\bufferede\\test.txt"));
System.out.println(br.readLine());
String line;
/*System.out.println((char)br.read());*/
while ((line=br.readLine())!=null)
{
System.out.println(line);
}
br.close();
}
}
转换流
/*转换流
字符编码:
编码:字符-->字节
解码:字节-->字符
字符集:一套自然语言与二进制数之间的对应规则
常用字符集:
ASCII:主要用于显示英语,基本ASCII 7bis表示一个字节,共128字符
扩展字符集8位表示一个字符共256字符,方便支持欧洲常用字符
ISO-8859-1:用于显示欧洲的语言,使用单字节编码,兼容ASCII
GBxxx字符集:GB表示国标,为显示中午而设计的一套字符集
GB2312:简称中文码表,小于127的字符意义与原来相同,但两个大于127的字符连在一起就表示一个汉字
可以表示7000多个汉字,此外各种符号包括全角字符也包含在内
GBK:最常用的中文码表,在GB2312上扩展而来,使用双字节编码,收录21003个汉字,兼容BG2312,支持繁体及日韩汉字等
GB18030:最新的中文字表,收录70244个汉字,采用多字节编码由1个、2个、或4、个字节组成,支持少数民族文字
Unicode字符集:为表达任意语言的任意字符而设计,是业界的一种标准,也就是统一码,标准万国码。
最多使用4个字节来表达每个字母、符号、或者文字。
有三种编码方式:UTF-8,UTF-16,UTF-32,-8最常用
互联网IETF小组要求所有互联网协议都要支持UTF-8所以,开发Web应用也要使用UTF-8,它使用一至四个字节为每个字符编码
规则:
1、1-128个US-ASCII只需要一个字节编码
2、拉丁文,二个字节
3、大部分常用字(含中文),使用三个字节编码
4、其他极少使用的Unicode辅助字符,使用四字节编码
编码引出的问题:
FileReader可以读取idea默认格式UTF-8的文件,但是读取系统默认编码GBK时会乱码
*/
utf-8读取GBK产生乱码的演示:
FileReader fr=new FileReader("src\\io\\gbk编码文件.txt");
int len;
while ((len=fr.read())!=-1){
System.out.print((char)len);
}
fr.close();
转换流的原理及使用
FileReader实际上是将FileInputStream转换成能看懂的字符,但是构造方法假定默认字符编码和默认字节缓冲区大小都是适当的。要指定这些值,可以现在FileInputStream上构造一个InputStreamReader
InputStreamReader类 extendsReader:是字节通向字符流的桥梁,它使用指定的charset读取字节并将其解码为字符
OutputStreamWriter类 extends Writer:是字符流通向字节流的桥梁:可以使用指定的charset将要写入流中的字符编码成字节
/*
OutputStreamWriter
构造方法:
OutputStreamWriter(OutputStream out)创建使用默认字符编码的OutputStreamWriter
OutputStreamWriter(OutputStream out,String charsetName)创建使用指定字符集的OutputStreamWriter
参数:
out:字节输出流,可以用来写转换之后的字节到文件中
charsetName:指定的编码表名称,不区分大小写
使用步骤:
1、创建OutputStreamWriter对象,构造方法中传递字节输出流和指定的编码名称
2、使用write方法写到缓冲区
3、使用flush刷新到文件中
4、释放资源
*/
public class Demo9 {
public static void main(String[] args) throws IOException {
utf_8("你好,我是使用utf-8写的txt文件");
gbk("你好,我是使用gbk写的txt文件");
}
private static void utf_8(String write) throws IOException {
OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("src\\io\\utf_8编码文件.txt"),"utf-8");
osw.write(write);
osw.flush();
osw.close();
}
private static void gbk(String write) throws IOException {
OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("src\\io\\gbk编码文件.txt"),"gbk");
osw.write(write);
osw.flush();
osw.close();
}
}
/*
InputStreamReader
构造方法:
InputStreamReader(InputStream in)
InputStreamReader(InputStream in,charsetName)
使用步骤:
1、创建对象,传入字节输入流和指定的编码表名称
2、使用read方法读取文件
3、释放资源
注意:构造方法中指定的编码表名称要和文件的编码相同,否则会乱码
*/
public class Demo10 {
public static void main(String[] args) throws IOException {
utf_8();
System.out.println();
gbk();
}
private static void utf_8() throws IOException {
InputStreamReader isr=new InputStreamReader(new FileInputStream("src\\io\\utf_8编码文件.txt"),"utf-8");
int len=0;
while ((len=isr.read())!=-1){
System.out.print((char)len);
}
isr.close();
}
private static void gbk() throws IOException {
InputStreamReader isr=new InputStreamReader(new FileInputStream("src\\io\\gbk编码文件.txt"),"gbk");
int len=0;
while ((len=isr.read())!=-1){
System.out.print((char)len);
}
isr.close();
}
}
序列化
序列化:把对象以流的方式写到文件中保存,叫写对象,也叫对象的序列化
反序列化:把文件中保存的对象,以流的方式读取出来,叫做读对象
序列化流:
/*
java.io.ObjectOutputStream extends OutputStream
也叫:对象的序列化流
构造方法:
ObjectOutputStream(OutputStream out)创建写入指定OutputStream的ObjectOutputStream
参数:
out:字节输出流
特有的成员方法
:
void writeObject(Object obj) 将指定的对象写入objectStream
使用步骤:
1、创建对象,构造方法中传入OutputStream
2、使用writeObject把对象写入到文件中
注意:类只有实现了Serializable接口才能被序列化,否则会抛出NotSerializableException异常
Serializable接口也叫标记型接口
当我们进行序列化和反序列化时,就会检测类上是否有这个标记
有:就可以进行序列化和反序列化
没有:就会出现NotSerializableException异常
*/
public class Demo1 {
public static void main(String[] args) throws IOException {
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("src\\io\\序列化流\\person.txt"));
oos.writeObject(new Person("无名者",18));
oos.close();
}
/*
反序列化:
ObjectInputStream extends InputStream
作用:把文件中保存的对象,以流的方式读取出来使用
构造方法:
ObjectInputStream(InputStream in)
特有的成员方法:
readObject()
会抛出ClassNotFoundException
当找不到class文件时会抛出此异常
反序列化的前提:
1、类必须实现Serializable
2、必须存在类对应的class文件
使用步骤:
1、创建对象,传入参数
2、readObject方法
3、释放资源
4、使用读取出来的对象
*/
@Test
public void test1() throws IOException, ClassNotFoundException {
ObjectInputStream ois=new ObjectInputStream(new FileInputStream("src\\io\\序列化流\\person.txt"));
Object o = ois.readObject();
System.out.println(o);
ois.close();
}
}
反序列化的产生的一些问题
InvalidClassException异常
当序列化一个对象后,更改了此对象,在反序列化的时候就会报这个异常
原因:每次修改类的定义就会给class文件生成一个新的序列号(serialVersionUID),当序列化一个对象的时候会把这个序列号添加进去,反序列化的时候就会比对txt文件和.class文件的序列号,当序列号不一致的时候就会报InvalidClassException
解决方案
无论是否对类的定义进行修改,都不生成新的序列号
格式在Serializable接口规定:
可序列化类可以通过声明名为“SerialVersionUID”的字段(该字段必须是静态的、最终的long型字段)显式声明自己的SerialVersionUID:
演示:
transient
static关键字修饰的变量优先于对象加载入内存,不能被序列化
例如age属性被static修饰后,序列化该对象,在反序列化后age输出得0
瞬态关键字:同样被transient修饰的变量不能被序列化,但是被其修饰的变量不会具有跟static一样的特性,用起来跟普通变量一样,只是不能被序列化,是一个序列化标记
打印流
sout就是一个打印流,java.io.PrintStream类 extends FilterOutputStream
PrintStream为其他输出流添加了功能,使他们能够方便地打印各种数据值表示形式
特点:
1、只负责数据的输出,不负责读取
2、与其他输出流不同,PrintStream永远不会抛出IOException
3、有特有的方法,print、println
void print(任意类型的值)
void println(任意类型的值并换行)
构造方法:
PrintStream(File file):输出的目的地是一个文件
PrintStream(OutputStream out):输出的目的地是一个字节输出流
PrintStream(String fileName):输出的目的地是一个文件路径
还有继承自OutputStream的方法等
注意:如果使用继承子父类的write方法写数据,那么查看数据的时候会查询编码表
如果使用自己的特有方法print/println方法写数据,写的数据原样输出
使用演示:
public class PrintStreamTest {
public static void main(String[] args) throws FileNotFoundException {
PrintStream ps=new PrintStream("src\\io\\print.txt");
ps.write(97);
ps.println(97);
ps.println(true);
ps.println("PrintStream流");
ps.close();
}
打印结果:
/*
可以改变输出语句的目的地(打印流的流向)
输出语句,默认在控制台输出
使用System.setOut方法改变输出语句的目改为的参数传递的打印流的目的地
static void setOut(PrintStream out)
*/
@Test
public void test() throws FileNotFoundException {
System.out.println("我是在控制台输出");
PrintStream ps=new PrintStream("src\\io\\打印流目的.txt");
System.setOut(ps);//把输出语句的目的地改变为打印流的目的地
System.out.println("我在打印流的目的地中输出");
ps.close();
}
}