0 0

java文件拷贝的代码改进 0

请看下面的代码,是一个典型的copy文件的例子,我需要一些改进.
现在的情况是,从源文件中读取一部分数据,然后等待输入到目标文件,然后再开始读,一直重复.
这样效率太低,因為只有一個線程在工作,因为每次读完,都要等待写入以后才开始第二次读入.
如何改进呢?我想一個線程读一個線程写,当缓存数组中有数据就写,没有的话就等待读入缓存数组之后再写,這樣可以大大的節約很多時間.代码如何改?



public void copy(File f1,File f2) throws IOException
{ //创建文件输入流对象
FileInputStream rf = new FileInputStream(f1);
FileOutputStream wf = new FileOutputStream(f2);
//创建文件输出流对象
int count,n=512;
byte buffer[] = new byte[n];
count = rf.read(buffer,0,n); //读取输入流
while (count != -1)
{
wf.write(buffer,0,count); //写入输出流
count = rf.read(buffer,0,n);
}
System.out.println("CopyFile "+f2.getName()+" !");
rf.close(); //关闭输入流
wf.close(); //关闭输出流
}
2012年8月31日 09:12

6个答案 按时间排序 按投票排序

0 0

个人认为还是单线程的最快,毕竟瓶颈在io这里。
1. io同一时刻只能读取一块(多磁盘或多磁头或阵列另算)
2. 提升io:磁头的移动尽可能的少(如果多线程争抢io,必然导致磁头频繁动作切换)

目前操作系统都会很好的优化你的磁盘读取的,那么关键是怎样利用OS的磁盘缓存。推荐使用java的直接内存映像操作文件系统。

private static void copy(File src, Path dist) throws IOException {
	if (src.isDirectory()) {
		if (!Files.exists(dist)) Files.createDirectories(dist);
		for (File child : src.listFiles()) {
			copy(child, dist.resolve(child.getName()));
		}
	} else {
		try (FileInputStream fin = new FileInputStream(src); FileOutputStream fout = new FileOutputStream(dist.toFile())) {
			fin.getChannel().transferTo(0, src.length(), fout.getChannel());
		}
	}
}
private static void copy2(File src, Path dist) throws IOException {
	if (src.isDirectory()) {
		if (!Files.exists(dist)) Files.createDirectories(dist);
		for (File child : src.listFiles()) {
			copy(child, dist.resolve(child.getName()));
		}
	} else {
		try (FileInputStream fin = new FileInputStream(src); FileOutputStream fout = new FileOutputStream(dist.toFile())) {
			int len;
			byte[] buf = new byte[2048];
			while ((len = fin.read(buf)) != -1) {
				fout.write(buf, 0, len);
			}
		}
	}
}

2012年8月31日 17:06
0 0

package bluechip.io;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class FileUtils {
	private static final int DEFAULT_BUFFER_SIZE = 8192;

	static class Producer implements Runnable {
		private final BlockingQueue<byte[]> queue;
		private File src;
		private boolean eof;
		private InputStream in;

		Producer(BlockingQueue<byte[]> q, File src) {
			queue = q;
			this.src = src;
		}

		public void run() {
			try {
				while (!eof) {
					queue.put(produce());
				}
			} catch (InterruptedException ex) {
				ex.printStackTrace();
			} catch (IOException ex) {
				ex.printStackTrace();
			}
			System.out.println("Reader done!");
		}

		private InputStream getInputStream() throws FileNotFoundException {
			if (in == null) {
				in = new FileInputStream(src);
			}
			return in;
		}

		byte[] produce() throws FileNotFoundException, IOException {
			byte[] buf = new byte[DEFAULT_BUFFER_SIZE];
			int len = getInputStream().read(buf);
			if (len == -1) {
				eof = true;
				return null;
			} else if (len == DEFAULT_BUFFER_SIZE) {
				return buf;
			} else {
				eof = true;
				byte[] b = new byte[len];
				System.arraycopy(buf, 0, b, 0, len);
				return b;
			}
		}
	}

	static class Consumer implements Runnable {
		private final BlockingQueue<byte[]> queue;
		private File dest;
		private OutputStream out;
		private boolean active;

		Consumer(BlockingQueue<byte[]> q, File dest) {
			queue = q;
			this.dest = dest;
		}

		private OutputStream getOutputStream() throws FileNotFoundException {
			if (out == null) {
				out = new FileOutputStream(dest);
			}
			return out;
		}

		public void run() {
			active = true;
			try {
				while (active) {
					consume(queue.take());
				}
			} catch (InterruptedException ex) {
				ex.printStackTrace();
			} catch (IOException ex) {
				ex.printStackTrace();
			}
			System.out.println("Writer done!");
		}

		void consume(byte[] b) throws FileNotFoundException, IOException {
			if (b == null) {
				active = false;
				return;
			}
			if (b.length < DEFAULT_BUFFER_SIZE) {
				active = false;
			}
			getOutputStream().write(b);
		}
	}

	public static void copyFile(File src, File dest) {
		BlockingQueue<byte[]> q = new ArrayBlockingQueue<byte[]>(10);
		Producer p = new Producer(q, src);
		Consumer c = new Consumer(q, dest);
		Thread t1 = new Thread(p);
		t1.start();
		Thread t2 = new Thread(c);
		t2.start();
		try {
			t1.join();
			t2.join();
		} catch (InterruptedException e) {
		}
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		copyFile(new File("d:/Testing for Non.docx"), new File("d:/1.docx"));
	}
}

