java 字节流入门(内存数组流->文件流)
日期: 2018-07-13 分类: 个人收藏 320次阅读
导读
本文介绍如何将内存数组流的数据写入文件流中。即将内存数组流中的数据通过文件流写到磁盘上,也叫flush,或持久化。毕竟内存是短暂的,磁盘才是永恒。
流就像管道,数据就像管道里的水。管道最大的魅力就是可以连接,使水从一个管道流到另一个管道,流也一样。
之前我们分别介绍了文件流和内存数组流,既然他们是流,那就应该可以连接起来。那么如何从内存数组流写入文件流呢?
在 java 字节流入门(文件流)中,我们介绍了 FileOutputStream(FOS) 和 RandomAccessFile(RAF) 两种写文件的方式。那么,当我们在内存中使用 ByteArrayOutputStream(BAOS) 维护数据时,如何利用 FOS 和 RAF 写文件呢,本文介绍四种方法。
import java.io.*;
import java.nio.file.Path;
import java.nio.file.Paths;
//由于 RandomAccessFile 不是标准的 OutputStream,所以没法直接用 writeTo() 方法实现。那如何将 BAOS 中的数据写入 RandomAccessFile 呢?解决方案是:把 RandomAccessFile 包装成一个 OutputStream。我们实现一个 自定义的 OutputStream,继承 OutputStream,并用 RAF 的三种写方法覆盖 OutputStream 的原有写方法。
class MyRandomAccessFileOutputStream extends OutputStream {
private RandomAccessFile raf;
public MyRandomAccessFileOutputStream(RandomAccessFile raf) {
this.raf = raf;
}
@Override
public void write(int b) throws IOException {
raf.write(b);
}
@Override
public void write(byte b[]) throws IOException {
raf.write(b);
}
@Override
public void write(byte b[], int off, int len) throws IOException {
raf.write(b, off, len);
}
public void seek(long pos) throws IOException {
raf.seek(pos);
}
public long length() throws IOException {
return raf.length();
}
@Override
public void close() throws IOException {
raf.close();
}
}
public class BAOS_FOS_Copy_WriteTo_Test {
private static final Path path = Paths.get("src", "main", "resources", "test.myfile");
private static final File file = path.toFile();
private static int size = 1024*1024*800;
private static byte[] b1 = new byte[size];
private static ByteArrayOutputStream out = new ByteArrayOutputStream();
public static void main(String[] args) throws IOException {
out.write(b1);
writeToFOS();
copyToFOS();
writeToMyRaf();
copyToRaf();
}
// 将 BAOS 中的数据写入 MyRandomAccessFileOutputStream
private static void writeToMyRaf() throws IOException {
if(file.exists())
file.delete();
RandomAccessFile raf = new RandomAccessFile(file, "rw");
MyRandomAccessFileOutputStream myraf = new MyRandomAccessFileOutputStream(raf);
long time = System.currentTimeMillis();
out.writeTo(myraf);
myraf.close();
time = System.currentTimeMillis() - time;
System.out.println("将 "+ size + " 个字节写入 MyRaf 耗时:" + time + "ms");
file.delete();
}
// 将 BAOS 中的数据 copy 写入 RandomAccessFile
private static void copyToRaf() throws IOException {
if(file.exists())
file.delete();
RandomAccessFile raf = new RandomAccessFile(file, "rw");
long time = System.currentTimeMillis();
raf.write(out.toByteArray());
raf.close();
time = System.currentTimeMillis() - time;
System.out.println("将 "+ size + " 个字节 copy 写入 Raf 耗时:" + time + "ms");
file.delete();
}
// 将 BAOS 中的数据写入 FileOutputStream.首先,BAOS 有一个方法叫 writeTo(),这个方法可以将 BAOS 中的数据直接写入另一个字节输出流中。更准确的说法是,使用另一个字节输出流的 write() 方法将 BAOS 中的数据写出去。这里 BAOS 就和一个字节数组是等价的。
private static void writeToFOS() throws IOException {
if(file.exists())
file.delete();
// 将 ByteArrayOutputStream 缓存的数据写入 FileOutputStream 中,即写入文件中
FileOutputStream fileOutputStream = new FileOutputStream(file, false);
long time = System.currentTimeMillis();
out.writeTo(fileOutputStream);
fileOutputStream.close();
time = System.currentTimeMillis() - time;
System.out.println("将 "+ size + " 个字节写入 FOS 耗时:" + time + "ms");
file.delete();
}
// 将 BAOS 中的数据 copy 写入 FileOutputStream
private static void copyToFOS() throws IOException {
if(file.exists())
file.delete();
// 将 ByteArrayOutputStream 缓存的数据写入 FileOutputStream 中,即写入文件中
FileOutputStream fileOutputStream = new FileOutputStream(file, false);
long time = System.currentTimeMillis();
fileOutputStream.write(out.toByteArray());
fileOutputStream.close();
time = System.currentTimeMillis() - time;
System.out.println("将 "+ size + " 个字节 copy 写入 FOS 耗时:" + time + "ms");
file.delete();
}
}
结果:
将 838860800 个字节写入 FOS 耗时:1541ms
将 838860800 个字节 copy 写入 FOS 耗时:2097ms
将 838860800 个字节写入 MyRaf 耗时:1632ms
将 838860800 个字节 copy 写入 Raf 耗时:2188ms
写 800M数据。将 RAF 包装成 OutputStream 和 FileOutputStream 的效率差不多。对于两种文件流的写入方法,writeTo 总是比 copy 写入要快。毕竟 copy 多了一步拷贝,而且会占用额外内存。
所以不管哪种文件流,用 BAOS 的 writeTo() 都是最好的。
假如用 ByteArrayOutputStream 管理内存数据,想持久化,那么有 FileOutputstream 和 RandomAccessFile 可以选择。
可以使用 BAOS 的 writeTo() 方法进行写入,为了将 RandomAccessFile 当流来用,可以外边包装一层。不要用 copy 方法,没好处的。
欢迎关注个人公众号:数据库漫游指南
除特别声明,本站所有文章均为原创,如需转载请以超级链接形式注明出处:SmartCat's Blog
标签:Java
上一篇: java 字节流入门(读文件)
下一篇: java 字节流入门(内存数组流)
精华推荐