您的位置:首页 > 职场人生

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

2015-09-01 18:44 911 查看
----------- 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 FileNotFoundException
public   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//读取一个boolean

public  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学习型技术博客、期待与您交流!------------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: