java笔记-IO流-管道流

对象的存储和读取

对象的存储和读取使用ObjectOutputStream和ObjectInputStream,这两个读写流是成对出现的。

/*
 对象的存储和读取
 对象存储时使用ObjectOutputStream,当读取时,只能使用ObjectInputStream读取。
*/
import java.io.*;
class ObjectStreamDemo 
{
	public static void main(String[] args)
	{
		try{
			//写对象。
			writeObj();
			//读对象。
			readObj();
		}
		catch(Exception e){
			throw new RuntimeException("读写失败。");
		}
	}

	public static void readObj()throws Exception{
		//读取Object对象。
		ObjectInputStream ois=new ObjectInputStream(new FileInputStream("obj.txt"));
		//依次读取两个。
		Person p1=(Person)ois.readObject();
		Person p2=(Person)ois.readObject();
		System.out.println(p1);
		System.out.println(p2);
		//资源使用完毕后关闭
		ois.close();
	}
	public static void writeObj()throws Exception{
		//存储Object对象。
		ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("obj.txt"));
		//依次存储两个。
		oos.writeObject(new Person("cs00",100));
		oos.writeObject(new Person("cs01",222));
		//资源使用完毕后关闭
		oos.close();
	}
}

输入和输出管道

主要用到两个流:PipedInputStream和PipedOutputStream

思路:

1.建立读和写两个(单线程易死锁)线程(继承Runnable,重写run方法)

2.读线程从输入管道中读取字符串数据(字符串转化为字节)

3.写线程向输出管道写入字节数据(字节转化为字符串)

4.建立输入和输出管道之间的联系。

5.启动输入和输出管道线程。

import java.io.*;
import java.util.*;
class PipedStreamDemo 
{
	public static void main(String[] args) throws Exception
	{
		//建立输入和输出管道。
		PipedInputStream pipedIn=new PipedInputStream();
		PipedOutputStream pipedOut=new PipedOutputStream();
		//搭建输入和输出管道的桥梁。
		pipedIn.connect(pipedOut);
		//启动输入和输出管道线程。
		new Thread(new Write(pipedOut)).start();
		new Thread(new Read(pipedIn)).start();
	}
}
class Read implements Runnable
{
	//对象一旦建立即初始化输入管道。
	private PipedInputStream in;
	Read(PipedInputStream in){
		this.in=in;
	}
	//重写run方法。
	public void run(){
		try{
			//建立读取缓冲,存读取的数据。
			byte[] buf=new byte[1024];
			//从输入管道读取字节数据,并返回读取长度。
			int len=in.read(buf);
			//将读取到的字节数据转化为字符串并输出。
			String s=new String(buf,0,len);
			System.out.println(s);	
			in.close();
		}
		catch(Exception e){
			throw new RuntimeException("管道读取失败");
		}
	}
}
class Write implements Runnable
{
	//Write一旦建立即初始化输出管道。
	private PipedOutputStream out;
	Write(PipedOutputStream out){
		this.out=out;
	}
	public void run(){
		try{
			//将要写的数据转化为字节。
			out.write("管道开始写数据".getBytes());
			//关闭管道流。
			out.close();
		}
		catch(Exception e){
			throw new RuntimeException("管道写数据失败。");
		}
	}
}

RandomAccessFile

此类的实例支持对随机访问文件的读取和写入。可分段实现读写操作,如多线程下载。通过构造函数可以看出,该类只能操作文件,并且有模式,如r,rw等,倘若对象的构造函数操作的文件不存在,会自动创建,如果存在则不会覆盖。

流的操作规律

源设备:

键盘:System.in    硬盘:FileStream    内存:ArrayStream

目的设备:

键盘:System.out    硬盘:FileStream    内存:ArrayStream

字符编码

字符流的出现方便了字符操作,更重要的是加入了编码转换,字符和字节的转换通过子类转换流来完成:InputStreamReader和OutputStreamWriter,在两个对象进行构造的时候可以加入字符集

编码解码

编码:字符串转为字节数组     String.getBytes()

解码:字节数组转为字符串     new String(Byte[])

UTF-8根据编码头的数值,确定依次读取几个字节。

“联通”编码时采用gbk码,但打开时由于“联通”的码符合UTF-8格式,所以会按照UTF-8解码。解决方法:在“联通”字前加任意中文即可。

打印学生信息(解码,排序,集合,文本,存储)

思路:

1.创建学生类对象,该对象具有比较性,需重写hashCode(),equals(),compareTo()方法。

