我正在为Linux编写一个SDL应用程序,它可以在控制台上运行(没有X服务器)。我的一个功能是文件复制机制,它将特定文件从HDD复制到USB闪存设备,并在UI中显示此副本的进度。为此,我使用简单的while循环并通过8kB块复制文件以获得复制进度。问题是,它很慢。我将在近10分钟内复制一个100 MB的文件,这是不可接受的。
如何实现更快的文件复制?我正在考虑一些异步API,它会将文件从HDD读取到缓冲区并将数据存储到USB中的单独线程,但我不知道我是否应该自己实现,因为它看起来不是一件容易的事。也许你知道一些C ++ API /库可以帮我吗?或者其他一些更好的方法?
答案 0 :(得分:4)
答案 1 :(得分:4)
不要使用复制进度同步更新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
请注意,如果要将文件发送到套接字而不是另一个文件,则应该使用sendfile(2)
系统调用,该调用直接在内核空间中复制文件而不进行往返进入用户空间。当然,如果你这样做,你就无法获得任何进度信息,因此可能并不总是理想的。
对于Windows系统,您应该使用CopyFileEx
,这既有效又可以为您提供进度回调例程。