对象流,管道流和随机访问文件流

------- android培训java培训、期待与您交流! ----------


1 对象的存储ObjectInputStream(InputStream())和ObjectOutputStream(OutputStream())


/*例子1:对象的存储ObjectInputStream和ObjectOutputStream对象的存储,这两个类是要一起用的,用它写的就要用它去读
ObjectInputStream(InputStream());
ObjectOutputStream(OutputStream());
要实现Serializable的原因:

每个类都有一个标记,对象从这个类产生之后,对象的标记和类的标记是一样的,
可是当类里的变量或者方法改变之后,产生对象的类的标记就发生变化了,因为标记是根据类的成员而计算出来的
于是对象的标记跟类的标记就不同了,当流去读存储在文件里的对象时,对象要通过类才能编译,但是以前产生的对象跟现在的类标记不一样了,对象读不出来

被静态修饰了的成员,不会保存在文件上,因为你保存的对象是在堆内存的,而静态的成员或方法都是在方法区里的


存储对象的时候,某些文件不想写在文件上,可以用transient修饰,经过修饰的变量将不会随对象存储
*/
import java.io.*;
import java.util.*;


class Person implements Serializable//要实现Serializable接口,这个接口里面没有抽象方法, 不用复写操作
{
	private String name;
	private int age;
	//transient private int age; 这个age不会随对象存储在文件上
	//static private int age;  这个age不会随对象存储在文件上
	Person(String name,int age)
	{
		this.name=name;
		this.age=age;
	}


	public String toString()
	{
		return name+":"+age;
	}
}
class ObjectDemo
{
	public static void main(String[] args)throws Exception
	{
		writePerson();
		readPerson();
	}


	public static void readPerson()throws Exception
	{
		ObjectInputStream obi=new ObjectInputStream(new FileInputStream("person.txt"));

		Person p1=(Person)obi.readObject();
		Person p2=(Person)obi.readObject();
		Person p3=(Person)obi.readObject();
		sop(p1);
		sop(p2);
		sop(p3);
	}
	
	public static void writePerson()throws IOException
	{
		ObjectOutputStream obo=new ObjectOutputStream(new FileOutputStream("person.txt"));
		obo.writeObject(new Person("zhangsan01",30));
		obo.writeObject(new Person("zhangsan02",31));
		obo.writeObject(new Person("zhangsan03",32));
		obo.close();
	}


	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
	
}


2 管道流:PipedInputStream和PipedOutputStream
connect()方法
in.connect(out);//把两个流关联起来

read()是阻塞方法,当没有数据可读时,会等待,知道写入数据,才会执行

/*
这是管道流写入和读取的例子
*/
import java.io.*;
class Read implements Runnable
{
	private PipedInputStream in;
	Read(PipedInputStream in)
	{
		this.in=in;
	}

	public void run()
	{
	try
	{
		byte[] bt=new byte[1024];
		System.out.println("没有数据可读,阻塞");
		int len=in.read(bt);
		System.out.println("有数据可读,解除阻塞");
		String s=new String(bt,0,len);
		System.out.println(s);

		in.close();
	}

	catch(Exception e)
	{
		throw new RuntimeException("管道流读取失败");
	}
	}
}


class Write implements Runnable
{
	private PipedOutputStream out;
	Write(PipedOutputStream out)
	{
	this.out=out;
	}


	public void run()
	{
	try
	{
		Thread.sleep(6000);
		System.out.println("正在写入数据");
		out.write("我是输出流,大爷我来啦".getBytes());
		out.close();
	}

	catch(Exception e)
	{
		throw new RuntimeException("管道流写入失败");
	}
	}
}


class PipedDemo
{
	public static void main(String[] args)throws Exception
	{
		PipedInputStream in=new PipedInputStream();
		PipedOutputStream out=new PipedOutputStream();
		in.connect(out);//把两个流关联起来
	
		Read r=new Read(in);
		Write w=new Write(out);

		Thread t1=new Thread(r);
		Thread t2=new Thread(w);
		t1.start();
		t2.start();
	}
}


