不知道是對原理理解的不夠還是表達能力太差,心中有話,總不知該如何組織,就想對象序列化,對于他的用法感覺已經很清楚了,手放在鍵盤上仍舊不知從何寫起,必須對照書本來闡述其原理。
記得今年5月份,有一次面試,面試完了是上機測試,題目是把一個對象數組寫入文本,再進行讀取,雖然給我提供了API,但仍無從下手,只好對面試主管笑了笑,我放棄。如果現在讓我寫,即便沒有API也能輕松搞頂了(必須用eclipse,用記事本完全不行)。還有就是前段時間,我公司美工的機子中毒了,在每個JSP文件的最后加了一行代碼,導致頁面加載速度非常慢,項目經理讓我寫一個小程序,把她機子上這些多余代碼清除掉,當然了第一步就是遞歸讀取每個磁盤下的文件內容,然后將目標代碼行刪除掉,當時在網上搜索輸入輸出的例子,折騰了一晚上才完成讀取的功能,而且對于其中的過程很模糊,只是東拼西湊的功能實現了,昨晚再回頭看我寫的那幾行代碼,思路非常清晰。
看書呀,很重要,必須看書。
1.一個可以讀取字節序列的對象稱為輸入流(input stream);一個可以寫入字節序列的對象被稱為輸出流(output
stream)。入或出是相對于內存而言的,凡是對字節進行讀寫的流都以stream為名字后綴?以Reader、Writer為
后綴的名字都是以字符為單位來處理的?
2.四個抽象類inputStream、outputStream、Reader和Writer構成了流類的基礎,不用創建這些類型的對象,而是
其他方法返回這些對象。這些基礎類只能讀取單個字節或字節數組,而功能更強大更適合開發者使用的是
他們多變的子類。流類家族非常龐大,方法更是多變,在這里不需要把每個類的每個功能列出來,只記錄
一些典型的使用,明白其原理就夠了。
3.流類設計策略:分為兩種流類,一種是從文件或其他源接受字節。另一種流可以將字節組合成更加有用的
數據類型。JAVA程序員采用將一個已經存在的流傳遞給另一個流的構造器的方法,將這兩種流結合起來,
結合后的流被稱為過濾流。舉例:
DateInputStream din = new DateInputStream(
new BufferedInputStream(
new FileInputStream("employee.dat")));
首先是從文件讀取數據,用FileInputStream構造輸入流;為了達到數據緩沖的效果,還要用
BufferedInputStream包裝;最后要輸出基本數據類型,而不是輸出字節流,還必須用DateInputStream來包裝一
層。這就是流最常用的包裝方式,這樣做很有必要,必須將流結構連續的分層,直到能夠使用的所需要的
功能為止。這樣雖然很麻煩,但是將流進行過濾分層,進行混合與匹配,從而構造出真正使用的流序列,
從而帶來了很大的靈活性。
4.書中提到的流類:
讀寫字節:InputStream、outputStream;InputStreamReader、OutputStreamReader;
讀寫壓縮文件:ZipInputStream、ZipOutputStream;
讀寫磁盤文件數據:FileInputStream、FileOutputStream;FileReader、FileWriter;
讀寫java基本數據類型:DataInputStream、DateOutputStream;DateInput、DateOutput;
讀寫是進行數據緩沖:BufferedInputStream、BufferedOutputStream;
具有預查看功能的流:PushbackInputStream、PushbackOutputStream;
隨即讀寫文件:RandonAccessFile;
友好格式文本輸出:PrintWriter;
對象流:ObjectInputStream、ObjectOutputStream;
5. 流類處理的是文件或其他源中的內容,而File類關注的是文件在磁盤上的存儲。
File file = new File("test.txt");若沒有提供路徑,則會使用當前目錄。所謂當前目錄,就是目前執行虛擬機處
理程序的當前目錄。是程序的當前目錄,如workpace/zmdsl/dist 。它只是根據提供的路徑或文件名創建了
一個File對象,并沒有在磁盤上創建文件。
6. 一個讀取磁盤目錄文件的例子
import java.io.*;
public class ReadFile {
/**
* 查找該目錄及其子目錄下的所有文件。
*/
public static boolean findFile(String filepath) throws FileNotFoundException, IOException {
try {
File file = new File(filepath);//獲得File對象
if (!file.isDirectory()) {//若此路徑對應的不是一個目錄,而是一個文件,則進行該文件的讀取
readContent(file.getPath());
} else if (file.isDirectory()) {//此路徑為目錄
String[] filelist = file.list();//返回該目錄下所有文件名字及和子目錄名字,只包含當前目錄下的子目錄
for (int i = 0; i < filelist.length; i++) {
File readfile = new File(filepath + "\\" + filelist[i]);
if (!readfile.isDirectory()) {//是文件,進行read
readContent(readfile.getPath());
} else if (readfile.isDirectory()) {//仍然是目錄,再遞歸調用findFile,進一層檢查
findFile(filepath + "\\" + filelist[i]);
}
}
}
} catch (FileNotFoundException e) {
System.out.println("readfile() Exception:" + e.getMessage());
}
return true;
}
//讀取文件內容
public static void readContent(String path) throws IOException { // 此處的path包括文件名
String str = "";
StringBuffer content = new StringBuffer();
File file = new File(path);
//FileInputStream讀取的是字節,而Reader(BufferedReader)處理的是字符,所以說InputStreamReader是連接
‘Stream’和‘Reader’的橋梁
InputStreamReader is = new InputStreamReader(new FileInputStream(file),"GB2312");
BufferedReader in = new BufferedReader(is);//進行緩沖,緩沖滿后再進行讀取
while ((str = in.readLine()) != null) {//一次讀一行內容
content = content.append(str);
}
in.close();
}

public static void writeFile(String path, String content) {

try {
FileWriter outFile = new FileWriter(path.replace("\\", "/"));
BufferedWriter bufferOut = new BufferedWriter(outFile);//包裝一層
bufferOut.write(content);//會刪除文件原來的內容
bufferOut.newLine();
bufferOut.flush();
bufferOut.close();

} catch (IOException e) {
e.printStackTrace();
}
}

public static void main(String[] args) {
String path = "E:\\workpace";// 讀取此目錄及子目錄下的所有文件

try {
findFile(path);

} catch (FileNotFoundException e) {
e.printStackTrace();

} catch (IOException e) {
e.printStackTrace();
}
}

}
7. 對象序列
對象序列化分兩部分:序列化(寫)和反序列化(讀)。對象的序列化就是將對象數據分解成字節流,以便存儲在磁盤文件或在網絡上傳輸。它實質上還是一個寫的過程。反序列化就是讀取字節流重構對象。
序列化對象主要用到兩個類:ObjectOutputStream和ObjectInputStream,這兩個類分別實現了DateOutput和DateInput接口,writerObject用于將指定的對象序列化;readObject則是從inputStream中重構對象。對象序列化可以實現對象的硬copy,如果對象中還包含對象域,則回遞歸序列化這些對象。每個ObjectOutputStream對象維護序列化后的對象引用表,防止對同一個對象發送多個拷貝。

