1:登錄註冊IO版本案例(掌握)
要求,對着寫一遍。
cn.itcast.pojo User
cn.itcast.dao UserDao
cn.itcast.dao.impl UserDaoImpl(實現我不管)
cn.itcast.game GuessNumber
cn.itcast.test UserTest
2:數據操作流(操作基本類型數據的流)(理解)
(1)可以操作基本類型的數據
(2)流對象名稱
DataInputStream
DataOutputStream
3:內存操作流(理解)
(1)有些時候我們操作完畢後,未必需要產生一個文件,就可以使用內存操作流。
(2)三種
A:ByteArrayInputStream,ByteArrayOutputStream
B:CharArrayReader,CharArrayWriter
C:StringReader,StringWriter
4:打印流(掌握)
(1)字節打印流,字符打印流
(2)特點:
A:只操作目的地,不操作數據源
B:可以操作任意類型的數據
C:如果啓用了自動刷新,在調用println()方法的時候,能夠換行並刷新
D:可以直接操作文件
問題:哪些流可以直接操作文件呢?
看API,如果其構造方法能夠同時接收File和String類型的參數,一般都是可以直接操作文件的
(3)複製文本文件
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
PrintWriter pw = new PrintWriter(new FileWriter("b.txt"),true);
String line = null;
while((line=br.readLine())!=null) {
pw.println(line);
}
pw.close();
br.close();
Demo:
import java.io.IOException; import java.io.PrintWriter; /* * 打印流 * 字節流打印流 PrintStream * 字符打印流 PrintWriter * * 打印流的特點: * A:只有寫數據的,沒有讀取數據。只能操作目的地,不能操作數據源。 * B:可以操作任意類型的數據。 * C:如果啓動了自動刷新,能夠自動刷新。 * D:該流是可以直接操作文本文件的。 * 哪些流對象是可以直接操作文本文件的呢? * FileInputStream * FileOutputStream * FileReader * FileWriter * PrintStream * PrintWriter * 看API,查流對象的構造方法,如果同時有File類型和String類型的參數,一般來說就是可以直接操作文件的。 * * 流: * 基本流:就是能夠直接讀寫文件的 * 高級流:在基本流基礎上提供了一些其他的功能 */ public class PrintWriterDemo { public static void main(String[] args) throws IOException { // 作爲Writer的子類使用 PrintWriter pw = new PrintWriter("pw.txt"); pw.write("hello"); pw.write("world"); pw.write("java"); pw.close(); } }
Demo2:
import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; /* * 1:可以操作任意類型的數據。 * print() * println() * 2:啓動自動刷新 * PrintWriter pw = new PrintWriter(new FileWriter("pw2.txt"), true); * 還是應該調用println()的方法纔可以 * 這個時候不僅僅自動刷新了,還實現了數據的換行。 * * println() * 其實等價于于: * bw.write(); * bw.newLine(); * bw.flush(); */ public class PrintWriterDemo2 { public static void main(String[] args) throws IOException { // 創建打印流對象 // PrintWriter pw = new PrintWriter("pw2.txt"); PrintWriter pw = new PrintWriter(new FileWriter("pw2.txt"), true); // write()是搞不定的,怎麼辦呢? // 我們就應該看看它的新方法 // pw.print(true); // pw.print(100); // pw.print("hello"); pw.println("hello"); pw.println(true); pw.println(100); pw.close(); } }
5:標準輸入輸出流(理解)
(1)System類下面有這樣的兩個字段
in 標準輸入流
out 標準輸出流
Demo:
import java.io.PrintStream; /* * 標準輸入輸出流 * System類中的兩個成員變量: * public static final InputStream in “標準”輸入流。 * public static final PrintStream out “標準”輸出流。 * * InputStream is = System.in; * PrintStream ps = System.out; */ public class SystemOutDemo { public static void main(String[] args) { // 有這裏的講解我們就知道了,這個輸出語句其本質是IO流操作,把數據輸出到控制檯。 System.out.println("helloworld"); // 獲取標準輸出流對象 PrintStream ps = System.out; ps.println("helloworld"); ps.println(); // ps.print();//這個方法不存在 // System.out.println(); // System.out.print(); } }
Demo2:
import java.io.BufferedWriter; import java.io.IOException; import java.io.OutputStreamWriter; /* * 轉換流的應用。 */ public class SystemOutDemo2 { public static void main(String[] args) throws IOException { // 獲取標準輸入流 // // PrintStream ps = System.out; // // OutputStream os = ps; // OutputStream os = System.out; // 多態 // // 我能不能按照剛纔使用標準輸入流的方式一樣把數據輸出到控制檯呢? // OutputStreamWriter osw = new OutputStreamWriter(os); // BufferedWriter bw = new BufferedWriter(osw); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter( System.out)); bw.write("hello"); bw.newLine(); // bw.flush(); bw.write("world"); bw.newLine(); // bw.flush(); bw.write("java"); bw.newLine(); bw.flush(); bw.close(); } }
(2)三種鍵盤錄入方式
A:main方法的args接收參數
B:System.in通過BufferedReader進行包裝
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
C:Scanner
Scanner sc = new Scanner(System.in);
Demo:
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; /* * System.in 標準輸入流。是從鍵盤獲取數據的 * * 鍵盤錄入數據: * A:main方法的args接收參數。 * java HelloWorld hello world java * B:Scanner(JDK5以後的) * Scanner sc = new Scanner(System.in); * String s = sc.nextLine(); * int x = sc.nextInt() * C:通過字符緩衝流包裝標準輸入流實現 * BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); */ public class SystemInDemo { public static void main(String[] args) throws IOException { // //獲取標準輸入流 // InputStream is = System.in; // //我要一次獲取一行行不行呢? // //行。 // //怎麼實現呢? // //要想實現,首先你得知道一次讀取一行數據的方法是哪個呢? // //readLine() // //而這個方法在哪個類中呢? // //BufferedReader // //所以,你這次應該創建BufferedReader的對象,但是底層還是的使用標準輸入流 // // BufferedReader br = new BufferedReader(is); // //按照我們的推想,現在應該可以了,但是卻報錯了 // //原因是:字符緩衝流只能針對字符流操作,而你現在是字節流,所以不能是用? // //那麼,我還就想使用了,請大家給我一個解決方案? // //把字節流轉換爲字符流,然後在通過字符緩衝流操作 // 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()); line = br.readLine(); int i = Integer.parseInt(line); System.out.println("你輸入的整數是:" + i); } }
(3)輸出語句的原理和如何使用字符流輸出數據
A:原理
System.out.println("helloworld");
PrintStream ps = System.out;
ps.println("helloworld");
B:把System.out用字符緩衝流包裝一下使用
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
6:隨機訪問流(理解)
(1)可以按照文件指針的位置寫數據和讀數據。
(2)案例:
A:寫數據
B:讀數據
C:獲取和改變文件指針的位置
Demo:
import java.io.IOException; import java.io.RandomAccessFile; /* * 隨機訪問流: * RandomAccessFile類不屬於流,是Object類的子類。 * 但它融合了InputStream和OutputStream的功能。 * 支持對文件的隨機訪問讀取和寫入。 * * public RandomAccessFile(String name,String mode):第一個參數是文件路徑,第二個參數是操作文件的模式。 * 模式有四種,我們最常用的一種叫"rw",這種方式表示我既可以寫數據,也可以讀取數據 */ public class RandomAccessFileDemo { public static void main(String[] args) throws IOException { // write(); read(); } private static void read() throws IOException { // 創建隨機訪問流對象 RandomAccessFile raf = new RandomAccessFile("raf.txt", "rw"); int i = raf.readInt(); System.out.println(i); // 該文件指針可以通過 getFilePointer方法讀取,並通過 seek 方法設置。 System.out.println("當前文件的指針位置是:" + raf.getFilePointer()); char ch = raf.readChar(); System.out.println(ch); System.out.println("當前文件的指針位置是:" + raf.getFilePointer()); String s = raf.readUTF(); System.out.println(s); System.out.println("當前文件的指針位置是:" + raf.getFilePointer()); // 我不想重頭開始了,我就要讀取a,怎麼辦呢? raf.seek(4); ch = raf.readChar(); System.out.println(ch); } private static void write() throws IOException { // 創建隨機訪問流對象 RandomAccessFile raf = new RandomAccessFile("raf.txt", "rw"); // 怎麼玩呢? raf.writeInt(100); raf.writeChar('a'); raf.writeUTF("中國"); raf.close(); } }
7:合併流(理解)
(1)把多個輸入流的數據寫到一個輸出流中。
(2)構造方法:
A:SequenceInputStream(InputStream s1, InputStream s2)
B:SequenceInputStream(Enumeration<? extends InputStream> e)
Demo:
import java.io.BufferedOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.SequenceInputStream; /* * 以前的操作: * a.txt -- b.txt * c.txt -- d.txt * * 現在想要: * a.txt+b.txt -- c.txt */ public class SequenceInputStreamDemo { public static void main(String[] args) throws IOException { // SequenceInputStream(InputStream s1, InputStream s2) // 需求:把ByteArrayStreamDemo.java和DataStreamDemo.java的內容複製到Copy.java中 InputStream s1 = new FileInputStream("ByteArrayStreamDemo.java"); InputStream s2 = new FileInputStream("DataStreamDemo.java"); SequenceInputStream sis = new SequenceInputStream(s1, s2); BufferedOutputStream bos = new BufferedOutputStream( new FileOutputStream("Copy.java")); // 如何寫讀寫呢,其實很簡單,你就按照以前怎麼讀寫,現在還是怎麼讀寫 byte[] bys = new byte[1024]; int len = 0; while ((len = sis.read(bys)) != -1) { bos.write(bys, 0, len); } bos.close(); sis.close(); } }
Demo2:
import java.io.BufferedOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.SequenceInputStream; import java.util.Enumeration; import java.util.Vector; /* * 以前的操作: * a.txt -- b.txt * c.txt -- d.txt * e.txt -- f.txt * * 現在想要: * a.txt+b.txt+c.txt -- d.txt */ public class SequenceInputStreamDemo2 { public static void main(String[] args) throws IOException { // 需求:把下面的三個文件的內容複製到Copy.java中 // ByteArrayStreamDemo.java,CopyFileDemo.java,DataStreamDemo.java // SequenceInputStream(Enumeration e) // 通過簡單的回顧我們知道了Enumeration是Vector中的一個方法的返回值類型。 // Enumeration<E> elements() Vector<InputStream> v = new Vector<InputStream>(); InputStream s1 = new FileInputStream("ByteArrayStreamDemo.java"); InputStream s2 = new FileInputStream("CopyFileDemo.java"); InputStream s3 = new FileInputStream("DataStreamDemo.java"); v.add(s1); v.add(s2); v.add(s3); Enumeration<InputStream> en = v.elements(); SequenceInputStream sis = new SequenceInputStream(en); BufferedOutputStream bos = new BufferedOutputStream( new FileOutputStream("Copy.java")); // 如何寫讀寫呢,其實很簡單,你就按照以前怎麼讀寫,現在還是怎麼讀寫 byte[] bys = new byte[1024]; int len = 0; while ((len = sis.read(bys)) != -1) { bos.write(bys, 0, len); } bos.close(); sis.close(); } }
8:序列化流(理解)
(1)可以把對象寫入文本文件或者在網絡中傳輸
(2)如何實現序列化呢?
讓被序列化的對象所屬類實現序列化接口。
該接口是一個標記接口。沒有功能需要實現。
(3)注意問題:
把數據寫到文件後,在去修改類會產生一個問題。
如何解決該問題呢?
在類文件中,給出一個固定的序列化id值。
而且,這樣也可以解決黃色警告線問題
(4)面試題:
什麼時候序列化?
如何實現序列化?
什麼是反序列化?
Person類:
import java.io.Serializable; /* * NotSerializableException:未序列化異常 * * 類通過實現 java.io.Serializable 接口以啓用其序列化功能。未實現此接口的類將無法使其任何狀態序列化或反序列化。 * 該接口居然沒有任何方法,類似於這種沒有方法的接口被稱爲標記接口。 * * java.io.InvalidClassException: * cn.itcast_07.Person; local class incompatible: * stream classdesc serialVersionUID = -2071565876962058344, * local class serialVersionUID = -8345153069362641443 * * 爲什麼會有問題呢? * Person類實現了序列化接口,那麼它本身也應該有一個標記值。 * 這個標記值假設是100。 * 開始的時候: * Person.class -- id=100 * wirte數據: oos.txt -- id=100 * read數據: oos.txt -- id=100 * * 現在: * Person.class -- id=200 * wirte數據: oos.txt -- id=100 * read數據: oos.txt -- id=100 * 我們在實際開發中,可能還需要使用以前寫過的數據,不能重新寫入。怎麼辦呢? * 回想一下原因是因爲它們的id值不匹配。 * 每次修改java文件的內容的時候,class文件的id值都會發生改變。 * 而讀取文件的時候,會和class文件中的id值進行匹配。所以,就會出問題。 * 但是呢,如果我有辦法,讓這個id值在java文件中是一個固定的值,這樣,你修改文件的時候,這個id值還會發生改變嗎? * 不會。現在的關鍵是我如何能夠知道這個id值如何表示的呢? * 不用擔心,你不用記住,也沒關係,點擊鼠標即可。 * 你難道沒有看到黃色警告線嗎? * * 我們要知道的是: * 看到類實現了序列化接口的時候,要想解決黃色警告線問題,就可以自動產生一個序列化id值。 * 而且產生這個值以後,我們對類進行任何改動,它讀取以前的數據是沒有問題的。 * * 注意: * 我一個類中可能有很多的成員變量,有些我不想進行序列化。請問該怎麼辦呢? * 使用transient關鍵字聲明不需要序列化的成員變量 */ public class Person implements Serializable { private static final long serialVersionUID = -2071565876962058344L; private String name; // private int age; private transient int age; // int age; public Person() { super(); } public Person(String name, int age) { super(); 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 "Person [name=" + name + ", age=" + age + "]"; } }
Demo:
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; /* * 序列化流:把對象按照流一樣的方式存入文本文件或者在網絡中傳輸。對象 -- 流數據(ObjectOutputStream) * 反序列化流:把文本文件中的流對象數據或者網絡中的流對象數據還原成對象。流數據 -- 對象(ObjectInputStream) */ 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( "oos.txt")); // 還原對象 Object obj = ois.readObject(); // 釋放資源 ois.close(); // 輸出對象 System.out.println(obj); } private static void write() throws IOException { // 創建序列化流對象 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream( "oos.txt")); // 創建對象 Person p = new Person("林青霞", 27); // public final void writeObject(Object obj) oos.writeObject(p); // 釋放資源 oos.close(); } }
9:Properties(理解)
(1)是一個集合類,Hashtable的子類
(2)特有功能
A:public Object setProperty(String key,String value)
B:public String getProperty(String key)
C:public Set<String> stringPropertyNames()
(3)和IO流結合的方法
把鍵值對形式的文本文件內容加載到集合中
public void load(Reader reader)
public void load(InputStream inStream)
把集合中的數據存儲到文本文件中
public void store(Writer writer,String comments)
public void store(OutputStream out,String comments)
(4)案例:
A:根據給定的文件判斷是否有鍵爲"lisi"的,如果有就修改其值爲100
B:寫一個程序實現控制猜數字小遊戲程序不能玩超過5次
10:NIO(瞭解)
(1)JDK4出現的NIO,對以前的IO操作進行了優化,提供了效率。但是大部分我們看到的還是以前的IO
(2)JDK7的NIO的使用
Path:路徑
Paths:通過靜態方法返回一個路徑
Files:提供了常見的功能
複製文本文件
把集合中的數據寫到文本文件