2.创建集合容器,依次逐行读取从键盘输入的学生信息

3.将读取到的学生信息存储到集合容器

4.对结合容器按照学生成绩总和从大到小排序

5.将排序好的数据输出到文本文件

/*
 五个学生对象,每个学生有三门课成绩
 从键盘输入以上数据(姓名,成绩1,成绩2,成绩3)
 将学生和计算的总分数按照分数大小排列保存到文本文件。
*/
import java.io.*;
import java.util.*;
class  StudentInfoDemo
{
	public static void main(String[] args) throws Exception
	{
		//反转比较器排序
		Comparator compStu=Collections.reverseOrder();
		//获得学生信息,存储在Set集合容器中。
		Set stu=StudentInfoTool.getStudent(compStu);
		//将Set集合容器中的信息存储到文本文件中。
		StudentInfoTool.write2File(stu);
	}
}
class Student implements Comparable{
	private String name;
	private int cj1;
	private int cj2;
	private int cj3;
	private int sum;
	//构造函数,初始化学生信息,并直接统计成绩总和。
	Student(String name,int cj1,int cj2,int cj3){
		this.name=name;
		this.cj1=cj1;
		this.cj2=cj2;
		this.cj3=cj3;
		this.sum=cj1+cj2+cj3;
	}
	public String getName(){
		return this.name;
	}
	public int getSum(){
		return this.sum;
	}
	//重写toString()方法。
	public String toString(){
		return "{Name:"+this.name+","+this.cj1+","+this.cj2+","+this.cj3+"}\t";
	}
	//重写Comparable中的compareTo方法。
	public int compareTo(Student s){
		//先比较成绩大小,若成绩相等再比较姓名
		int num=new Integer(this.sum).compareTo(new Integer(s.sum));
		if(num==0){
			return this.name.compareTo(s.name);
		}
		return num;
	}
	//重写hash值。
	public int hashCode(){
		return name.hashCode()+sum;
	}
	//重写equals方法,当姓名和总成绩相同则为同一个人。
	public boolean equals(Object obj){
		if(!(obj instanceof Student))	
			throw new ClassCastException("Student 类型不匹配");
		Student s=(Student)obj;
		return (this.name.equals(s.name)) && (this.sum==s.sum);
	}
}
class StudentInfoTool
{
	//重载函数,一个有参,一个无参。
	public static Set getStudent() throws Exception{
		return getStudent(null);
	}
	//默认成绩总和从小到大,若使成绩从大到小,可传递比较器参数
	//该方法保留了顺排序和逆排序。
	public static Set getStudent(Comparator cmp) throws Exception{
		//创建缓冲区接收键盘输入学生信息。
		BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
		String str=null;
		//创建集合容器,该集合容器盛装Student
		Set s=null;
		//若按照默认排序,则TreeSet无需传递新的比较器。
		if(cmp==null){
			s=new TreeSet();
		}
		else{
			s=new TreeSet(cmp);
		}
		//依次循环读行数据。
		while((str=bufr.readLine())!=null){
			//行数据为over终止。
			if("over".equals(str)){
				break;
			}
			//使用”,“分割字符串并存储到字符串数组。
			String[] Stus=str.split(",");
			//创建学生对象并初始化。
			Student stu=new Student(Stus[0],
							Integer.parseInt(Stus[1]),
							Integer.parseInt(Stus[2]),
							Integer.parseInt(Stus[3]));
			//将初始化的学生对象装到集合容器中。
			s.add(stu);
		}
		bufr.close();
		//返回集合容器。
		return s;
	}
	//将装有学生信息的集合容器数据存储到文本文件中。
	public static void write2File(Set stus)throws Exception{
		BufferedWriter bufw=new BufferedWriter(new FileWriter("stu.info"));
		//遍历集合中的学生对象,并取出学生信息存储到文本文件。
		for(Student s:stus){
			bufw.write(s.toString());
			//学生总成绩为int型,需转化为字符串。
			//BufferedWriter中的write方法为写入单个字符
			//若传递的小于128的整数,则会按照ascii码表查询该整数对应的字符。
			//若大于128,则返回"?"
			bufw.write(s.getSum()+"");
			//换行
			bufw.newLine();
			//使用了缓冲技术,需即时刷新。
			bufw.flush();
		}
		bufw.close();
	}
}
在上述函数中,默认排序是按照学生成绩从小到大排序,在不改变原有排序的基础上,通过传递比较器参数,利用重载实现从大到小排序,值得注意。

你可能感兴趣的:(走走)