不知道是对原理理解的不够还是表达能力太差,心中有话,总不知该如何组织,就想对象序列化,对于他的用法感觉已经很清楚了,手放在键盘上仍旧不知从何写起,必须对照书本来阐述其原理。
记得今年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
杨爱友 阅读(1819)
评论(2) 编辑 收藏 所属分类:
java相关技术