黑马程序员_io流2

 ------- android培训java培训、期待与您交流! ----------

合并流:

SequenceInputStream

SequenceInputStream表示其他输入流的逻辑串联。它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。

也就是将多个流对象拼成一个流对象。

例如:

FileInputStream fis = new FileInputStream("1.txt");
FileInputStream fis1 = new FileInputStream("2.txt");
	SequenceInputStream sis = new SequenceInputStream(fis, fis1);
	InputStreamReader isr = new InputStreamReader(sis);
	BufferedReader br = new BufferedReader(isr);
	String line = null;
	while ((line = br.readLine()) != null)
	{
	    System.out.println(line);
	}
	br.close();


主要用于多个源对应一个目的文件。首先将多个源变成一个源,也就是SequenceInputStream.

 

能合并就得能切割。

例子:文件的切割与合并

public class Test
{
    public static void main(String[] args) throws Exception
    {
	splitFile("1.zip");

    }
    public static void splitFile(String filename) throws Exception
    {
	FileInputStream fis  = new FileInputStream(filename);
	byte[] buf = new byte[1024*1024*4];
	int len = 0;
	int total = 1;
	while((len = fis.read(buf))!=-1)
	{
	    FileOutputStream fos = new FileOutputStream(total+".txt");   
	    fos.write(buf,0,len);
	    fos.flush();
	    fos.close();
	    total++;
	}
	Vector<InputStream> vector = new Vector<InputStream>();
	for(int i=1;i<total;i++)
	{
	    FileInputStream fis1 = new FileInputStream(i+".txt");
	    vector.add(fis1);
	}
	SequenceInputStream sis = new SequenceInputStream(vector.elements());
	
	FileOutputStream fos2 = new FileOutputStream("2.zip");
	byte[] bytes = new byte[1024*1024];
	int len1 = 0;
	while((len1 = sis.read(bytes))!=-1)
	{
	    fos2.write(bytes,0,len1);
	}
	fos2.close();	
    }
}

操作对象的流。可以直接操作对象的流:ObjectInputStream ObjectOutputStream

被操作的对象需要实现Serializable()可序列化接口,这是一个标记接口。

这个流可以将创建出来的对象放在硬盘上,避免当程序结束后,对象被垃圾回收。

也就是对象的持久化存储。主要的作用是操作对象

例子:

FileOutputStream fos = new FileOutputStream("2.dmp");
	 ObjectOutputStream oos = new ObjectOutputStream(fos); 
	 oos.writeObject(new String("yxt"));
	 oos.close();
	 FileInputStream fis = new FileInputStream("2.dmp");
	 ObjectInputStream ois = new ObjectInputStream(fis);
	 Object obj = ois.readObject();	 
	 System.out.println((String)obj);
	 ois.close();


但是要求对象必须实现一个Serializable接口,才能被写入

注意,静态的数据不能被序列化。

ObjectInputStream  ObjectOutputStream必须成对出现。

 

管道流:PipedInputStream PipedOutputStream

对于一般的流对象:都是通过一个变量或者数组相关联,也就是先将数据读到内存中的某个地方,再通过输出流写到另一个地方。而管道流直接将两个流对象联系起来。

要集合多线程执行。

实例:

public class Test
{
    public static void main(String[] args) throws Exception
    {
	PipedOutputStream pos  = new PipedOutputStream();
	PipedInputStream pis = new PipedInputStream(pos);
	
	new Thread(new Read(pis)).start();
	new Thread(new Write(pos)).start();
	
    }
}
class Read implements Runnable
{
    private PipedInputStream in;
    public Read(PipedInputStream in)
    {
	this.in = in;
    }
    public void run()
    {
	try
	{
	   int a = in.read(); 
	   System.out.println(a);
	}
	catch(Exception e)
	{
	    
	    
	}
    }
}
class Write implements Runnable
{
    private PipedOutputStream out;
    public Write(PipedOutputStream out)
    {
	this.out = out;
    }
    public void run()
    {
	try
	{
	  Thread.sleep(5000);
	  out.write(2);  
	}catch(Exception e)
	{
	    e.printStackTrace();
	}
    }
}

RandomAccessFile。不是io体系中的子类,而是直接继承自Object。

此类的实例支持对随机访问文件的读取和写入。随机访问文件的行为类似存储在文件系统中的一个大型 byte 数组。存在指向该隐含数组的光标或索引,称为文件指针。

