黑马程序员——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学习型技术博客、期待与您交流!------------