黑马程序员——41,打印流,合并流,对象序列化,管道流,RandomAccessFile

来源:互联网 发布:c语言从右至左的运算符 编辑:程序博客网 时间:2024/04/30 02:38
----------- android培训java培训、java学习型技术博客、期待与您交流!------------    
黑马程序员——41,打印流,合并流,对象序列化,管道流,RandomAccessFile    
一:打印流----》
        字节打印流PrintStream:其构造函数可以接收File对象,String型路径,字节流    
        字符打印流PrintWriter:其构造函数可以接收File对象,String型路径,字节流和字符流,应用更加广泛。
        所以主要介绍PrintWriter的使用,比较常用的构造函数有两个PrintWriter(OutputStream   out,boolean  autoFlush)和PrintWriter(Writer    out, boolean   autoFlush),一般后面填写的都是true,表示自动刷新。
 
import    java.io.*;class    Ioliou25{         public   static  void   main(String[] args)throws  IOException         {                   File   f=new File("f:\\yyyyyyyk.txt");                   BufferedReader    bufr=new BufferedReader(new InputStreamReader(System.in));           //      PrintWriter  pw=new   PrintWriter(System.out,true);//这个带true的就自动刷新,不用写flush方法了       //          InputStreamReader是字节与字符的桥梁                 //PrintWriter   pw=new PrintWriter(f,true);//这种写法编译错误,PrintWriter类没有这种构造函数                   /*                   PrintWriter构造函数里面可以带true的只有                   PrintWriter(OutputStream   out,boolean  autoFlush)                   PrintWriter(Writer    out, boolean   autoFlush)                   */         //       PrintWriter   pw=new   PrintWriter(System.out);                  PrintWriter   pw=new PrintWriter(new   FileWriter(f),true);//使用FileWriter嵌套f的话就可以带true                   String   s=null;                   while((s=bufr.readLine())!=null)                   {                              if(s.equals("over"))//设置结束语句                                     break;                             // pw.write(s.toUpperCase()); //没有换行                             pw.println(s.toUpperCase());//这个使用println方法更为常见                             //pw.flush();                   }                   bufr.close();                   pw.close();          }         public  static   void  soc(Object  obj)//打印方法         {             System.out.println(obj);                    }}



二:合并流SquenceInputStream----》
        SequenceInputStream的构造函数有两个:
public   SequenceInputStream(Enumeration<? extends InputStream> e)//接收的是Enumeration的实例,该构造函数主要用在需要合并两个以上的读取流的情况下public   SequenceInputStream(InputStream s1,InputStream s2)//按顺序接收读取流s1和s2(注意顺序不能调乱)


import java.io.*;import java.util.*; class  Ioliou27{         public  static void  main(String[] args)throws  IOException         {                      qiege();                    //hebing();                     hebing2();          }         public   static  void  qiege()/*切割文件*/throws  IOException         {                   File   f=new  File("f:\\8.11\\8.11练习.png");//建立文件对象                   FileInputStream     fis=new  FileInputStream(f);//关联目的文件                   FileOutputStream    fos=null;                   int  i=0,k=0;                   byte[]    by=new byte[1024*10];                   while((i=fis.read(by))!=-1)                   {                               k++;                                fos=new FileOutputStream("f:\\8.11\\8.11练习"+k+".part");                               //每一次循环k值都不同所以对应有不同的关联的碎片文件                               fos.write(by,0,i);                                                   }                   fis.close();                   fos.close();                                }         public  static   void  hebing()/*合并文件*/throws  IOException         {              ArrayList<FileInputStream>     al=new  ArrayList<FileInputStream>();                    //这里采用的是ArrayList集合                    for(int x=1;x<=4;x++)                    {                        al.add(new   FileInputStream("f:\\8.11\\8.11练习"+x+".part"));                               //把与文件相关联的流装进集合中                    }                   final  Iterator<FileInputStream>    it=  al.iterator();                   //被匿名内部类访问的局部成员要被final修饰                   Enumeration<FileInputStream>      en=new   Enumeration<FileInputStream>()                   {                       //直接覆盖hasMoreElements和nextElement方法                   public   boolean  hasMoreElements()                   {                       return    it.hasNext();                    }                   public   FileInputStream   nextElement()                   {                       return   it.next();                   }                                     };                   SequenceInputStream   sis=new  SequenceInputStream(en);                   FileOutputStream   fos=new  FileOutputStream("f:\\8.11\\8.11练习合并.png");//确定目的地的                   int  i=0;                   byte[]    by= new  byte[1024];                   while((i=sis.read(by))!=-1)                   {                        fos.write(by,0,i);                        }                   sis.close();                   fos.close();                   }         public  static   void  hebing2()/*第二种合并方法*/throws  IOException         {                   Vector<FileInputStream>   v=new  Vector<FileInputStream>();//直接用Vector集合来装流对象                   for(int   x=1;x<=4;x++)                   {                        v.add(new FileInputStream("f:\\8.11\\8.11练习"+x+".part"));                    }                   Enumeration<FileInputStream>    en=v.elements();                   SequenceInputStream    sis=new SequenceInputStream(en);                   FileOutputStream   fos=new FileOutputStream("f:\\8.11\\8.11练习合并2.png");                   int   i=0;                   byte[]    by=new byte[1024*10];                   while((i=sis.read(by))!=-1)                   {                         fos.write(by,0,i);                      }                   sis.close();                   fos.close();                              }         public  static   void  soc(Object  obj)         {                System.out.println(obj);                 }}



三:对象的序列化ObjectOutputStream----》
        对象序列化就是把对象存放在硬盘上,存放对象所属的类必须是实现了Serializable类。虚拟机会给实现了Serializable接口的类划分UID号标示,UID号与类成员有关,如果类成员有改变,虚拟机会重新划分UID号的,当然也可以自动在该类中添加固定的UID号:public  static   final   long   serialazableUID=42L;这样无论该类的成员怎么变化该类的UID号都是固定不变的。
       为什么会有这个UID号的存在?
       因为对象都是按照对象建立的,如果没有UID号的话,那么把一个类的对象存放在硬盘上,接着该类成员有所改变,程序再读取该对象的话,虚拟机就会容易混乱。
被static或者transient修饰的成员无法被序列化。
       调用readObject读取对象,调用writeObject写入对象。
import   java.io.*;import   java.util.*; class   Ioliou28{         public   static  void   main(String[] args)throws  Exception//主函数         {      //  xieru();            duqu() ;         }         public  static  void   xieru()/*写入*/ throws  Exception         {                   File   f=new File("f:\\北方.txt");                   FileOutputStream   fos=new  FileOutputStream(f);                   ObjectOutputStream   oops=new ObjectOutputStream(fos);                   oops.writeObject(new  Per("呼呼呼",26,"jkl"));                   //写入对象,写入的对象所属的类必须是实现了Serializable借口                  oops.close();                                         }         public  static  void  duqu()/*读取*/ throws  Exception         {                      File   f=new  File("f:\\北方.txt");                     FileInputStream   fos=new  FileInputStream(f);                    ObjectInputStream   oips=new  ObjectInputStream(fos);                    Object  obj=oips.readObject();//readObject方法返回的是Object类型的对象                    //readObject方法会抛出一个ClassNotFoundException,为了简便,方法上声明抛出都是Exception                    Per    p =(Per)obj;                  oips.close();                       soc(p);                                  }         public  static  void  soc(Object  obj)         {            System.out.println(obj);                     } }class   Per   implements  Serializable{//public   static  final  long   serializableUID=42L;         static   String   name="无名";//静态成员不能被序列化         private   int    age;         transient   String  country="cn";//transient修饰的成员也不能被序列化         Per(String   name, int    age,String   country)         {              this.name=name;                    this.age=age;                    this.country=country  ;         }         public   String  toString()         {               return  name+":"+age+":"+country;                    }}


四:管道流PipeInputStream和PipeOutputSatream----》
        管道输入流和管道输出流可以用connect方法连接在一起,通常与多线程密切相关:一般是一条线程负责管道输入流,一条线程负责管道输出流。
   
 class  Read() /*读取线程*/  implements   Runnable  throws  IOException{         private   PipedInputStream   pis=null;          Read(PipedInputStream   pis)         {             this.pis=pis;              }         public   void   run()           {                int i=0;                      byte[]  by=new  byte[1024];                      while((i=pis.read(by))!=-1)                      {                         //填写内容                                }           }}class  Write()  /*写入线程*/implements   Runnable throws  IOException{         private   PipedOutputStream    pos=null;         Write(PipedOutputStream   pos)         {             this.pos=pos;             }          public   void   run( )           {                // int i=0;                      // byte[]  by=new   byte[1024];                            pos.write("huhuhu".getBytes());           }            }import  java.io.*;class  Ioliou29{         public   static void   main(String[] args)throws  IOException         {                   PipedInputStream    pis=new  PipedInputStream();                   PipedOutputStream    pos=new  PipedOutputStream();                   pis.connect(pos);//管道输入流和管道输出流连接                 //开启线程                   new  Thread(new  Read(pis)).start();                   new  Thread(new   Write(pos)) .start();                        }         public   static  void   soc(Object   obj)         {             System.out.println(obj);                           }}


五:RandomAccessFile----》
        RandomAccessFile也是IO包的成员,里面封装了字节写入流和字节读取流,所以可以选取模式,常用的有两种模式”r”只读和”rw”读写,该类里面封装了一个非常大的数组,还有一个指针指示数组,通过getFilePointer方法获取指针位置,通过seek方法调整指针位置。
        有两个常用的构造函数,都是用来关联文件并且确定模式的:
public   RandomAccessFile(File file,  String  mode)throws FileNotFoundExceptionpublic   RandomAccessFile(String  name,String mode)throws FileNotFoundException
       由于该类方法很多,下面就列举一些比较常用的读取相关方法:

public   void close()throws  IOException   //关闭public  int  read()throws  IOException //读取一个数据字节public  int  read(byte[] b)throws  IOException //按照数组长度读取public  int  read(byte[] b,int off,int len)throws  IOException//按照数组中实际接收数据的长度读取public  final  boolean  readBoolean()throws  IOException//读取一个booleanpublic  final  byte  readByte()throws  IOException//读取一个字节public  final  char  readChar()throws  IOException//读取一个字符public  final  double  readDouble()throws  IOException//读取一个double数据public  final  float  readFloat()throws  IOException//读取一个float数据public  final  int  readInt()throws IOException//读取一个int数据
        那么也有对应的写入方法,这里就不一一列举了。我们可以发现一个规律,那就是该类读取与写入都可以按照某个数据长度的进行操作的,非常的方便。
import   java.io.*;class  Ioliou30{         public  static   void   main(String[] args) throws   IOException         {          write();          read();               }         public   static  void   write()throws  IOException         {                   File    f=new  File("f:\\学习.txt");                   RandomAccessFile    raf=new RandomAccessFile(f,"rw");//关联文件并确定操作模式                   //如果文件不存在会自动创建                   raf.write("一二三".getBytes());                   raf.writeInt(56);//写入数字时最好用writeInt,以32位形式写入                   raf.write("四五六".getBytes());                   raf.writeInt(85);//写入数字时最好用writeInt,以32位形式写入                                    }         public   static   void  read()throws  IOException         {                   File   f=new   File("f:\\学习.txt");                   RandomAccessFile    raf=new RandomAccessFile(f,"rw");//关联文件并确定操作模式                   soc("raf.getFilePointer()="+raf.getFilePointer());//getFilePointer方法返回内部数组指针位置                    //raf.seek(2);//调整内部数组的指针指向第2位                   byte[]   by=new byte[4];                   raf.read(by);//按照字节数组读取                   String   s=new  String(by);//按照字节数组转成字符串                   int  i=  raf.readInt();//按照32位读取数据                                       soc(s);                   soc(i);          }         public  static void  soc(Object  obj)         {             System.out.println(obj);                  }}


----------- android培训java培训、java学习型技术博客、期待与您交流!------------    


0 0
原创粉丝点击