可以通过getFilePoint获取指针位置,用时可以用过seek改变指针的位置。

其实完成读写的原理就是内部封装了字节流输入和输出流。

通过构造函数可以看出,该类只能操作文件。

在字节流输入字符和数字的时候,先将字符转成相应的二进制位(根据编码的格式),

而数字根据其中的类型,将其对应类型的位数,转成字节。

例如:当我们使用write(“a”.getBytes())时候,由于默认的UTF-8,而a占一位.

WriteInt(“王”)的时候,由于‘王’在UTF-8编码时候为3个字节。所以总写出了3位。

实例:

RandomAccessFile raf = new RandomAccessFile("1.txt","rw");
	raf.write("王".getBytes());
	raf.write("大".getBytes());
	raf.write("斌".getBytes());
	raf.close();
	RandomAccessFile raf1 = new RandomAccessFile("1.txt","rw");
	byte[] bytes = new byte[3];
	raf1.read(bytes);
	System.out.println(new String(bytes));
	raf1.read(bytes);
	System.out.println(new String(bytes));
	raf1.read(bytes);
	System.out.println(new String(bytes));
	raf1.close();

当然,这里我们可以用raf1.seek(3);去设置不同的指正位置,从而实现跳过数据读取。

当然,要跳过的字节数一定要满足你的规则。

也可以使用raf1.skipBytes()向后跳若干字节。但是缺点是不能往回跳。

它不仅仅可以实现随机的读,而且还能实现随机的写。

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

 

操作基本数据类型的对象:DataInputStream  DataOutputStream

专门针对使用字节流去操作基本数据类型的数据。

实例:

FileOutputStream fos = new FileOutputStream("data.txt");
	DataOutputStream dos = new DataOutputStream(fos);
	dos.writeBoolean(true);
	dos.writeDouble(1.22);
	dos.writeChar('a');
	dos.writeInt(20);
	dos.close();
	
	FileInputStream fis = new FileInputStream("data.txt");
	DataInputStream dis  = new DataInputStream(fis);
	boolean b = dis.readBoolean();
	
	double d  = dis.readDouble();
	
	char a  = dis.readChar();
	
	int i = dis.readInt();
	
	System.out.println(b+"  "+d+"  "+a+"  "+i);
	

这其中有一种特殊的方式dos.writeUTF(str)的方式去写一个字符串,也就是使用修改版的utf-8去写入到文件中.

使用dos.writeUTF(str)必须使用dos.readUTF();

但是不能使用这个去读取正常的utf编码的文件。

 

操作字节数组的流对象。ByteArrayInputStreamByteArrayOutputStream

ByteArrayInputStream包含一个内部缓冲区,该缓冲区包含从流中读取的字节。内部计数器跟踪 read 方法要提供的下一个字节。也就是这个流直接从这个缓冲区中读取数据,也就是这个流的源设备是内存,而不是文件。

在一定义的时候,就要指定要从哪里读取的源设备。

ByteArrayInputStream(byte[]buf)

          创建一个 ByteArrayInputStream,使用 buf 作为其缓冲区数组。

ByteArrayInputStream(byte[]buf, int offset, int length)

          创建 ByteArrayInputStream,使用 buf 作为其缓冲区数组。

 

注意:这个流对象没有去调用底层资源,也就是只在内存中进行数据移动。

 

ByteArrayOutputStream

此类实现了一个输出流,其中的数据被写入一个 byte 数组。缓冲区会随着数据的不断写入而自动增长。可使用 toByteArray() 和 toString() 获取数据。

也就是将数据写到这个流中定义的可变长度的缓冲区去。

仅仅针对的是内存,而没有涉及底层资源

源设备:

      键盘 System.in,硬盘 FileStream ,内存 ArrayStream

 目的设备:

     控制台System.out,硬盘 FileStream ,内存 ArrayStream

 

上述这个流的出现,就是用流的思想去操作一个字节数组。十分的简单。

 

可以使用ByteArrayOutputStream中的writeTo将这个流中的字节数组输出到指定的输出流中,这与out.write(buf,0,count)的方法效果一致,十分的简单。

baos.writeTo(newFileOutputStream("2.txt"));//一次性的将一个字节中的数据写到这个硬盘中对应的文件中。

 

与它功能相类似的就是CharArrayReader和CharArryWriter

StringReader 和StringWriter

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值