黑马程序员--- 学习笔记(第二十一天)

来源:互联网 发布:mac apache 关联php7 编辑:程序博客网 时间:2024/04/29 23:57
 —————————— ASP.Net+Android+IOS开发.Net培训、期待与您交流!——————————
ObjectInputStream
ObjectOutputStream


流构造的时候,必须有一个目的


直接操作对象数据的流


对象序列化(持久化)
要被流操作的对象必须实现Serialziable接口,否则会抛
NOSerializableException 没有序列化异常,
同时应该自定义SerivalVersionUID,给类一个固定标识符
public static final ServialVersionUID=78L;


InvaildClassException 无效类异常


静态不能被序列化,只能序列化堆内存的,不能序列化方法区的
,不想成员变量被序列化可以加上transient关键字


建议输出流的文件命名: 类名.Object


接口中没有方法称为标志接口


常用方法:
writeObject(); //写入对象
readObject(); //读取返回Object

/*人类  对象持久化*/import java.io.Serializable;public class   Person implements Serializable{private static final long  serialVersionUID=1314L;private String name;transient private int age; //被transient修饰不能序列化static String city;//静态不能序列化public void setName(String name){   this.name=name;}public String getName(){   return name;}public void setAge(int age){ this.age=age;}public int getAge(){return age;}public Person(String name, int age,String city){this.name=name;this.age=age;this.city=city;}}


/* ObjectInputStream ObjectOutputStream 直接操作对象数据的流 演示两个特殊方法: writeObject(); readObject();*/import java.io.*;class Demo1 {public static void main(String[] args) throws Exception{//write();read();}public static void read()throws Exception{//从Person.object 中读取对象数据ObjectInputStream ois=new ObjectInputStream(new FileInputStream("Person.object"));//返回Object需要强转Person p=(Person)ois.readObject();Person p1=(Person)ois.readObject();  //无法读取static数据 所以返回null//System.out.println(p.getName()+""+p.city);//被transient修饰的变量 返回0 System.out.println(p.getName()+""+p.getAge());ois.close();}public static void write()throws IOException{//写入对象数据 到Person.objectObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("Person.object"));oos.writeObject(new Person("张三",15,"张角"));oos.writeObject(new Person("李四",50,"捏么"));oos.close();}}



管道流:
PipedInputStream
PipedOutputStream
输入和输出可以直接进行连接,涉及到多线程


connect();连接流


集合中涉及到IO的是Properties
IO中涉及到多线程的是PipeInputStream,PipeOutputStream


/*管道流 PipeInputStream PipeOutputStream演示 connect() 连接流  涉及到多线程*/import java.io.*;class Demo2 {public static void main(String[] args)throws Exception {PipedInputStream pis=new PipedInputStream();PipedOutputStream pos=new PipedOutputStream();pis.connect(pos);new Thread(new Read(pis)).start();Thread.sleep(6000);new Thread(new Write(pos)).start();}}class Read implements Runnable{private PipedInputStream pis;public Read(PipedInputStream pis)throws IOException{this.pis=pis;}public void run(){ try{byte []buf=new byte[1024];int len=0;while((len=pis.read(buf))!=-1){System.out.println(new String(buf,0,len));}}catch (IOException e){System.out.println(e.getMessage());}finally{try{if(pis!=null)pis.close();}catch (IOException e){System.out.println(e.getMessage());}}}}class Writeimplements Runnable{private PipedOutputStream pos;public Write(PipedOutputStream pos){this.pos=pos;}public void run(){try{pos.write("我是管道流 我来le ".getBytes());}catch (IOException e){System.out.println(e.getMessage());}finally{try{if(pos!=null)pos.close();}catch (IOException e){System.out.println(e.getMessage());}}}}



RandomAccessFile类
随机访问文件的读取和写入


该类不算是IO体系中的子类,而是直接继承Object,但是它是IO包中的
成员,因为他具备读和写功能,内部封装了一个数组,而是通过指针对数组
元素进行操作,可以通过getFilePointer获取指针位置,同时可以通过seek
改变指针位置.
其实完成读的原理就是内部封装了输入流和输出流,通过构造函数可以看出
该类只能操作文件,而且操作文件还有模式
r 只读
wr可读可写等


seek();//设置指针,前后都能跳
skipBytes();//跳过字节,只能往后跳


而且该对象的构造函数要操作的文件不存在会自动创建,如果存在则
不会覆盖,如果模式为r只读,不会创建文件,会去读取一个已存在的文件
如果该文件不存在,则会出现异常.如果模式为rw,文件不存在,会自动
创建,不会覆盖文件


可以实现数据的分段写入


/*RandomAccessFile 类getFilePointer();//获取指针skipBytes();//跳过字节seek(); 设置指针 实现多线程分段输出*/import java.io.*;class Demo3 {public static void main(String[] args)throws Exception {//读取RandomAccessFile raf=new RandomAccessFile("g.mp3","rw");//写入RandomAccessFile raf1=new RandomAccessFile("gg.mp3","rw");//三个线程进行分段写入//seek 设置指针位置 实现分段功能new Thread(new Thread1(raf,raf1,0)).start();new Thread(new Thread1(raf,raf1,2097152)).start();new Thread(new Thread1(raf,raf1,4194304)).start();}}//多线程class Thread1 implements Runnable{private RandomAccessFile raf;private RandomAccessFile raf1;private int skip;public Thread1(RandomAccessFile raf,RandomAccessFile raf1,int skip){this.raf=raf;this.raf1=raf1;this.skip=skip;}//run方法public void run(){   try   {   byte []buf=new byte[1024*1024*2];   int len=0;len=raf.read(buf);raf1.write(buf,0,len);   }   catch (IOException e)   {   System.out.println(e.getMessage());   }   finally   {try{if(raf!=null)raf.close();if(raf1!=null)raf1.close();}catch (IOException e)   {   System.out.println(e.getMessage());   }   }}}



DataInputStream与DataOutputStream
可以用来操作基本数据类类型的流对象
//注意, 写入的UTF-8修改版, 正常UTF-8无法读取
writeUTF();
readUTF();


/*DataInputStreamDataOutputStream操作基本数据类型的流对象*/import java.io.*;class Demo4 {public static void main(String[] args)throws Exception {//write();   //read();      DataOutputStream dos=new DataOutputStream(new FileOutputStream("utf.txt"));   //使用utf-7修改版写输入 dos.writeUTF("你好"); dos.close();   DataInputStream dis=new DataInputStream(new FileInputStream("utf.txt")); /* //不能使用默认GBK的编码读 会乱码 byte bu[]=new byte[10]; int len=dis.read(bu); sop(new String(bu,0,len)); */ //只能使用ReadUTF才能读出来 sop(dis.readUTF()); dis.close();}public static void read()throws IOException{DataInputStream dis=new DataInputStream(new FileInputStream("type.txt"));//读的时候要按照写的顺序sop(dis.readBoolean());sop(dis.readByte());//等等dis.close();}public static void write()throws IOException{DataOutputStream dos=new DataOutputStream(new FileOutputStream("type.txt"));// void writeBoolean(boolean v) //          将一个 boolean 值以 1-byte 值形式写入基础输出流。 dos.writeBoolean(true);// void writeByte(int v) //          将一个 byte 值以 1-byte 值形式写出到基础输出流中。  dos.writeByte(102);//void writeBytes(String s) //          将字符串按字节顺序写出到基础输出流中。dos.writeBytes("bytes");//void writeChar(int v) //          将一个 char 值以 2-byte 值形式写入基础输出流中,先写入高字节。 dos.writeChar(97);//void writeChars(String s) //          将字符串按字符顺序写入基础输出流。 dos.writeChars("chars");//void writeDouble(double v) //          使用 Double 类中的 doubleToLongBits 方法将 double 参数转换为一个 long 值,然后将该 long 值以 8-byte 值形式写入基础输出流中,先写入高字节。 dos.writeDouble(4454.12);//void writeFloat(float v) //          使用 Float 类中的 floatToIntBits 方法将 float 参数转换为一个 int 值,然后将该 int 值以 4-byte 值形式写入基础输出流中,先写入高字节。 dos.writeFloat(12.14f);//void writeInt(int v) //          将一个 int 值以 4-byte 值形式写入基础输出流中,先写入高字节。 dos.writeInt(12121);//void writeLong(long v)  //   将一个 long 值以 8-byte 值形式写入基础输出流中,先写入高字节。dos.writeLong(4444444);dos.close();}public static void sop(Object o){System.out.println(o);}}



字节数组流:
ByteArrayInputStream
在构造时需要接受数据源,数据源是一个字节数组
ByteArrayOutputStream
在构造时不用定义数据目的,因为该对象中内部已经封装了可变长度的字节数组


因为这两个对象操作的是数组,没有使用底层资源,所以不用进行close关闭
,不会抛任何IOException,除了writeTo(OutputStream);


toByteArray();//变成字节数组
size();//缓冲区大小
toString();//变成字符串形式
writeTo();//写出到字节输出流


设备:内存就是数组流


用流的读写思想操作数组,,


/*ByteArrayInputStreamByteArrayOutputStream字节数组流只要不使用WriteTo();其他方法都不操作底层数据 不会发生异常*/import java.io.*;class Demo5 {public static void main(String[] args){String s="不管还有多少明天";System.out.println("字节输入读取流\n");ByteArrayInputStream bis=new ByteArrayInputStream(s.getBytes());byte []bb=new byte[1024];int ch=0;while((ch=bis.read(bb,0,1024))!=-1){ //读取System.out.println(new String(bb,0,ch));} System.out.println("\n字节数组写入流");ByteArrayOutputStream bos=new ByteArrayOutputStream();bos.write(12); //写入字节bos.write(5);bos.write(56);byte []bu=bos.toByteArray();//转成字节数组for (byte b : bu ){System.out.println(b);}System.out.println(bos.size());//获取缓冲区大小}}



字符数组流:
CharArrayInputStream与CharArrayInputStream


字符串流:
StringReader与StringWriter


字符编码:
常见的编码表:
ASCII:美国标准信息交换码  一个字节7位表示
ISO8859-1:拉丁码表,欧洲码表  一个字节8位表示 最高位1
GB2312中国的中文编码表,两个字节表示 每个字节最高位1
GBK 中国的编码表升级,融合了更多的中文字符等
Unicode:国际标准码表,融合了多种文字,所有文字都有两个字节表示,
java使用的就是Unicode,  char字符
UTF-8:最多用三个字节表示


编码:字符串变成字节数组
str.getBytes();//可以指定编码
解码:字节数组变成字符串
new String();//构造时可以指定编码


例如:
String s="你好";
byte []b=s.getBytes("GBK");


如果指定的编码不存在会报UnsupportedEncodingException 不支持的编码异常


乱码,编一次,解一次


UTF-8标识头,标识一开始读几个字节,最多三个
一个字节:0
两个字节:110 0
三个字节:1110 10 10


/*字符编码编码 解码*/import java.io.*;import java.util.*;class Demo6 {public static void main(String[] args)throws Exception {  /*String s="你好";byte []b=s.getBytes();byte []b1=s.getBytes("gbk");byte []b2=s.getBytes("iso8859-1");byte []b3=s.getBytes("utf-8");sop(Arrays.toString(b));//使用编码会引发UnsupportedEncodingExceptionSystem.out.println("\n b的多种解码格式 \n");sop(new String(b));sop(new String(b,"gbk"));sop(new String(b,"utf-8"));//no  ???sop(new String(b,"iso8859-1"));//no ????  System.out.println("\n b1的多种解码格式 \n");sop(new String(b1));   sop(new String(b1,"gbk"));sop(new String(b1,"utf-8"));  //no ???sop(new String(b1,"iso8859-1"));//no  ????   System.out.println("\n b2的多种解码格式 \n");sop(new String(b2));//no ??sop(new String(b2,"gbk")); //no  ??sop(new String(b2,"utf-8"));//no ??sop(new String(b2,"iso8859-1"));//no ??System.out.println("\n b3的多种解码格式 \n");sop(new String(b3));// no 浣犲ソ sop(new String(b3,"gbk"));// no 浣犲ソsop(new String(b3,"utf-8"));sop(new String(b3,"iso8859-1"));//no ??????*//*默认字符串编码是gbk 使用的是系统默认的*//*String s="你好";byte []b=s.getBytes("gbk");String str=new String(b,"utf-8");sop(str); // ??? byte bb[]=str.getBytes("utf-8");sop(new String(bb,"gbk"));//锟斤拷锟?*//**/ String s="你好";byte []b=s.getBytes("utf-8");String str=new String(b,"gbk");sop(str); // 浣犲ソ//在编一次,在解一次byte bb[]=str.getBytes("gbk");sop(new String(bb,"utf-8"));  //你好/*String s="你好";byte []b=s.getBytes("iso8859-1");String str=new String(b,"utf-8");sop(str); // ??byte bb[]=str.getBytes("utf-8");sop(new String(bb,"iso8859-1"));//??*/}public static void sop(Object o){System.out.println(o);}}



/*
练习题
*/
/*练习有五个学生,每个学生都有三门成绩键盘录入格式:张三,40,50,60计算他们的总成绩, 按总分高低排序输出到stu.txt*/import java.util.*;import java.io.*;class Demo7 {public static void main(String[] args)throws Exception {//反转比较器Comparator<Student> cmp=Collections.reverseOrder();  //获取集合 TreeSet<Student> ts=set(cmp);toText(ts);}//将数据录入存储到集合 不使用比较器public static TreeSet<Student> set()throws Exception{return set(null);}//将数据录入存储到集合 使用比较器public static TreeSet<Student> set(Comparator<Student> cmp)throws Exception{TreeSet<Student> ts=new TreeSet<Student>();if(cmp!=null)  ts=new TreeSet<Student>(cmp);//反转比较器 进行排序 Collection.reverseOrder() BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); String line=null; while((line=br.readLine())!=null){ if("over".equals(line)) break; String info[]=line.split(",");    ts.add(new Student(info[0],new Integer(info[1]),new Integer(info[2]),new Integer(info[3]))); }br.close();return ts;}//写到硬盘文件 stud.txtpublic static void toText(TreeSet<Student> ts)throws IOException{//写入流PrintWriter pw=new PrintWriter(new FileOutputStream("stud.txt")); Iterator<Student> it=ts.iterator(); while(it.hasNext()){ Student s=it.next();pw.println(s.toString());//目的是流 所以自动刷新 } pw.close();}}//学生类,自身具备成绩比较性class Student implements Comparable<Student>{private String name;  //姓名private int Yuwen;  //语文private int Shuxue; //数学private int Yingyu; //英语private int sum;  //总分public void setName(String name){this.name=name;}public String getName(){return name;}public void setYuwen(int Yuwen){this.Yuwen=Yuwen;}public int getYuwen(){return Yuwen;}public void setShuxue(int Shuxue){ this.Shuxue=Shuxue;}public int getShuxue(){   return Shuxue;}public void setYingyu(int Yingyu){this.Yingyu=Yingyu;}public int getYingyu(){return Yingyu;}public int getSum(){ return Yuwen+Shuxue+Yingyu;}//构造函数public Student(String name, int Yuwen, int Shuxue, int Yingyu){this.name=name;this.Yuwen=Yuwen;this.Shuxue=Shuxue;this.Yingyu=Yingyu;}//复写 hashCodepublic int hashCode(){return (this.getName().hashCode())+(getSum()*13);}//复写 equalspublic boolean equals(Object obj){   if(! (obj instanceof Student))   throw new ClassCastException("类型转换异常");   Student s=(Student)obj;   return (this.getName().equals(s.getName()))&&this.getSum()==s.getSum();}//复写compareTopublic int compareTo(Student s){int num=new Integer(this.getSum()).compareTo(new Integer(s.getSum()));if(num==0)returnthis.getName().compareTo(s.getName());return num;}//复写public String toString(){return "Student["+name+" "+Yuwen+" "+Shuxue+" "+Yingyu+" "+getSum()+" ]";}}/*lisi,10,20,30wanwu,50,60,40zhaoliu,100,50,60wangwu,45,78,32woziji,100,100,99*/









 —————————— ASP.Net+Android+IOS开发.Net培训、期待与您交流!——————————

0 0