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

来源:互联网 发布:es6数组去重 编辑:程序博客网 时间:2024/05/16 02:22

------- 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集合elsestus=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);}}



原创粉丝点击