java 通过流, nio 移动文件或者文件夹

我们用例子说明java怎样通过不同的方式移动文件或文件夹。

[b]首先, 我们先介绍通过流的例子[/b],你可以很容易把指定的源文件或文件夹移动到目标文件夹中。
程序中, 你需要指定源文件/文件夹和目标文件夹的绝对路径。 如果指定的源文件(夹)不存在, 程序打印出提示信息"File or directory does not exist.", 然后从控制台中推出程序。 如果指定的目标文件夹不存在,程序会提示你是否创建一个新的文件夹。 通过输入"y", 程序就会为你创建一个新的文件夹并且把源文件全部移动到目标文件夹中。 当目标文件夹存在时, 它会征询你是否替换掉已经存在的文件夹。

package io;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;

import javax.swing.JOptionPane;

public class MovingFile {

public static void main(String[] args) throws IOException {

int a = 0;

BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
System.out
.print("Enter the file or directory name that has to be moved : ");

String src = in.readLine();

if (src.equals("")) {

System.out.println("Invalid directory or file name.");

System.exit(0);

}

File source = new File(src);

if (!source.exists()) {

System.out.println("File or directory does not exist.");

System.exit(0);

}

System.out
.print("Enter the complete path where file or directory has to be moved: ");

String dest = in.readLine();

if (dest.equals("")) {

System.out.println("Invalid directory or file name.");

System.exit(0);

}

File destination = new File(dest);

if (!destination.exists()) {

System.out
.print("Mentioned directory does not exist. \nDo you want to create a new directory(Y/N)? ");

String chk = in.readLine();

if (chk.equals("Y") || chk.equals("y")) {

destination.mkdir();

copyDirectory(source, destination);

a = 1;

}

else if (chk.equals("N") || chk.equals("n")) {

System.exit(0);

}

else {

System.out.println("Invalid Entry!");

System.exit(0);

}

}

else {

int num = JOptionPane
.showConfirmDialog(null,
"Given file or folder name already exists. \nDo you want to replace now?");

if (num == 0) {

copyDirectory(source, destination);

a = 1;

}

}

if (a == 1) {

System.out.println("File or directory moved successfully.");

if (!delete(source)) {

throw new IOException("Unable to delete original folder");

}

} else if (a == 0) {

System.exit(0);

}

}

public static void copyDirectory(File sourceDir, File destDir)
throws IOException {

if (!destDir.exists()) {

destDir.mkdir();

}

File[] children = sourceDir.listFiles();

for (File sourceChild : children) {

String name = sourceChild.getName();

File destChild = new File(destDir, name);

if (sourceChild.isDirectory()) {

copyDirectory(sourceChild, destChild);

}

else {

copyFile(sourceChild, destChild);

}

}

}

public static void copyFile(File source, File dest) throws IOException {

if (!dest.exists()) {

dest.createNewFile();

}

InputStream in = null;

OutputStream out = null;

try {

in = new FileInputStream(source);

out = new FileOutputStream(dest);

byte[] buf = new byte[1024];

int len;

while ((len = in.read(buf)) > 0) {

out.write(buf, 0, len);

}

}

finally {

in.close();

out.close();

}

}

public static boolean delete(File resource) throws IOException {

if (resource.isDirectory()) {

File[] childFiles = resource.listFiles();

for (File child : childFiles) {

delete(child);

}

}

return resource.delete();

}

}



[b]File object 有个方法叫renameTo[/b], 但这个方法是平台相关的。 我在windows 平台上测试过可以成功。 但没在linux上测试, 所以不清楚这个方法在其它平台上运行的结果。 要是有测试过的朋友, 可以给我留言。 谢谢。
如果可以用这个方法的话, 那方法 copyFile(File source, File dest) 就很简单了, 只需写成:


public static void copyFile(File source, File dest) throws IOException {
source.renameTo(dest);
}



[b]通过NIO的方。[/b]
流移动文件, 有个潜在的性能问题, 主要是缓存的原因。 在实际情况下, 需要优化缓存的大小以达到最优的情况。 一般文件不是很大的情况, 在windons下, 2k比较快。NIO就不需要人为的设置缓存了。 但nio的话, 对于超大文件, 几百M或者上G的话, 性能不是很乐观。 但小文件的话, 如果流的缓存没有配置好。nio 的性能是很快的。下面我们用nio的方式新建一个方法替换 copyFile(File source, File dest):

public static void copyFileWithNIO(File sourceFile, File destFile)
throws IOException {

if (!destFile.exists()) {
destFile.createNewFile();
}

FileChannel source = null;
FileChannel destination = null;
long count = 0;
try {
source = new FileInputStream(sourceFile).getChannel();
long size = source.size();
destination = new FileOutputStream(destFile).getChannel();
while( (count += destination.transferFrom(source, count, size-count)) < size );
} finally {
if (source != null) {
source.close();
}
if (destination != null) {
destination.close();
}
}

}
 

但是, Windows, based on configuration, uses either executes a native copy or does the Stream-based copy. Solaris and AIX always uses the Channel implementation.
所以, 对于移动大文件的话, 最好是用流的方式。 那我们干脆判断一下, 如果是大文件, 就用流, 否则就用nio的方式。 我们对copyDirectory(File sourceDir, File destDir)方法改造下:

public static void copyDirectory(File sourceDir, File destDir)
throws IOException {

if (!destDir.exists()) {

destDir.mkdir();

}

File[] children = sourceDir.listFiles();

for (File sourceChild : children) {

String name = sourceChild.getName();

File destChild = new File(destDir, name);

if (sourceChild.isDirectory()) {

copyDirectory(sourceChild, destChild);

}

else {
long fileSize = sourceChild.length();

// for larger files (20Mb) use streams
if ( fileSize > 20971520l )
copyFile(sourceChild, destChild);
else
copyFileWithNIO (sourceChild, destChild);
}

}

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值