------- 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编码的文件。
操作字节数组的流对象。ByteArrayInputStream与ByteArrayOutputStream
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