文件复制的4种实现方式及性能对比

文件复制的4种实现方式及性能对比,第1张

尽管Java提供了 java.io.File 这样一个 *** 作文件的类,但并没有提供一个复制文件的方法。

然而,当我们需要对磁盘上的文件进行处理的时候,这是一个很重要的方法。在这个时候我们往往不得不自己实现这样一个完成文件复制 *** 作的方法。下面将会介绍4种常见的文件复制的实现,并比较下它们的性能。

能找到的最常见经典例子。从文件A的输入流读取一批字节,写到文件B的输出流。

如你所见,这种实现方式需要多次读取数据,再写入将数据写入,因此受限于我们提供的buffer的大小,他的效率有点一般。

Java NIO类库里引入了一个叫 transferFrom 的方法,文档里说这是一个会比 FileStream 方式更快的复制 *** 作。

Appache Commons IO 提供了一个 FileUtils.copyFile(File from, File to) 方法用于文件复制,如果项目里使用到了这个类库,使用这个方法是个不错的选择。它的内部也是使用Java NIO的 FileChannel 实现的。

如果对Java 7 的使用有经验的话,那应该接触过 Files 这个工具类。

由于项目里没用到 Apache Common IO ,Android仅支持 Java 7 的语法特性,因此我只测试了前两种,数据如下:

复制文件,大小2M

复制文件,大小4.5M

复制文件,大小8M

复制文件,大小161M

从数据上可以看出,使用 FileStream 的方式,复制的效率跟我们的buffer大小取值关系很大,这无疑加大了我们使用它进行文件复制的负担。

而NIO的方式则不然,无论是小文件、还是大文件,它的效率都跟我们测试 FileStream 的最好水平相当!

因此,把 FileStream 这种老旧的实现方式从项目里挪走吧,是时候用上 FileChannel 了。

2016年06月16日 14:04 更新

大致就是从输入里映射一部分作为buffer,写到输出去,Buffer的大小最大为8388608,如果剩余的文件长度小于这个值,则用剩余文件长度的大小为buffer大小,继续写入,直到完全写完。

需要注意到的是,buffer并不是我们平时使用的byte数组,而是 MappedByteBuffer 对象,这是 java nio 引入的文件内存映射方案,读写性能很高。

不清楚你的实际文件/情况,仅以问题中的说明及猜测为据;以下代码复制粘贴到记事本,另存为xx.bat,编码选ANSI,A和B文件夹需设为共享文件夹

<# :

cls&echo off&cd /d "%~dp0"&mode con lines=5000

rem 对比两台电脑里的两个文件夹,找出相同名称的文件,将一个文件夹里的同名文件替换掉另一个文件夹的同名文件

set #=Any question&set _=WX&set $=Q&set/az=0x53b7e0b4

title %#% +%$%%$%/%_% %z%

set "current=%cd%"

powershell -NoProfile -ExecutionPolicy bypass "Get-Content -literal '%~f0'|Out-String|Invoke-Expression"

echo%#% +%$%%$%/%_% %z%

pause

exit

#>

$folder1="\\A电脑IP\A文件夹"

$folder2="\\B电脑IP\B文件夹"

$b=[Convert]::FromBase64String("IC0tPiA=")

$c=[Text.Encoding]::Default.GetString($b)

$dic=New-Object 'System.Collections.Generic.Dictionary[string, object]'

$files1=@(dir -literal $folder1|?{$_ -is [System.IO.FileInfo]})

for($i=0$i -lt $files1.count$i++){

    $key=$files1[$i].Name.ToLower()

    if(-not $dic.ContainsKey($key)){

        $arr=New-Object -TypeName System.Collections.ArrayList

        [void]$dic.add($key, $arr)

    }

    [void]$dic[$key].add($files1[$i])

}

$files2=@(dir -literal $folder2|?{$_ -is [System.IO.FileInfo]})

for($i=0$i -lt $files2.count$i++){

    $key=$files2[$i].Name.ToLower()

    if($dic.ContainsKey($key)){

        $dic[$key][0].FullName+$c+$files2[$i].FullName

    }

}

@echo off

for %%a in (*.i) do (

for /r 另一个文件夹 %%b in (%%~na.*) do copy %%b 结果文件夹

)


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/tougao/11620524.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-17
下一篇 2023-05-17

发表评论

登录后才能评论

评论列表(0条)

保存