亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定

文件io的坑

標簽:
Java

API的误解

最近被同事问到一个问题,就是他做的文件下载功能下载下来的结果不对,在review代码的时候,发现了如下的写法。

    byte[] bytes = new byte[1024];
    int len = 0;
    while((len = in.read(bytes))>0){
           os.write(bytes);
    }

然后就把bytes写入文件了。然后最后数据多了,这个问题,主要是没有仔细看java的api。

public int read(byte[] b) throws IOException

read方法接受一个数组,并且返回一个int类型的长度,表示这次读取了多少数据。多出数据的原因就是没有获取到返回的长度进行合理的获取。
下面简单说一下不检验长度的问题。
byte[] b=new byte[5]第一次从读取文件返回返回以后被填满。
{1,2,3,4,5}
下次没有5个数据只有三个了
{6,7,8,4,5}
一直使用这个byte会发现,下次数据如果写入byte的全部的长度的话,就会有脏数据,{4,5}。这就是问题的原因,没有注意方法的返回值。
如果是一个正常的java文件拷贝,例如下面的代码

 byte[] bytes = new byte[1024];
 while ((i = bis.read(bytes)) >0 ) {
        os.write(bytes, 0, i);
 }

每次需要读取到返回值,然后写入的时候,然后把数组的值,按照长度截取传入。

最佳实践

java7的特性nio2–Files

static long	copy(InputStream in, Path target, CopyOption... options)
static long	copy(Path source, OutputStream out)
static Path	copy(Path source, Path target, CopyOption... options)

在java7 nio的特性里,提供了丰富的拷贝的方式。底层都是通过jni实现的拷贝,要比java中写byte数组拷贝要更高效,减少了对象从堆内存到系统内存的折腾。
顺带说一下,nio2其他的比较好用的拷贝文件可能用到的方法。

static InputStream	newInputStream(Path path, OpenOption... options)
static OutputStream	newOutputStream(Path path, OpenOption... options)

用静态方法获取输入输出流。通过这个方法只是让代码更短,看着舒服。这个相当于静态工厂了。

static byte[]	readAllBytes(Path path)
static List<String>	readAllLines(Path path, Charset cs)

直接获取到文件所有数组以及所有行。这里不用再去考虑什么文件关闭的问题。比try-with-resource还简单。

static Path	createFile(Path path, FileAttribute<?>... attrs)
static void	delete(Path path)
static Path	move(Path source, Path target, CopyOption... options)

普通的文件操作。
nio2带来了优势主要是在一些特殊功能上,一方面是有更高效的jni实现,一方面是静态方法使得调用的代码更整洁。
如果jdk在7以下。就需要考虑common io的封装的操作。性能上可能没有提升,但是也能使得调用代
common io
CopyUtils

       Method      Input               Output          Dependency
       ------      -----               ------          -------
 1     copy        InputStream         OutputStream    (primitive)
 2     copy        Reader              Writer          (primitive)
 3     copy        InputStream         Writer          2
 4     copy        Reader              OutputStream    2
 5     copy        String              OutputStream    2
 6     copy        String              Writer          (trivial)
 7     copy        byte[]              Writer          3
 8     copy        byte[]              OutputStream    (trivial)

common io有更多的封装,有InputStream到OutputStream的拷贝,这个可以直接应用到网络io。

common io关闭的方式需要注意

 try {
     return IOUtils.copy(inputStream, outputStream);
 } finally {
     IOUtils.closeQuietly(inputStream, outputStream);
 }

总结

java7已经是提供了很强大的功能了,在不依赖其他库的时候是不错的选择。如果可以引用common io。建议可以考虑common io。因为他封装的更多,应对复杂的场景,可以写较少的代码。

點擊查看更多內容
TA 點贊

若覺得本文不錯,就分享一下吧!

評論

作者其他優質文章

正在加載中
JAVA開發工程師
手記
粉絲
1.6萬
獲贊與收藏
380

關注作者,訂閱最新文章

閱讀免費教程

  • 推薦
  • 評論
  • 收藏
  • 共同學習,寫下你的評論
感謝您的支持,我會繼續努力的~
掃碼打賞,你說多少就多少
贊賞金額會直接到老師賬戶
支付方式
打開微信掃一掃,即可進行掃碼打賞哦
今天注冊有機會得

100積分直接送

付費專欄免費學

大額優惠券免費領

立即參與 放棄機會
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號

舉報

0/150
提交
取消