/** *//**
* 對象序列化測試
* @throws IOException
* @throws FileNotFoundException
* @throws ClassNotFoundException
*/

public static void objectSeri() throws FileNotFoundException, IOException, ClassNotFoundException{
User[] users = new User[3];//構造一個對象數組的object,用于序列化和反序列化
users[0] = new User(24,"yangay");
users[1] = new User(23,"shiw");
users[2] = new User(18,"zhumh");
FileOutputStream fout = new FileOutputStream("ioText.txt");
ObjectOutputStream outs = new ObjectOutputStream(fout);
outs.writeObject(users);//以字節流形式寫入指定文件
outs.close();//關閉輸出流
FileInputStream fin = new FileInputStream("ioText.txt");
ObjectInputStream ins = new ObjectInputStream(fin);
User[] newUsers = (User[])ins.readObject();//恢復對象狀態
ins.close();

for(int i = 0;i < newUsers.length;i++){//打印
System.out.print(newUsers[i].getUserName() + " ");
System.out.println(newUsers[i].getAge());
}
}
8. 單個流類的學習
1)PrintWriter類
向文本輸出流打印對象的格式化表示形式。

public static void printWriter() throws FileNotFoundException{
String dir = "E:\\workspace\\test\\ioTest.txt";
FileOutputStream out = new FileOutputStream(dir);
PrintWriter pw = new PrintWriter(out,false);
pw.write("yang");
pw.write("aiyou");

/**
* CharSequence與String有什么區別?Writer及其子類都有write(int i)和write(String s)方法,
* write(2)打印出2,write("2")也是打印出2,為什么還要加一個write(int i)方法呢?
* 另外print(String s)、write(String s)、write(CharSquence cs)、append(String s)也看不出有什么區別?都是先刪掉原來內容再
*寫入指定的字符(串)
*/
pw.flush();//不要忘記
}
posted on 2007-08-17 01:06
楊愛友 閱讀(1821)
評論(2) 編輯 收藏 所屬分類:
java相關技術