1 标准输入流【应用】
System 类中有两个静态的成员变量
public static fifinal InputStream in :标准输入流。通常该流对应于键盘输入或由主机环境或用户指定的
另一个输入源
public static fifinal PrintStream out :标准输出流。通常该流对应于显示输出或由主机环境或用户指定的
另一个输出目标
自己实现键盘录入数据
public class SystemInDemo { public static void main ( String [] args ) throws IOException { //public static final InputStream in :标准输入流 // InputStream is = System.in; // int by; // while ((by=is.read())!=-1) { // System.out.print((char)by); // } // 如何把字节流转换为字符流?用转换流 // InputStreamReader isr = new InputStreamReader(is); // // 使用字符流能不能够实现一次读取一行数据呢?可以 // // 但是,一次读取一行数据的方法是字符缓冲输入流的特有方法 // BufferedReader br = new BufferedReader(isr); BufferedReader br = new BufferedReader ( new InputStreamReader ( System . in )); System . out . println ( " 请输入一个字符串: " ); String line = br . readLine (); System . out . println ( " 你输入的字符串是: " + line ); System . out . println ( " 请输入一个整数: " ); int i = Integer . parseInt ( br . readLine ()); System . out . println ( " 你输入的整数是: " + i ); // 自己实现键盘录入数据太麻烦了,所以 Java 就提供了一个类供我们使用 Scanner sc = new Scanner ( System . in ); } }
2 标准输出流【应用】
System 类中有两个静态的成员变量
public static fifinal InputStream in :标准输入流。通常该流对应于键盘输入或由主机环境或用户指定的
另一个输入源
public static fifinal PrintStream out :标准输出流。通常该流对应于显示输出或由主机环境或用户指定的
另一个输出目标
输出语句的本质:是一个标准的输出流
PrintStream ps = System.out;
PrintStream 类有的方法, System.out 都可以使用
示例代码
public class SystemOutDemo { public static void main ( String [] args ) { //public static final PrintStream out :标准输出流 PrintStream ps = System . out ; // 能够方便地打印各种数据值 // ps.print("hello"); // ps.print(100); // ps.println("hello"); // ps.println(100); //System.out 的本质是一个字节输出流 System . out . println ( "hello" ); System . out . println ( 100 ); System . out . println (); // System.out.print(); }
}
3 字节打印流【应用】
打印流分类
字节打印流: PrintStream
字符打印流: PrintWriter
打印流的特点
只负责输出数据,不负责读取数据
永远不会抛出 IOException
有自己的特有方法
字节打印流
PrintStream(String fifileName) :使用指定的文件名创建新的打印流
使用继承父类的方法写数据,查看的时候会转码;使用自己的特有方法写数据,查看的数据原样输出
可以改变输出语句的目的地
public static void setOut(PrintStream out) :重新分配 “ 标准 ” 输出流
示例代码
public class PrintStreamDemo { public static void main ( String [] args ) throws IOException { //PrintStream(String fileName) :使用指定的文件名创建新的打印流 PrintStream ps = new PrintStream ( "myOtherStream\\ps.txt" ); // 写数据 // 字节输出流有的方法 // ps.write(97); // 使用特有方法写数据 // ps.print(97); // ps.println(); // ps.print(98); ps . println ( 97 ); ps . println ( 98 ); // 释放资源 ps . close (); } }
4 字符打印流【应用】
字符打印流构造房方法
示例代码
public class PrintWriterDemo { public static void main ( String [] args ) throws IOException { //PrintWriter(String fileName) :使用指定的文件名创建一个新的 PrintWriter ,而 不需要自动执行行刷新 // PrintWriter pw = new PrintWriter("myOtherStream\\pw.txt"); // pw.write("hello"); // pw.write("\r\n"); // pw.flush(); // pw.write("world"); // pw.write("\r\n"); // pw.flush(); // pw.println("hello"); /* pw.write("hello"); pw.write("\r\n"); */ // pw.flush(); // pw.println("world"); // pw.flush(); //PrintWriter(Writer out, boolean autoFlush) :创建一个新的 PrintWriter PrintWriter pw = new PrintWriter ( new FileWriter ( "myOtherStream\\pw.txt" ), true ); // PrintWriter pw = new PrintWriter(new FileWriter("myOtherStream\\pw.txt"),false); pw . println ( "hello" ); /* pw.write("hello"); pw.write("\r\n"); pw.flush(); */ pw . println ( "world" ); pw . close (); } }
5 复制Java文件打印流改进版【应用】
案例需求
把模块目录下的 PrintStreamDemo.java 复制到模块目录下的 Copy.java
分析步骤
根据数据源创建字符输入流对象
根据目的地创建字符输出流对象
读写数据,复制文件
释放资源
代码实现
public class CopyJavaDemo { public static void main ( String [] args ) throws IOException { /* // 根据数据源创建字符输入流对象 BufferedReader br = new BufferedReader(new FileReader("myOtherStream\\PrintStreamDemo.java")); // 根据目的地创建字符输出流对象 BufferedWriter bw = new BufferedWriter(new FileWriter("myOtherStream\\Copy.java")); // 读写数据,复制文件 String line; while ((line=br.readLine())!=null) { bw.write(line); bw.newLine(); bw.flush(); } // 释放资源 bw.close(); br.close(); */ // 根据数据源创建字符输入流对象 BufferedReader br = new BufferedReader ( new FileReader ( "myOtherStream\\PrintStreamDemo.java" )); // 根据目的地创建字符输出流对象 PrintWriter pw = new PrintWriter ( new FileWriter ( "myOtherStream\\Copy.java" ), true ); // 读写数据,复制文件 String line ; while (( line = br . readLine ()) != null ) { pw . println ( line ); } // 释放资源 pw . close (); br . close (); } }
6 对象序列化流【应用】
对象序列化介绍
对象序列化:就是将对象保存到磁盘中,或者在网络中传输对象
这种机制就是使用一个字节序列表示一个对象,该字节序列包含:对象的类型、对象的数据和对象中存
储的属性等信息
字节序列写到文件之后,相当于文件中持久保存了一个对象的信息
反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化
对象序列化流: ObjectOutputStream
将 Java 对象的原始数据类型和图形写入 OutputStream 。 可以使用 ObjectInputStream 读取(重构)对
象。 可以通过使用流的文件来实现对象的持久存储。 如果流是网络套接字流,则可以在另一个主机上或
另一个进程中重构对象
构造方法
序列化对象的方法
示例代码
学生类
public class Student implements Serializable { private String name ; private int age ; public Student () { } public Student ( String name , int age ) { this . name = name ; this . age = age ; } 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 ; } @Override public String toString () { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}' ; } }
测试类
public class ObjectOutputStreamDemo { public static void main ( String [] args ) throws IOException { //ObjectOutputStream(OutputStream out) :创建一个写入指定的 OutputStream 的 ObjectOutputStream ObjectOutputStream oos = new ObjectOutputStream ( new FileOutputStream ( "myOtherStream\\oos.txt" )); // 创建对象 Student s = new Student ( " 林青霞 " , 30 ); //void writeObject(Object obj) :将指定的对象写入 ObjectOutputStream oos . writeObject ( s ); // 释放资源 oos . close (); } }
注意事项
一个对象要想被序列化,该对象所属的类必须必须实现 Serializable 接口
Serializable 是一个标记接口,实现该接口,不需要重写任何方法
7 对象反序列化流【应用】
对象反序列化流: ObjectInputStream
ObjectInputStream 反序列化先前使用 ObjectOutputStream 编写的原始数据和对象
构造方法
反序列化对象的方法
示例代码
public class ObjectInputStreamDemo { public static void main ( String [] args ) throws IOException , ClassNotFoundException { //ObjectInputStream(InputStream in) :创建从指定的 InputStream 读取的 ObjectInputStream ObjectInputStream ois = new ObjectInputStream ( new FileInputStream ( "myOtherStream\\oos.txt" )); //Object readObject() :从 ObjectInputStream 读取一个对象 Object obj = ois . readObject (); Student s = ( Student ) obj ; System . out . println ( s . getName () + "," + s . getAge ()); ois . close (); } }
8 serialVersionUID&transient【应用】
serialVersionUID
用对象序列化流序列化了一个对象后,假如我们修改了对象所属的类文件,读取数据会不会出问题呢?
会出问题,会抛出 InvalidClassException 异常
如果出问题了,如何解决呢?
重新序列化
给对象所属的类加一个 serialVersionUID
private static fifinal long serialVersionUID = 42L;
transient
如果一个对象中的某个成员变量的值不想被序列化,又该如何实现呢?
给该成员变量加 transient 关键字修饰,该关键字标记的成员变量不参与序列化过程
示例代码
学生类
public class Student implements Serializable { private static final long serialVersionUID = 42L ; private String name ; // private int age; private transient int age ; public Student () { } public Student ( String name , int age ) { this . name = name ; this . age = age ; } 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 ; } // @Override // public String toString() { // return "Student{" + // "name='" + name + '\'' + // ", age=" + age + // '}'; // } }
测试类
public class ObjectStreamDemo { public static void main ( String [] args ) throws IOException , ClassNotFoundException { // write(); read (); } // 反序列化 private static void read () throws IOException , ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream ( new FileInputStream ( "myOtherStream\\oos.txt" )); Object obj = ois . readObject (); Student s = ( Student ) obj ; System . out . println ( s . getName () + "," + s . getAge ()); ois . close (); } // 序列化 private static void write () throws IOException { ObjectOutputStream oos = new ObjectOutputStream ( new FileOutputStream ( "myOtherStream\\oos.txt" )); Student s = new Student ( " 林青霞 " , 30 ); oos . writeObject ( s ); oos . close (); } }