欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

java之 21天 随机读取文件,管道流,序列化

程序员文章站 2022-04-03 19:46:04
...
对象持久化 ,序列化, 串行化

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

/**
 * 对象持久化 ,序列化, 串行化
 * 直接操作对象的流 
 * ObjectOutputStream
 * ObjectInputStream
 *
 * Serializable:没有方法的接口 :通常 称为 标记接口 , 序列化只能 序列化 堆里面的对象属性
 * 
 *  注意:
 *  1)静态成员:  不能被序列化,因为 静态在方法区里面 ,不再 堆里面, 
 *  2)transient: 修饰静态成员, 使它不被序列化 
 * 
 */
public class ObjectStreamDemo {

	public static void main(String[] args) throws Exception {
		//method();
		//readObj();
		writeObj();
		readObj();  //斯蒂芬::59::cn  发现  country 属性没有被序列化进去
	}
	public static void writeObj() throws IOException{
		ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("E:\\person.object"));
		oos.writeObject(new Person("斯蒂芬",59,"kr"));
		oos.close();
	}
	//序列化
	public static void method() throws IOException{
		ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("E:\\person.object"));
		oos.writeObject(new Person("lisi",39));
		oos.close();
	}
	
	//反序列化
	public static void readObj() throws IOException, ClassNotFoundException{
		ObjectInputStream ois= new ObjectInputStream(new FileInputStream("E:\\person.object"));
		Person p=(Person)ois.readObject();
		System.out.println(p);
		ois.close();
	}

}

//要序列化的类  都必须 实现这个接口 
class Person implements Serializable{
	//必须 生成一个 UID 否则会有序列化后,再反序列 就会有问题.
	private static final long serialVersionUID = 7457608434653264123L;
	
	private String name;  //
	
	transient private int age;  //如果想要非静态成员也不序列化 就使用个 transient 修饰, 但是保证 堆中有
	
	static String country="cn";   //静态 成员不能被序列化 
	Person(String name,int age){
		this.name=name;
		this.age=age;
	}
	Person(String name,int age,String country){
		this.name=name;
		this.age=age;
		this.country=country;
	}
	
	
	public String toString(){
		return name+"::"+age+"::"+country;
	}
}



管道流

import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;

/**
 * 管道流
 * PipedInputStream  管道读取流
 * PipedOutputStream  管道写入流
 *  
 * 联合两者的关系
 * 1)通过构造函数 :PipedInputStream(PipedOutputStream src) 
 * 2)使用方法:  void connect(PipedOutputStream src)  进行连接
 * 
 * 
 * 总结 ::
 * 集合中涉及到 IO流的 是properties
 * IO中涉及到多线程的就是  管道流 
 *  
 */
public class PipedStreamDemo {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		try {
			PipedInputStream pin=new PipedInputStream();
			PipedOutputStream pon=new PipedOutputStream();
			pin.connect(pon);
			
			ReadPiped rp=new ReadPiped(pin);
			WritePiped wp=new WritePiped(pon);
			new Thread(rp).start();
			new Thread(wp).start();
			
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}

//读取管道流
class ReadPiped implements Runnable{
	private PipedInputStream in;
	ReadPiped(PipedInputStream in){
		this.in=in;
	}
	
	public void run(){
		try {
			System.out.println("读取前没有数据就阻塞....");
			byte[] buf=new byte[1024];
			int len=in.read(buf);
			System.out.println("读到数据阻塞结束");
			
			String s=new String(buf,0,len);
			System.err.println(s);
			in.close();
		} catch (IOException e) {
			throw new RuntimeException("管道读取流失败!");
		}
	}
}

//写入管道流
class WritePiped implements Runnable{
	private PipedOutputStream out;
	WritePiped(PipedOutputStream out){
		this.out=out;
	}
	public void run(){
		try{
			System.out.println("6秒后开始写入数据...");
			Thread.sleep(6000l);
			out.write("Piped lai la".getBytes());
			out.close();
		}catch(IOException e){
			e.printStackTrace();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
}



随机访问文件的类

import java.io.IOException;
import java.io.RandomAccessFile;

/**
 * RandomAccessFile: 随机访问文件的类
 * 特点:
 *   1)该类 不算IO体系中的子类 ,而是 直接继承 Object 
 *   2)但,是IO包中的成员
 *   3)同时具备 读和写的功能.
 *   4)内部封装了一个数组,而且通过指针对数组的元素进行操作.
 *   5)可以通过 getFilePointer获取指针的位置
 *   6)可以通过seek改变指针的位置
 *   
 *   
 *   seek(long pos) :  跳到指定的索引位置上
 *   skipBytes(int n): 跳过指定的 字节数
 *   
 *   其实能够完成 读写的原因,就是内部封装了字节输入流和输出流.
 *   
 *   通过构造函数 可以看出 ,该类只能操作 文件.mod 只能 4中值
 *   r:读
 *   rw:读写
 *   而且该对象构造函数要操作的文件不存在,会自动创建, 如果存在会覆盖 .
 *   
 *   如果模式为r:只读,不会创建文件,会去读取一个已经存在的文件,如果文件不存在,则会出现异常.
 *   如果模式为rw: 操作的文件不存在,会自动创建,如果存在 则不会覆盖文件,但是会替换对应位置上的文件
 *   
 *   多线程 下载和写入
 *   可以实现,文件的分段写入 ,和下载
 */
public class RandomAccessFileDemo {
	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		System.out.println("不存在就创建,然后写,存在就会覆盖,");
		 //writeFile();
		//System.out.println(Integer.toBinaryString(258));  // 100000010--00000010(write 只将最低8位 写入流中)
		
		System.out.println("跳过指定的字节后再读");
		//readFile();
		System.out.println("跳过指定的字节后再写");
		writeFile_2();
	}
	public static void writeFile_2() throws IOException{
		RandomAccessFile raf=new RandomAccessFile("E:\\ran.txt","rw");
		
		//第三个 不知道 写什么 但是第四个知道写什么
		//raf.seek(8*3);
		raf.write("周期".getBytes());
		raf.writeInt(444);
		
		raf.close();
		
	}
	
	
	public static void readFile() throws IOException{
		RandomAccessFile raf=new RandomAccessFile("E:\\ran.txt","r");
		//raf.write("haha".getBytes());  //java.io.IOException: 拒绝访问。
		
		byte[] buf=new byte[4];
		
		//调整指针,  如果是有序 就这样就可以了
		//raf.seek(8*1); //跳到指定的索引,  取到的就是 王武了,否则 从头开始取  李四
		raf.skipBytes(8); //跳过指定的字节数 只能 往下跳, 不会回跳
		
		raf.read(buf);
		String name=new String(buf);
		int age=raf.readInt();  //自动读取 4个字节转换成 int
		System.out.println("name:"+name+"----age:"+age);
		
		
		raf.close();
		
	}
	public static void writeFile() throws IOException{
		
		RandomAccessFile raf=new RandomAccessFile("E:\\ran.txt","rw");
		raf.write("GGG".getBytes());
		//raf.write(97);  //存入后 变成 a 因为 是 97 对应的码表是 a
		raf.writeInt(97);  //存入后 变成 a 因为 是 97 对应的码表是 a
		//raf.writeInt(258); // 前面有三空格 ,3个字节是空的 写出了4个字节 
		raf.write("KKK".getBytes());
		raf.writeInt(99); // 
		raf.close();
	}

}