3 RandomAccessFile随机访问文件的功能演示:
这个类既能读又能写
它是直接继承于Object的,不是IO流的子类,但是RandomAccessFile类是属于io包的,因为它有读写功能,其实它里面封装了流对象,原理是里面封装了一个数组,数组里存的都是字节
一个汉字等于一个字符,一个字符等于两个字节,一个int类型的数字等于4个字节

3.1)主要功能:
能够改变指针,来读取或者写入字节:
seek(int x);//可以随意改变数组的指针大小
skip(int x);//也是改变数组的指针来读写,但是指针只能越来越大

3.2)构造方法:
RandomAccessFile raf=new RandomAccessFile("1.txt","mode");
 1传入要读写的文本文件
 2mode模式:r 只能写  rw既能读又能写     rws   rwd


如果模式是r,当传入的文件不存在,程序会报异常,
如果模式是rw,当传入的文件存在,写入数据将不会覆盖整个文件,而只是覆盖写入数据对应的指针位置的数据,不像以前那些,如果指定文件存在了就把整个文件完全覆盖掉,当指定的文件不存在,会新建一个文件

/*
例子:随机访问文件的例子
*/
import java.io.*;
class RandomAccessFileDemo
{
	public static void main(String[] args)throws Exception
	{
		RandomAccessFile raf=new RandomAccessFile("raf.txt","rw");
		raf.write("张三".getBytes());
		raf.writeInt(97);

		byte[] buf=new byte[4];
		raf.read(buf);

		String s=new String(buf);
		System.out.println(s);

	}
	
}

4 操作基本数据类型的流对象 DataInputStream()和DataOutputStream();

4.1)功能
writeInt()
writeBoolean()
writeDouble()
writeUTF()

/*
例子:操作基本数据类型的流对象 DataInputStream()和DataOutputStream()的例子
*/
import java.io.*;
class DataStreamDemo
{	
	public static void main(String[ ] args)
	{
	outD();
	intD();
	}
	public static void intD()throws Exception
	{
		DataInputStream das=new DataInputStream(new FileInputStream("haha.txt"));

		sop(das.readInt());
		sop(das.readBoolean());
		sop(das.readDouble());
	}
	public static void outD()throws Exception
	{
		DataOutputStream dao=new DataOutputStream(new FileOutputStream("haha.txt"));

		dao.writeInt(13);//int类型是4个字节的所以用writeInt(int x);
		dao.writeBoolean(true);//Boolean是一个字节,用writBoolean;
		dao.writeDouble(111.222);//Double类型是8个字节,用writeDouble;

		/*
		还有这个功能
		dao.writeUTF("您好");//这是采用新的utf-8编译的
		*/
	}


	public static void sop(Object obj)
	{
	System.out.println(obj);
	}
}


现在源和目的都是内存

把数组跟流结合起来了
ByteArrayInputStream(byte[])//源传入一个字节数组

ByteArrayOutputStream();//目的,里面自动封装一个可变长度的字节数组,把传进来的字节数组,存到字节数组里面

把数组变成字符串打印数组里的东西:

Arrays.toString(byt[] buf);

操作字符数组
CharArrayReader(char[])//传入一个字符数组
CharArrayReader()


操作字符串
StringReader(String s)
StringWriter()

/*
例子:数组跟流结合的例子ByteArrayInputStream(byte[])和ByteArrayOutputStream()
*/
import java.io.*;
class ByteDemo
{
	public static void main(String[] args)throws IOException
	{
		ByteArrayInputStream bis=new ByteArrayInputStream("abcde".getBytes());
		ByteArrayOutputStream bos=new ByteArrayOutputStream();
		int a=0;
		while((a=bis.read())!=-1)
		{
			bos.write(a);
		}
		System.out.println(bos.size());//打印数组输出流中的size方法可以把存储在内存里
的数组大小打印出来
		System.out.println(bos); //直接打印数组输出流可以把存储在内存里的字节打印出来
	}
}

/*
例子:有个5个学生,每个学生有3门课的成绩
从键盘输入以上数据,包括姓名和三门课成绩
输入格式:zhangsan,20,40,60
并把学生的信息和计算出的总分数高低顺序存放在磁盘文件

*/

