Thinking in java 琐碎知识点之 I/O流 、对象序列化(七)

2014-11-23 21:43:47 · 作者: · 浏览: 31
} catch (FileNotFoundException e) { e.printStackTrace(); }finally{ if(p!=null){ p.close(); } } } }
Scanner和IO流接(BufferedReader)受键盘输入的比较(BufferedReader输入都被当成String对象,BufferedReader不能读取基本类型输入项)
例程:InputTest.java
public class InputTest {
	public static void main(String[] args) throws IOException {
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
//		int len=br.read();
//		System.out.println((char)len);
//		String len2=br.readLine();
//		System.out.println(len2);
		
//		Scanner sn=new Scanner(System.in);
//		System.out.println(sn.nextLine());
//		System.out.println(sn.nextInt());
		String input = "1 fish 3 fish red fish blue fish";
	     Scanner s = new Scanner(input).useDelimiter("\\s*fish\\s*");//自定义分隔符为fish
	     System.out.println(s.nextInt());
	     System.out.println(s.nextInt());
	     System.out.println(s.next());
	     System.out.println(s.next());
	     
	     input="324 42314 fish zpc";
	     s=new Scanner(input);
	     System.out.println(s.nextInt());
	     System.out.println(s.nextInt());
	     System.out.println(s.next());
	    // System.out.println(s.nextByte(0));
	     s.close(); 
	}
}
//Scanner也可以指定读取某个文件
public class TestScanner {
	public  static void main(String[] args){
		Scanner sn=null;
		//sn.useDelimiter("\n");//如果增加这一行将只把回车符作为分隔符
		try {
			sn=new Scanner(new File("F:\\Thinking.txt"));
			while(sn.hasNext()){
				System.out.println(sn.nextLine());
			}
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

11、RandomAccessFile对象
package Serialize;
/*
 * 功能:读一个文件,复制自身追加到此文件,操作完成后文件应该变成双倍大小
 * RandomAccessFile对象不能向文件的指定位置插入内容,这会覆盖原来的内容
 * 如果要在指定位置插入内容,程序需要先把插入点后面的内容都入缓冲区,
 * 等把需要插入的数据写入文件后,在将缓冲区的内容追加到文件后面,详见InsertContent.java
 */
import java.io.*;


public class RandomAccessFileTest {
	public static void main(String[] args) {
		RandomAccessFile raf = null;
		// 以只读方式打开一个RandomAccessFile对象
		try {
			raf = new RandomAccessFile("F:\\掀起你的盖头来.mp3", "rw");
			System.out.println("RandomAccessFile对象的文件指针初始位置:"
					+ raf.getFilePointer());
			System.out.println("raf.length():"+raf.length());
			//读文件
			byte[] b = new byte[1024];
			int hasRead = 0;
			int readTotal=0;
			long FileTotalLen= raf.length();
			while (((hasRead = raf.read(b)) != -1)&&readTotal<=FileTotalLen) {
				readTotal+=hasRead;
				//System.out.println(new String(b, 0, hasRead));
				raf.seek(raf.length());
				raf.write(b);
				raf.seek(readTotal);
			}
			
			System.out.println("raf.length():"+raf.length());
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (raf != null) {
					raf.close();
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}


//InsertContent.java
import java.io.*;
/*
 * 功能:向一个文件的指定位置插入内容,而不覆盖原有的内容
 */
public class InsertContent {
	public static void main(String[] args) {
		insert("F:\\thinking.txt",200,"===========我是鸟鹏!==========");
	}
	public static void insert(String fileName, long pos, String content) {
		InputStream is = null;
		OutputStream os = null;
		RandomAccessFile raf = null;
		// 创建一个临时文件来保存插入点后面的数据
		try {
			File temp = File.createTempFile("tem", null);
			temp.deleteOnExit();
			raf = new RandomAccessFile(fileName, "rw");
			os=new FileOutputStream(temp);
			byte[] buf=new byte[1024];
			int hasRead=0;
			raf.seek(pos);
			while((hasRead=raf.read(buf))!=-1){
				os.write(buf,0,hasRead);
			}
			raf.seek(pos);
			raf.write(content.getBytes());
			
			//下面的代码实现插入数据的功能
			is=new FileInputStream(temp);
			while((hasRead=is.read(buf))!=-1){
				raf.write(buf,0,hasRead);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			try {
				if(raf!=null)
				raf.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

12、对象序列化
在Java中如果需要将某个对象保存到磁盘或者通过网络传输,那么这个类应该实现Serializable标记接口或者Externalizable接口之一
序列化的步骤:
a、创建一个ObjectOutputstream处理流(必须建立在其它结点的基础上)对象
b、调用ObjectOutputstream对象的writeObject方法输出可序列化对象
从二进制流中恢复Java对象的反序列化步骤(按照实际写入的顺序读取):
a、创建一个ObjectInputStream处理流(必须建立在其它结点的基础上)对象
b、调用ObjectInputstream对象的readObject方法输出可序列化对象(该方法返回的是Object类型的Java对象)
(反序列化恢复Java对象时必须要提供java对象所属类的class文件)
注:如果一个可序列化对象有多个父类,则该父类要么是可序列化的,要么有无参的构造器,因为反序列化机制要恢复其关联的父类实例
而恢复这些父类实例有两种方式:使用序列化机制、使用父类无参的构造器
采用Java序列化机制时,只有当第一次调用writeObject输出某个对象时才会将该对象转换成字节序列写到ObjectOutputStream
在后面程序中如果该对象的属性发生了改变,即再次调用writeObject方法输出该对象时,改变后的属性不会被输出
如果父类没有实现Serializable接口,则其必须有默认的构造函数(即没有参数的构造函数)
但是若把父类标记为可以串行化,则在反串行化的时候,其默认构造函数不会被调用。
这是因为Java 对串行化的对象进行反串行化的时候,直接从流里获取其对象数据来生成一个对象实例,而不是通过其构造函数来完成。

例程:
import java.io.Serializable;
public class Person implements Serializable {
	private String name ;
	private int age;
	p