如何在不依赖平台的情况下使用C语言复制文件?

9

看起来这个问题很简单,但我找不到没有平台依赖的在C语言下复制文件的明确解决方案。

在我的开源项目中,我使用了system()调用来创建目录、复制文件和运行外部程序。它在Mac OS X和其他类Unix系统上运行得非常好,但在Windows上失败了。问题出在:

system( "cp a.txt destination/b.txt" );
  • Windows使用反斜杠作为路径分隔符。(Unix中使用斜杠)
  • Windows使用'copy'来表示内部复制命令。(Unix中使用cp)

如何编写一个不依赖于其他代码的复制命令?

(实际上,我曾经用宏解决这个问题,但是这并不酷。参考:http://code.google.com/p/npk/source/browse/trunk/npk/cli/tests/testutil.h, L22-56 )


问题并不是像我之前提到的那样在“复制”上悬挂。 - lqez
3个回答

9
system()函数带来的麻烦远大于其价值,它会在一个单独的进程中调用shell,并且通常应该避免使用。
相反,用fopen()打开a.txtdest/b.text文件,并使用getc()/putc()进行复制(因为标准库更有可能执行页面对齐缓冲,比你写的程序更高效)。
FILE *src = fopen("a.txt", "rb");
FILE *dst = fopen("dest/b.txt", "wb");
int i;
for (i = getc(src); i != EOF; i = getc(src))
{
    putc(i, dst);
}
fclose(dst);
fclose(src);

谢谢您的回答。但是它并没有解决路径分隔符问题。 - lqez
1
根据http://msdn.microsoft.com/en-us/library/77859s1t(v=VS.71).aspx的说法,路径分隔符是“system()”问题,而不是“fopen()”问题。这是由于shell调用在系统中失败了。 - Dave
@Dave:那些应该是fclose()调用吧? - 0xC0000022L

6

您需要使用C标准库函数中的stdio.h

特别地,fopenfreadfwritefclose足够使用。

请确保在fopen标志中包含b(二进制)选项。

[编辑]

不幸的是,文件名本身(斜杠 vs 反斜杠)仍然与平台有关。因此,您需要一些类似于#ifdef的东西来处理它。

或者您可以使用跨平台工具包


2
由于目录组织是特定于平台的,因此没有完全简单的方法。但是,在API级别上,Windows接受路径名中的斜杠或反斜杠(cmd.exe shell需要反斜杠)。因此,只要您的Unix名称不包含反斜杠(可能也不包含冒号),您就可以使用。 - Jonathan Leffler
@Jonathan:好的,我承认我不知道这个。那么对于在Windows上合法的带有斜杠的文件名呢?也许我应该试一下 :-) - Nemo
斜杠被视为目录分隔符;在Windows上,路径名组件不能包含斜杠(或反斜杠)。冒号与驱动器字母(C:\Program Files\SomeThing)、特殊设备:NUL以及备用数据流或“资源叉”一起使用。 - Jonathan Leffler
2
这是因为经典的 Mac 没有使用 / 作为分隔符,而是使用 ":"。如果你阅读 http://en.wikipedia.org/wiki/Filename ,你会发现有很多保留字符是你从未想到过的! - user539810
1
@lqez:fopen等不仅仅是POSIX的一部分,它们也是C标准本身的一部分。因此它们非常易于移植。(尽管我不认为C标准提供了创建目录的任何方法。) - Nemo
显示剩余3条评论

0

使用标准的C库stdio.h。首先使用fopen(inputFilename, "rb")打开输入文件以进行读取,并使用fopen(outputFilename, "wb")打开输出文件以进行写入,使用freadfwrire复制内容。最后使用fclose关闭两个文件。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接