import java.io.*;
import java.util.*;
//定义一个学生类
class Student implements Comparable<Student>
{
		private String name; //姓名
		private double ma,cn,en; //三门课程的分数
		private double sum;  //总分
	Student(String name,double ma,double cn,double en) //构造函数初始化
	{
		this.name=name;
		this.ma=ma;
		this.en=en;
		this.cn=cn;
		sum=ma+cn+en; //总分
	}
	public void setName(String s) //函数修改学生姓名
	{
		 this.name=name;
	}


	public String getName() //获取学生姓名
	{
		return this.name;
	}


	public double getSum() //获取总分
	{
		return this.sum;
	}
	public int compareTo(Student s) //覆盖compareTo()方法
	{
		int num=new Double(this.sum).compareTo(new Double(s.sum));
		if(num==0)
		return this.name.compareTo(s.name);
		return num;
	}
	public int hashCode() //覆盖hashCode()方法
	{
		return this.name.hashCode()+(int)sum*31;
	}


	public boolean equals(Object obj)//覆盖equals方法
	{
		if(!(obj instanceof Student))
		throw new ClassCastException("类型不匹配");
	
		Student stu=(Student)obj;
		return this.name.equals(stu.name)&&this.sum==stu.sum;
	}


	public String toString()//覆盖toString方法
	{
		return "Student["+name+", "+ma+", "+cn+", "+en+"]";
	}
}


class StudentTool
{


	public static Set<Student> getStudents()//这个得到的是自然排序的集合
	{
	return getStudents(null);
	}


	//这个是有比较器的集合
	public static Set<Student> getStudents(Comparator<Student> cmp)
	{
	Set<Student> stus=null;
	if(cmp==null)
	stus=new TreeSet<Student>(); //定义一个自然排序的treeSet集合


	else
	stus=new TreeSet<Student>(cmp);//定义一个自定义排序的集合
	//创建一个字符流,以便键盘录入
	BufferedReader bufr=null;
	try
	{
		bufr=new BufferedReader(new InputStreamReader(System.in));

		String line=null;
		while((line=bufr.readLine())!=null)
	{
		if(line.equals("over"))//键盘录入的退出条件
		break;

		String[] str=line.split(","); //用","切割从键盘读取到的字符串
		//创建学生对象
		Student stu=new Student(str[0],new Double(str[1]),new Double(str[2]),new Double(str[3]));
		stus.add(stu);//把学生对象添加到集合
	
	}
	}


	//异常处理
	catch(Exception e)
	{
	throw new RuntimeException("键盘录入失败");
	}
	finally
	{
		if(bufr!=null)
		try
		{
			bufr.close();
		}
		catch(Exception e)
		{
			throw new RuntimeException("键盘录入关闭失败");
		}
	}
		return stus; //返回一个学生集合
	}


	//定义一个功能把学生集合,得到相应文件
	public static void write2File(Set<Student> stus)
	{
		//创建一个字符输出流
		BufferedWriter bufw=null;
	try
	{
		bufw=new BufferedWriter(new FileWriter("student.txt"));
	
	for(Student stu:stus)//遍历接受进来的集合
	{
		bufw.write(stu.toString()+"\t");//把学生信息写进目的文件
		bufw.write(stu.getSum()+""); //把总分写进目的文件
		bufw.newLine(); //换行
		bufw.flush();//刷新流
	}
	}
	//处理异常
	catch(Exception e)
	{
		throw new RuntimeException("文件写入失败");
	}


	finally
	{
		if(bufw!=null)
		try
		{
			bufw.close();
		}

	catch(Exception e)
	{
		throw new RuntimeException("文件关闭失败");
	}


	
	}
	}
}


class StudentTest
{
	public static void main(String[] args)
	{
		Comparator<Student> cmp=Collections.reverseOrder();//逆转比较器
		//调用静态方法取得学生集合
		Set<Student> stus=StudentTool.getStudents(cmp);
		//调用静态方法把集合中的学生写到目的文件
		StudentTool.write2File(stus);
	}
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值