2012年8月31日 16:02
0 0

生产者-消费者模式


package bluechip.io;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class FileUtils {
private static final int DEFAULT_BUFFER_SIZE = 8192;

static class Producer implements Runnable {
private final BlockingQueue<byte[]> queue;
private File src;
private boolean eof;
private InputStream in;

Producer(BlockingQueue<byte[]> q, File src) {
queue = q;
this.src = src;
}

public void run() {
try {
while (!eof) {
queue.put(produce());
}
} catch (InterruptedException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
System.out.println("Reader done!");
}

private InputStream getInputStream() throws FileNotFoundException {
if (in == null) {
in = new FileInputStream(src);
}
return in;
}

byte[] produce() throws FileNotFoundException, IOException {
byte[] buf = new byte[DEFAULT_BUFFER_SIZE];
int len = getInputStream().read(buf);
if (len == -1) {
eof = true;
return null;
} else if (len == DEFAULT_BUFFER_SIZE) {
return buf;
} else {
eof = true;
byte[] b = new byte[len];
System.arraycopy(buf, 0, b, 0, len);
return b;
}
}
}

static class Consumer implements Runnable {
private final BlockingQueue<byte[]> queue;
private File dest;
private OutputStream out;
private boolean active;

Consumer(BlockingQueue<byte[]> q, File dest) {
queue = q;
this.dest = dest;
}

private OutputStream getOutputStream() throws FileNotFoundException {
if (out == null) {
out = new FileOutputStream(dest);
}
return out;
}

public void run() {
active = true;
try {
while (active) {
consume(queue.take());
}
} catch (InterruptedException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
System.out.println("Writer done!");
}

void consume(byte[] b) throws FileNotFoundException, IOException {
if (b == null) {
active = false;
return;
}
if (b.length < DEFAULT_BUFFER_SIZE) {
active = false;
}
getOutputStream().write(b);
}
}

public static void copyFile(File src, File dest) {
BlockingQueue<byte[]> q = new ArrayBlockingQueue<byte[]>(10);
Producer p = new Producer(q, src);
Consumer c = new Consumer(q, dest);
Thread t1 = new Thread(p);
t1.start();
Thread t2 = new Thread(c);
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
}
}

/**
* @param args
*/
public static void main(String[] args) {
copyFile(new File("d:/Testing for Non.docx"), new File("d:/1.docx"));
}
}

2012年8月31日 16:02
0 0

在 common-io 2.1.jar 的 源码中, 采用的 方法 是  FileChannel

  /**
     * Internal copy file method.
     * 
     * @param srcFile  the validated source file, must not be <code>null</code>
     * @param destFile  the validated destination file, must not be 
在 common-io 2.1的 源码中提供了一个 copy的 方法 ,采用的  是 
<code>null</code>
     * @param preserveFileDate  whether to preserve the file date
     * @throws IOException if an error occurs
     */
    private static void doCopyFile(File srcFile, File destFile, boolean preserveFileDate) throws IOException {
        if (destFile.exists() && destFile.isDirectory()) {
            throw new IOException("Destination '" + destFile + "' exists but is a directory");
        }

        FileInputStream fis = null;
        FileOutputStream fos = null;
        FileChannel input = null;
        FileChannel output = null;
        try {
            fis = new FileInputStream(srcFile);
            fos = new FileOutputStream(destFile);
            input  = fis.getChannel();
            output = fos.getChannel();
            long size = input.size();
            long pos = 0;
            long count = 0;
            while (pos < size) {
                count = (size - pos) > FILE_COPY_BUFFER_SIZE ? FILE_COPY_BUFFER_SIZE : (size - pos);
                pos += output.transferFrom(input, pos, count);
            }
        } finally {
            IOUtils.closeQuietly(output);
            IOUtils.closeQuietly(fos);
            IOUtils.closeQuietly(input);
            IOUtils.closeQuietly(fis);
        }

        if (srcFile.length() != destFile.length()) {
            throw new IOException("Failed to copy full contents from '" +
                    srcFile + "' to '" + destFile + "'");
        }
        if (preserveFileDate) {
            destFile.setLastModified(srcFile.lastModified());
        }
    }

2012年8月31日 11:20
0 0

觉得没必要多线程。效率低不低是要实验数据来说话的。
小文件加个BufferedReader缓存一下,大文件用NIO就可以了。
或者如楼上所说用commons io。

2012年8月31日 09:19
0 0

建议直接使用 apache的 commons io 工具包  里边有关于io操作的详细工具类;简化开发
如FileUtil

2012年8月31日 09:14

相关推荐

    JAVA上百实例源码以及开源项目源代码

    28个目标文件 内容索引:JAVA源码,媒体网络,飞鸽传书 Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java文件传输实例不可错过,Java网络编程...

    java源码包---java 源码 大量 实例

     Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java文件传输实例不可错过,Java网络编程技能的提升很有帮助。 Java聊天程序,包括服务端和...

    FastCopy 2.01 文件拷贝利器

    而且,作为开源软件,FastCopy的源代码公开,开发者社区会持续改进和维护,确保软件的稳定性和兼容性。 总的来说,无论是日常的工作备份,还是开发者处理大型项目,FastCopy 2.01都能提供强大的文件拷贝支持。它以...

    java源码包3

     Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java文件传输实例不可错过,Java网络编程技能的提升很有帮助。 Java聊天程序,包括服务端和...

    java源码包2

     Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java文件传输实例不可错过,Java网络编程技能的提升很有帮助。 Java聊天程序,包括服务端和...

    成百上千个Java 源码DEMO 4(1-4是独立压缩包)

    28个目标文件 内容索引:JAVA源码,媒体网络,飞鸽传书 Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java文件传输实例不可错过,Java网络编程...

    java源码包4

     Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java文件传输实例不可错过,Java网络编程技能的提升很有帮助。 Java聊天程序,包括服务端和...

    成百上千个Java 源码DEMO 3(1-4是独立压缩包)

    28个目标文件 内容索引:JAVA源码,媒体网络,飞鸽传书 Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java文件传输实例不可错过,Java网络编程...

    java使用nio2拷贝文件的示例

    NIO2引入了许多改进,包括异步文件操作、文件系统感知以及更强大的文件拷贝功能。本示例将详细讲解如何使用Java NIO2来高效地拷贝文件。 首先,我们看到代码中定义了一个名为`MyFiles2`的类,这个类用于实现文件或...

    Postman拷贝下来的代码调通的依赖包.zip

    标题 "Postman拷贝下来的代码调通的依赖包.zip" 提示我们这是一份与Postman相关的代码,可能包含了在Postman中复制的API请求代码,用于在Java环境中调用和测试HTTP接口。描述中的信息进一步确认了这个点,表明这个...

    计算机软件-商业源码-实例089-拷贝文件.zip

    在这个实例089中,我们可以期待看到如何在具体编程环境中实现文件拷贝功能,例如可能的优化策略、错误处理机制以及与其他系统功能(如多线程或网络传输)的整合。不过,由于没有提供具体的源码内容,我们无法深入...

    java class加密保护(完全免费) v2.1

    很容易被反编译工具反编译,而传统的java源代码保护方法基本都是采用混淆的方式, 但这样会带来很多麻烦,而且也不能真正保护class文件, 本工具是对class文件进行加密,采用jni的方式解密运行, 加密算法达到256位...

    JDK1.7 无需安装,拷贝直接用

    JDK1.7,即Java SE 7,是Oracle公司发布的一个重要版本,它在Java 6的基础上引入了许多新特性和改进,对开发者来说具有重要意义。 标题中的“JDK1.7 无需安装,拷贝直接用”指的是这个版本的JDK可以直接解压使用,...

    java 复数程序源代码

    根据提供的文件信息,我们可以深入分析并提取出与Java复数程序相关的知识点: ### 1. 复数类的定义 #### (1)基础版本 `Complex` 类定义 ```java public class Complex { double real, imag; // 实部和虚部 ...

    拷贝文件夹

    - **日志记录**:为了更好地跟踪程序运行情况,可以在程序中加入日志记录功能,记录文件拷贝的状态和进度。 - **界面交互**:如果是在桌面应用中使用,可以添加图形界面,提供更友好的用户交互体验。 综上所述,...

    java类加密工具v2.1

    很容易被反编译工具反编译,而传统的java源代码保护方法基本都是采用混淆的方式, 但这样会带来很多麻烦,而且也不能真正保护class文件, 本工具是对class文件进行加密,采用jni的方式解密运行, 加密算法达到256位...

    java1.7 特性实现

    之前的版本中,字符串连接通常涉及多次内存分配和拷贝,而Java 7改进了字符串连接性能,当字符串数量较少时,使用StringBuilder优化内部实现。 5. **增强的for循环(遍历数组和集合)** Java 7允许在for-each循环...

    我心飞扬java类加密工具2.1(亲测可用)

    众所周知,java编译后的class文件是一种中间字节字文件,很容易被反编译工具反编译,而传统的java源代码保护方法基本都是采用混淆的方式,但这样会带来很多麻烦,而且也不能真正保护class文件,本工具是对class文件...

    总结java的算法之2

    文件中的“公共交换乘乘算法.java”可能是一种改进的搜索或交换算法。 4. **文件操作与配置文件读取**:“加载并读取配置文件.java”和“加载并读取配置文件例子【DBCon】.java”涉及到的是I/O流和资源管理,Java的...

    cpp-Lua533和LuaJava移植至Android的示例

    首先,Lua 5.3.3是Lua语言的一个版本,它提供了一些新特性,比如改进的数字处理、元表的隐式拷贝以及新的语法结构。在Android中使用Lua,我们需要将它的源码编译为适用于Android的二进制库。这通常涉及到使用Android...

Global site tag (gtag.js) - Google Analytics