不要与复制进度同步更新您的 UI,这会大大减慢速度。您应该在与主 UI 线程不同的线程上运行文件复制,以便文件复制可以尽可能快地进行,而不会影响应用程序的响应能力。然后,UI 可以以自然速率(例如以显示器的刷新速率)进行自我更新。
您还应该使用大于 8 KB 的缓冲区大小。尝试一下,但我认为使用更大的缓冲区大小(例如在 64-128 KB 范围内)您会获得更快的结果。
所以,它可能看起来像这样:
#define BUFSIZE (64*1024)
volatile off_t progress, max_progress;
void *thread_proc(void *arg)
{
// Error checking omitted for expository purposes
char buffer[BUFSIZE];
int in = open("source_file", O_RDONLY);
int out = open("destination_file", O_WRONLY | O_CREAT | O_TRUNC);
// Get the input file size
struct stat st;
fstat(in, &st);
progress = 0;
max_progress = st.st_size;
ssize_t bytes_read;
while((bytes_read = read(in, buffer, BUFSIZE)) > 0)
{
write(out, buffer, BUFSIZE);
progress += bytes_read;
}
// copy is done, or an error occurred
close(in);
close(out);
return 0;
}
void start_file_copy()
{
pthread_t t;
pthread_create(&t, NULL, &thread_proc, 0);
}
// In your UI thread's repaint handler, use the values of progress and
// max_progress
请注意,如果您要将文件发送到socket而不是另一个文件,您应该使用sendfile(2) http://linux.die.net/man/2/sendfile系统调用,直接在内核空间中复制文件,而无需往返用户空间。当然,如果您这样做,您将无法获得任何进度信息,因此这可能并不总是理想的。
对于 Windows 系统,您应该使用CopyFileEx http://msdn.microsoft.com/en-us/library/aa363852%28v=VS.85%29.aspx,这既高效又为您提供进度回调例程。