标准流和打印流
标准流和打印流虽然在日常生活中比较少见,但是这两个与底层的源码息息相关,所以为了深入聊节I/O操作,需要学习这两个流。
标准流
1、我们与ide交换信息时也需要输入流操作,而我们平时都没有见过直接用流来直接输入,而会用到一个类,这个类是什么?它的底层原理是什么?
__针对问题一:__通常情况下我们使用scanner类与ide实现信息输入,scanner底层实现了对输入流的一种包装盒加强。
标准流包含标准输出流和标准输入流,小猿将这连个流结合使用入一个例子中。
案例一
不利用scanner 实现从键盘上的输入。
public class StandardStream {
public static void main(String[] args) throws IOException {
//InputStream in = System.in;
// int by;
// while ((by=in.read())!=-1){
// System.out.println((char)by);
// }
//InputStreamReader isr = new InputStreamReader(in);
//BufferedReader br = new BufferedReader(isr);
System.out.println("------------------------------------------------");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line;
System.out.println("请出入字符串:");
while ((line = br.readLine())!=null){
System.out.println("你输入的字符串是: "+line);
if(line.equals("null")){
break;
}
}
System.out.println("请输入一个整数:");
int i = Integer.parseInt(br.readLine());
System.out.println("您输入的整数是:"+i);
br.close();
System.out.println("--------------------标准输出流练习--------------------");
PrintStream ps =System.out;
ps.print("hello");
ps.print("world");
System.out.println("hello");
System.out.println("world");
System.out.println("----------------------------");
}
}
运行结果:
结论:输出语句的本质是一个标准的输出流。
打印流
1、打印流和字符输出流之间的区别是什么?
__针对问题一:__打印流写文件和字符输出流写文件的有不同操作方法。
字符输出流写文件
在构造函数中可以看到有另外一个参数autoFlush。
while ((line=br.readLine())!=null) {
bw.write(line);
bw.newLine();
bw.flush();
}
打印流写文件
while ((line = br.readLine())!=null){
pw.println(line);
}
由上面两种代码对比可知打印流是autoflush的,而字符流则必须自己将flush加上。
案例二
public class PrintDemo {
public static void main(String[] args) throws IOException {
printStream();
printWriter();
copyFiles();
}
public static void printWriter() throws IOException {
System.out.println("-----------字符打印流---------------");
// PrintWriter pw = new PrintWriter("reader&writer\\PrintWriter.txt");
// pw.write("hello");
// pw.write("\r\n");
// pw.flush();
// //pw.write("world");
// pw.println("world");
// pw.flush();
PrintWriter pw = new PrintWriter(new FileWriter("reader&writer\\PrintWriter.txt"),true);
pw.println("hello");
// pw.write("hello");
// pw.write("\r\n");
// pw.flush();
pw.println("world");
pw.close();
}
public static void printStream() throws FileNotFoundException {
System.out.println("----------字节流打印流------------");
PrintStream ps = new PrintStream("reader&writer\\PrintStream.txt");
ps.println(97);
ps.println(98);
ps.println(99);
ps.close();
System.out.println("--------------------------------");
}
public static void copyFiles() throws IOException {
BufferedReader br = new BufferedReader(new FileReader("reader&writer\\src\\charbuffer\\PrintDemo.java"));
PrintWriter pw = new PrintWriter(new FileWriter("reader&writer\\copy.java"),true);
String line;
while ((line = br.readLine())!=null){
pw.println(line);
System.out.println(line);
}
br.close();
pw.close();
}
}
运行结果达到预期效果
这两种方法其效果都是一样的,至于效率如何,小猿目前不是太清楚。
序列化流
1、为什么需要序列化流?
2、序列化流中需要注意中出现“java.io.NotSerializeableException”是什么问题引发的?若果要继承接口,为什么该接口没有实现的方法?
3、用对象序列化流序列化了一个对象后,假如修改了对象所属类的文件,读数据会不会出现问题呢?如果出问题了,如何解决呢?
4、若果一个对象中的某一个成员变量不想被序列化,有该如何实现呢?
__针对问题一:__作为对象在网络传输中存在着诸多问题,对象直接在网络中传输或者存储在硬盘中不是很不方便,至于为什么不方便,请参考为什么要序列化所以就引入序列化流。
__针对问题二:__需要实现Serializable接口,Serializable接口是标识性接口,所以不需要实现其他的方法之类的。
__针对问题三:__会出现问题,序列化流在序列化对象之前需要生成一个序列化版本号,方便在反序列化是实现版本匹配,当发对象文件被修改时,则会抛出异常。这是后我们就需要修改默认规则,修改方法是加入如下代码,使得序列化版本一致即可 。
private static final long serialVersionUID =xxxx;
__针对问题四:__如果不想一个成员变量序列化,则需要提价申明加入关键字transient;
案例一
序列化读写person 类,必须实现Serializable接口。
public class Person implements Serializable {
private static final long serialVersionUID =400;
private String name;
private int age;
private transient String phoneNum;
public Person() {
}
public Person(String name, int age, String phoneNum) {
this.name = name;
this.age = age;
this.phoneNum = phoneNum;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getPhoneNum() {
return phoneNum;
}
public void setPhoneNum(String phoneNum) {
this.phoneNum = phoneNum;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", phoneNum='" + phoneNum + '\'' +
'}';
}
}
测试类
public class SerilizableStream {
public static void main(String[] args) throws IOException, ClassNotFoundException {
write();
read();
}
public static void write() throws IOException {
//序列化
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("reader&writer\\SerializableOutStream.txt"));
Person p1 = new Person("唐建秀", 31, "13883073323");
oos.writeObject(p1);
oos.close();
}
public static void read() throws IOException, ClassNotFoundException {
//反序列化
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("reader&writer\\SerializableOutStream.txt"));
Object o = ois.readObject();
Person p=(Person)o;
System.out.println(p);
ois.close();
}
}
测试结果
测试结果符合预期。