1.标准输入流输出流
默认字节流
1.标准输入流
1.System.in
属性
1.当前的流已经打开并关联了输入源–键盘
2.如果不想让键盘充当输入源,可以通过setIn进行更换
标准输入流的read方法为阻塞式方法
2.阻塞式方法
程序一直停在read()方法这里,等待数据。没有数据就不继续往下执行,至到得到数据。
2.标准输出流
System.out
定义:
1.此流已打开并准备接受输出数据。通常,此流对应于显示器输出或者由主机环境或用户指定的另一个输出目标。
2.可以通过setout进行更换输出源
3.标准输出流本质是PrintStream类
3.小小的总结
1.输入输出源
//将键盘作为输入源
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
//将文件作为输入源
BufferedReader bufferedReader1 = new BufferedReader(new FileReader("temp1.txt"));
//将控制台作为输出源
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(System.out));
//将文件作为输出源
BufferedWriter bufferedWriter1 = new BufferedWriter(new FileWriter("temp2.txt"));
2.更改输入源
这里是临时更换,只能在当前程序中使用更换后的输入源输出源,如果在其他的程序中会自动变回原来的输入源输出源
2.转换流
转换流的本质是字符流
Object->Reader->FileReader(调用InputStreamReader,InputSreamReader(调用StreamDecoder,内含指定字符编码的功能)
1.InputStreamReader
1.构造方法
InputStreamReader(InputStream in,String charsetName) //接收所有的字节输入流
2.读取
FileInputStream fis = new FileInputStream("c:\\utf.txt");
//创建转换流对象,构造方法中,包装字节输入流,同时写编码表名
InputStreamReader isr = new InputStreamReader(fis,"UTF-8");
char[] ch = new char[1024];
int len = isr.read(ch);
System.out.println(new String(ch,0,len));
isr.close();
2.OutputStreamWriter
1.构造方法
OutputStreamWriter(OutputStream out, String charsetName) //接收所有的字节输出流
String charsetName 传递编码表名字 GBK UTF-8
2.读取
FileOutputStream fos = new FileOutputStream("c:\\utf.txt");
//创建转换流对象,构造方法保证字节输出流,并指定编码表是UTF-8
OutputStreamWriter osw = new OutputStreamWriter(fos,"UTF-8");
osw.write("你好");
osw.close();
3.打印流
打印流添加输出数据的功能,使它们能够方便地打印各种数据值表示形式.
1.分类
字节打印流 PrintStream
构造方法:接收File类型,接收字符串文件名,接收字节输出流OutputStream
字符打印流 PrintWriter
构造方法接收File类型,接收字符串文件名,接收字节输出流OutputStream, 接收字符输出
2.特点
- 此流不负责数据源,只负责数据目的
- 为其他输出流,添加功能
- 永远不会抛出IOException,但是可能抛出别的异常
- 两个打印流的方法,完全一致
- 构造方法,就是打印流的输出目的端
3.字节打印流
write方法会默认的将类型转换为byte,所以会丢失精度
* 1.File类型的文件
* 2.字符串类型的文件
* 3.字节输出流
PrintStream printStream1 = new PrintStream(new File("test2.txt"));
PrintStream printStream2 = new PrintStream("test2.txt");
PrintStream printStream3 = new PrintStream(new FileOutputStream("test.txt"));
printStream3.println("haha");
printStream1.close();
printStream2.close();
printStream3.close();
PrintStream printStream4 = new PrintStream(new FileOutputStream("test5.txt"));
printStream4.write(97);//00000000 00000000 00000000 01100001 默认将前三个字节砍掉 01100001 a
printStream4.write(353);//00000000 00000000 00000001 01100001 默认将前三个字节砍掉 01100001 a
printStream4.print(353);
//这是print方法的内部实现原理
//先将353转成字符串再转成字节数组
printStream4.write(String.valueOf(353).getBytes());
printStream4.close();
4.字符打印流
-
- 1.File类型的文件 - 2.字符串类型的文件 - 3.字节输出流 - 4.字符写出流 - - 注意点: - public PrintWriter(Writer out, boolean autoFlush) - autoFlush - boolean 变量;如果为 true,则 println、printf 或 format 方法将刷新输出缓冲区 - */ public class Demo11 { public static void main(String[] args) throws IOException { //3.支持字节输出流 PrintWriter printWriter = new PrintWriter(new FileOutputStream("test6.txt")); //4.支持字符写出流 PrintWriter printWriter2 = new PrintWriter(new FileWriter("test6.txt")); printWriter.close(); printWriter2.close(); } }
4.序列化
1.Properties
hashtable的子类
1.定义
实际上就是Map集合,存储的是属性,属性以键值对的方式存储.这里的键和值都必须是字符串.所以不需要考虑泛型
2.序列化
1.定义
-
序列化:将数据从内存放入磁盘,可以实现数据的长久保存–数据持久化的手段
-
反序列化:将数据从磁盘放回内存
[外链图片转存失败(img-2Q9jdWp4-1565247744411)(C:\Users\root\Desktop\总结\assets\Properties的工作原理.png)]
2.properties的应用
//1.Properties的基础
public static void fun1() {
//创建对象
Properties properties = new Properties();
properties.setProperty("a", "java");
properties.setProperty("b", "html");
System.out.println(properties);
//根据key取值
System.out.println(properties.getProperty("a"));
//key是唯一的
Object object = properties.setProperty("a", "BigData");
System.out.println(object);
//当前的key在Properties中不存在时,会打印python
System.out.println(properties.getProperty("c", "python"));
```
}
//2.利用Properties获取系统属性
public static void fun2() {
Properties properties = System.getProperties();
//遍历
Set<String> set = properties.stringPropertyNames();
```
// Iterator<String> iterator = set.iterator();
// while (iterator.hasNext()) {
// String string = (String) iterator.next();
// System.out.println("key:"+string+" value:"+properties.getProperty(string));
// }
//增强for循环
for (String key : set) {
System.out.println("key:"+key+" value:"+properties.getProperty(key));
}
//对系统属性的某个属性进行更改
properties.setProperty("sun.jnu.encoding", "UTF8");
System.out.println(properties.getProperty("sun.jnu.encoding"));
//重新获取一遍值
//原理:会先到内存中找属性集合的对象,如果有,直接使用.如果没有,会重新初始化一个新的对象,并获取属性集合.
Properties properties1 = System.getProperties();
System.out.println(properties1.getProperty("sun.jnu.encoding"));
properties1.list(System.out);
}
//3.Properties在实际中的使用
public static void fun3() throws FileNotFoundException, IOException {
//创建Properties对象
Properties properties = new Properties();
//利用load方法将内容从磁盘读到内存
//注意:使用的文件内容的格式应用是key=value
properties.load(new FileReader("text3.txt"));
properties.list(System.out);
//更改内容
properties.setProperty("a", "hehe");
//写会磁盘 第二个参数是提醒信息
properties.store(new FileWriter("text3.txt"), "hello world");
}
3.序列化步骤
进行序列化的步骤:–通过对象的序列化讲解
- 1.创建一个类
- 2.使用对应的流将对象存入磁盘中----序列化----ObjectOutputStream
- 3.使用对应的流将对象从磁盘中取出放回内存–反序列化------ObjectInputStream
- 4.关闭流
注意点:序列化流在工作时也要关联对应的基本的输入流和输出流
4.序列化接口
1.接口
一个类如果没有实现Serializable,进行序列化会报异常:NotSerializableException
2.Serializable详解
实现了Serializable接口的类可以达到的目的:
1.可以进行序列化
2.进行序列化的类的元素都必须支持序列化
3.接口本身没有方法或字段,只是用来表示可序列化的语义
3.注意点
-
- ClassNotFoundException:当前的类没有找到
分析:将Person对象进行序列化之后,将Person类删除,再进行反序列化的时候出现了异常
原因:反序列化在执行的时候依赖字节码文件,当类没有了,字节码文件无法创建,反序列化失败
-
2.java.io.InvalidClassException 无效的类
出现的原因:没有声明自己的serialVersionUID,而使用系统的.在进行反序列化的时候,类被改动了,系统认为现在的类
已经不是原来的类了(在使用系统的id进行识别的时候,重写给Person设置了id),认为此类无效
-
3.使用系统的serialVersionUID与自定义的ID的区别?
使用系统的,序列化和反序列化,id不能手动设置,使用的是编译器默认生成的,一旦类发生了改动,id会重新赋值
使用自定义的,序列化和反序列化,id不会发生改变,所以当反序列化的时候,即使对Person类进行了一些改动,也能继续反序列化
-
4.总结序列化,反序列化工程的注意点:
a.合理使用序列化流和反序列化流,要与输入流与输出流配合使用
b.进行序列化的类一定要实现Serializable接口,只要实现了接口就可以序列化.包括集合,包装类等
c.进行序列化的类要保证当前类与内部的类都要实现Serializable接口
*/
//要想让Person类的对象可以实现序列化,必须让Person类实现Serializable接口
//类通过实现 java.io.Serializable 接口以启用其序列化功能。
//注意:不仅要求当前类可序列化,而且要求当前类的所有子类型本身都是可序列化的(比如:ArrayList)
class Person implements Serializable{
// /**
// * generated:由编译器自动生成的,后面加L表示long型
// */
private static final long serialVersionUID = -7224641225172644265L;
// /**
// * default:UID是由用户自己指定的,默认值是1L
// */
// private static final long serialVersionUID = 1L;
String name;
//int age;
public Person(String name) {
this.name = name;
}
public String toString() {
return "Person [name=" + name + "]";
}
}
public class Demo13 {
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
//对象的序列化
//objectWrite();
//对象的逆序列化流
objectRead();
}
//对象的序列化
// public static void objectWrite() throws FileNotFoundException, IOException {
//
// ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("test6.txt"));
// //objectOutputStream.writeInt(100);
// //对象序列化
// Person person = new Person("bingbing");
// objectOutputStream.writeObject(person);
// objectOutputStream.close();
// }
```
//对象的逆序列化流
//序列化的东西要通过逆序列化流读取
public static void objectRead() throws FileNotFoundException, IOException, ClassNotFoundException {
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("test6.txt"));
```
// int value = objectInputStream.readInt();
// System.out.println(value);
Object object = objectInputStream.readObject();
System.out.println(object);
objectInputStream.close();
}
}
5.注意事项
静态不能序列化
A: 静态不能序列化
序列化是把对象数据进行持久化存储
静态的东西不属于对象,而属于类
transient关键字
A: transient关键字
被transient修饰的属性不会被序列化
transient关键字只能修饰成员变量
6.数据流
datainputstream
dataoutputstream
7.内存流
没有出内存
close无用