本篇内容介绍了“java如何将内存数组流的数据写入文件流中”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
在 java 字节流入门(文件流)中,我们介绍了 FileOutputStream(FOS) 和 RandomAccessFile(RAF) 两种写文件的方式。那么,当我们在内存中使用 ByteArrayOutputStream(BAOS) 维护数据时,如何利用 FOS 和 RAF 写文件呢,本文介绍四种方法。
准备工作:
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();
并将 b1 写入 out 中
out.write(b1);
writeTo写入FOS
首先,BAOS 有一个方法叫 writeTo(),这个方法可以将 BAOS 中的数据直接写入另一个字节输出流中。更准确的说法是,使用另一个字节输出流的 write() 方法将 BAOS 中的数据写出去。这里 BAOS 就和一个字节数组是等价的。
/** * Writes the complete contents of this byte array output stream to * the specified output stream argument, as if by calling the output * stream's write method using <code>out.write(buf, 0, count)</code>. * * @param out the output stream to which to write the data. * @exception IOException if an I/O error occurs. */ public synchronized void writeTo(OutputStream out) throws IOException { out.write(buf, 0, count); }
因为 FOS 本身就是 OutputStream,所以可以直接将 BAOS 中的数据通过 writeTo() 写入 FOS 中。
// 将 BAOS 中的数据写入 FileOutputStream 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(); }
writeTo写入RAF
由于 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(); }}
接下来,就可以开心的把 RandomAccessFile 当 OutputStream 用了。
// 将 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(); }
Copy写入FOS
大家记不记得 BAOS 还有个 toByteArray() 方法可以将其中的内容返回一个 byte 数组。其实现调用了 Arrays.copyOf() 方法,这里记做 copy 。
然后回想,其实各种流都有一个 write(byte[]) 方法,所以你们知道我想干嘛了吗,嗯,很粗暴的实现方式,上代码。
// 将 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(); }
Copy写入RAF
同样的,RandomAccessFile 也有 write(byte[]) 方法,所以。。。继续上代码:
// 将 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(); }
接下来我们比较一下这四种方式的速度:
实验对比
写 800M数据。将 RAF 包装成 OutputStream 和 FileOutputStream 的效率差不多。对于两种文件流的写入方法,writeTo 总是比 copy 写入要快。毕竟 copy 多了一步拷贝,而且会占用额外内存。
所以不管哪种文件流,用 BAOS 的 writeTo() 都是最好的。
将 838860800 个字节写入 FOS 耗时:1413ms将 838860800 个字节 copy 写入 FOS 耗时:2092ms将 838860800 个字节写入 MyRaf 耗时:1452ms将 838860800 个字节 copy 写入 Raf 耗时:2203ms
“java如何将内存数组流的数据写入文件流中”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。
原文链接:https://my.oschina.net/u/3664598/blog/4430318