如何在c / c ++中将文件从一个目录复制到另一个目录

时间:2011-09-01 07:37:25

标签: c++ c file-io

我正在寻找一个关于如何在C中将文件从一个目录复制到另一个目录的简单示例。该程序应该只使用C本机的跨平台函数。

7 个答案:

答案 0 :(得分:6)

这是一个简单的未经测试的C程序,可以满足您的需求:

#include <stdio.h>

int main(int argn, char * argv[]) {

    int src_fd, dst_fd, n, err;
    unsigned char buffer[4096];
    char * src_path, dst_path;

    // Assume that the program takes two arguments the source path followed
    // by the destination path.

    if (argn != 3) {
        printf("Wrong argument count.\n");
        exit(1);
    }

    src_path = argv[1];
    dst_path = argv[2];

    src_fd = open(src_path, O_RDONLY);
    dst_fd = open(dst_path, O_CREAT | O_WRONLY);

    while (1) {
        err = read(src_fd, buffer, 4096);
        if (err == -1) {
            printf("Error reading file.\n");
            exit(1);
        }
        n = err;

        if (n == 0) break;

        err = write(dst_fd, buffer, n);
        if (err == -1) {
            printf("Error writing to file.\n");
            exit(1);
        }
    }

    close(src_fd);
    close(dst_fd);
}

答案 1 :(得分:4)

open source file read-only
create destination file for write
while there's still data in source file
    read data from source file
    write it to destination file
close both files

我相信你能做到!

答案 2 :(得分:2)

下面是使用dirent.h在C ++中复制文件的正确方法。请注意,dirent.h是Linux的一部分,但不包含在Windows中。对于Windows,请查看here

对于Windows Visual C ++:

 // CopyAll_Windows.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include<stdio.h>
#include"dirent.h"   //Copy dirent.h to folder where stdafx.h is and add to project
#include<errno.h>
#include<sys/stat.h>
#include <iostream>

#define MAX 1024
#define MAX_FILE_NAME_LEN 256

using namespace std;

int main()
{
    string homedir = "C:\\Users\\Tom\\Documents";
    cerr << endl << "Home =  " << homedir.c_str() << endl;
    string SrcPath = homedir + "\\Source 1";
    string DestPath = homedir + "\\Dest 1\\Dest 1";
    string DestPath_mkdir = "\"" + DestPath + "\"";
    string command = "mkdir " + DestPath_mkdir;
    cerr << endl << "Command = " << command.c_str() << endl << endl;
    system(command.c_str());
    const char *arSrcPath = SrcPath.c_str();
    const char *arDestPath = DestPath.c_str();

    struct dirent* spnDirPtr;    /* struct dirent to store all files*/
    DIR* pnWriteDir = NULL;    /*DIR Pointer to open Dir*/
    pnWriteDir = opendir(arDestPath);

    if (!pnWriteDir)
        cerr << endl << "ERROR! Write Directory can not be open" << endl;

    DIR* pnReadDir = NULL;    /*DIR Pointer to open Dir*/
    pnReadDir = opendir(arSrcPath);

    if (!pnReadDir || !pnWriteDir)
        cerr << endl << "ERROR! Read or Write Directory can not be open" << endl << endl;

    else
    {
        int nErrNo = 0;

        while ((spnDirPtr = readdir(pnReadDir)) != NULL)
        {
            char readPath[MAX_FILE_NAME_LEN] = { 0 };
            memset(readPath, 0, MAX_FILE_NAME_LEN);

            // Following line needed to get real path for "stat" call
            _snprintf_s(readPath, MAX_FILE_NAME_LEN, _TRUNCATE, "%s/%s", arSrcPath, spnDirPtr->d_name);
            struct stat st_buf;
            stat(readPath, &st_buf);

            if (S_ISDIR(st_buf.st_mode))
            {
                cerr << endl << "Reading directory here..." << endl;
                continue;
            }
            else if (S_ISREG(st_buf.st_mode))
            {
                if (nErrNo == 0)
                    nErrNo = errno;

                cerr << endl << "Now reading and writing file " << spnDirPtr->d_name << endl;
                char strSrcFileName[MAX_FILE_NAME_LEN] = { 0 };
                memset(strSrcFileName, 0, MAX_FILE_NAME_LEN);

                // Following line needed to get real path for "pnReadFile"
                _snprintf_s(strSrcFileName, MAX_FILE_NAME_LEN, _TRUNCATE, "%s/%s", arSrcPath, spnDirPtr->d_name);

                FILE* pnReadFile;
                errno_t err_read;

                if ((err_read = fopen_s(&pnReadFile, strSrcFileName, "r")) == 0)
                {
                    cerr << endl << "Now reading file " << strSrcFileName << endl;
                    char strDestFileName[MAX_FILE_NAME_LEN] = { 0 };
                    memset(strDestFileName, 0, MAX_FILE_NAME_LEN);

                    // Following line needed to get real path for "pnWriteFile"
                    _snprintf_s(strDestFileName, MAX_FILE_NAME_LEN, _TRUNCATE, "%s/%s", arDestPath, spnDirPtr->d_name);

                    FILE* pnWriteFile;  /*File Pointer to write in file*/
                    errno_t err_write;

                    if ((err_write = fopen_s(&pnWriteFile, strDestFileName, "w")) == 0)
                    {
                        cerr << endl << "Now writing file " << strDestFileName << endl;
                        char buffer[MAX] = { 0 };    /*Buffer to store files content*/

                        while (fgets(buffer, MAX, pnReadFile))
                        {
                            fputs(buffer, pnWriteFile);
                        }
                        fclose(pnWriteFile);
                    }
                    else
                    {
                        cerr << endl << "Error! Unable to open file for writing " << strDestFileName << endl;
                    }
                    fclose(pnReadFile);
                }
                else
                {
                    cerr << endl << "ERROR! File Could not be open for reading" << endl;
                }
            }
        }
        if (nErrNo != errno)
            cerr << endl << "ERROR Occurred!" << endl;
        else
            cerr << endl << "Process Completed" << endl << endl;
    }
    closedir(pnReadDir);
    closedir(pnWriteDir);

    return 0;
}

对于Linux Eclipse C ++:

// CopyAll_linux.cpp : Defines the entry point for the console application.
//

//#include "stdafx.h"
#include<stdio.h>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<dirent.h>
#include<errno.h>
#include<sys/stat.h>
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>

#define MAX 1024
#define MAX_FILE_NAME_LEN 256

using namespace std;

int main()
{
    const char *homedir;
    if ((homedir = getenv("HOME")) == NULL) {
        homedir = getpwuid(getuid())->pw_dir;
    }
    cerr << endl << "Home =  " <<  homedir << endl;
    string hd(homedir);
    string SrcPath = hd + "/Source 1";
    string DestPath = hd + "/Dest 1/Dest 1";
    string DestPath_mkdir = "\"" + DestPath + "\"";
    string command = "mkdir -p " + DestPath_mkdir;
    cerr << endl << "Command = " <<  command.c_str() << endl << endl;
    system(command.c_str());
    const char *arSrcPath = SrcPath.c_str();
    const char *arDestPath = DestPath.c_str();

    struct dirent* spnDirPtr;    /* struct dirent to store all files*/
    DIR* pnWriteDir = NULL;    /*DIR Pointer to open Dir*/
    pnWriteDir = opendir(arDestPath);

    if (!pnWriteDir)
        cerr << endl << "ERROR! Write Directory can not be open" << endl;

    DIR* pnReadDir = NULL;    /*DIR Pointer to open Dir*/
    pnReadDir = opendir(arSrcPath);

    if (!pnReadDir || !pnWriteDir)
        cerr << endl <<"ERROR! Read or Write Directory can not be open" << endl << endl;

    else
    {
        int nErrNo = 0;

        while ((spnDirPtr = readdir(pnReadDir)) != NULL)
        {
            char readPath[MAX_FILE_NAME_LEN] = { 0 };
            memset(readPath, 0, MAX_FILE_NAME_LEN);
            // Following line needed to get real path for "stat" call
            snprintf(readPath, MAX_FILE_NAME_LEN, "%s/%s", arSrcPath, spnDirPtr->d_name);
            struct stat st_buf;
            stat(readPath, &st_buf);

            if (S_ISDIR(st_buf.st_mode))
            {
                cerr << endl << "Reading directory here..." << endl;
                continue;
            }
            else if (S_ISREG(st_buf.st_mode))
            {
                if (nErrNo == 0)
                    nErrNo = errno;

                cerr << endl << "Now reading and writing file "<< spnDirPtr->d_name << endl;
                char strSrcFileName[MAX_FILE_NAME_LEN] = { 0 };
                memset(strSrcFileName, 0, MAX_FILE_NAME_LEN);
                // Following line needed to get real path for "pnReadFile"
                snprintf(strSrcFileName, MAX_FILE_NAME_LEN, "%s/%s", arSrcPath, spnDirPtr->d_name);
                FILE* pnReadFile;
                pnReadFile = fopen(strSrcFileName, "r");

                if (pnReadFile == NULL)
                    cerr << endl << "Null pointer on read file ..." << endl;

                if (pnReadFile)
                {
                    cerr << endl << "Now reading file " << strSrcFileName << endl;
                    char strDestFileName[MAX_FILE_NAME_LEN] = { 0 };
                    memset(strDestFileName, 0, MAX_FILE_NAME_LEN);
                    // Following line needed to get real path for "pnWriteFile"
                    snprintf(strDestFileName, MAX_FILE_NAME_LEN, "%s/%s", arDestPath, spnDirPtr->d_name);
                    FILE* pnWriteFile = fopen(strDestFileName, "w");    /*File Pointer to write in file*/

                    if (pnWriteFile)
                    {
                        cerr << endl << "Now writing file " << strDestFileName << endl;
                        char buffer[MAX] = { 0 };    /*Buffer to store files content*/

                        while (fgets(buffer, MAX, pnReadFile))
                        {
                            fputs(buffer, pnWriteFile);
                        }
                        fclose(pnWriteFile);
                    }
                    else
                    {
                        cerr << endl << "Error! Unable to open file for writing " << strDestFileName << endl;
                    }
                    fclose(pnReadFile);
                }
                else
                {
                    cerr << endl << "ERROR! File Could not be open for reading" << endl;
                }
            }
        }
        if (nErrNo != errno)
            cerr << endl << "ERROR Occurred!" << endl;
        else
            cerr << endl << "Process Completed" << endl << endl;
    }
    closedir(pnReadDir);
    closedir(pnWriteDir);

    return 0;
}

Visual Studio C ++ dll:

 // copy_all_dll.cpp : Defines the exported functions for the DLL application.
//

#include "stdafx.h"
#include<stdio.h>
#include"dirent.h"   //Copy dirent.h to folder where stdafx.h is and add to project
#include<errno.h>
#include<sys/stat.h>
#include <iostream>

#define MAX 1024
#define MAX_FILE_NAME_LEN 256

using namespace std;

BOOL DirectoryExists(const char* dirName);

extern "C"  __declspec(dllexport) char*  copy_combos_all(char *source, char *dest)

{
    char *pnError = "";

    BOOL dest_exists = DirectoryExists(dest);

    if (!dest_exists)
    {
        string DestPath(dest);
        DestPath = "\"" + DestPath + "\"";
        string command = "mkdir " + DestPath;
        system(command.c_str());
    }

    const char *arSrcPath = source;
    const char *arDestPath = dest;

    struct dirent* spnDirPtr;    /* struct dirent to store all files*/
    DIR* pnWriteDir = NULL;    /*DIR Pointer to open Dir*/
    pnWriteDir = opendir(arDestPath);
    if (!pnWriteDir)
    {
        pnError =  "ERROR! Write Directory can not be open";
        return pnError;
    }
    DIR* pnReadDir = NULL;    /*DIR Pointer to open Dir*/
    pnReadDir = opendir(arSrcPath);

    if (!pnReadDir) 
    {
        pnError = "ERROR! Read Directory can not be open";
        if (pnWriteDir)
        {
            closedir(pnWriteDir);
        }
        return pnError;
    }
    else
    {
        int nErrNo = 0;

        while ((spnDirPtr = readdir(pnReadDir)) != NULL)
        {
            char readPath[MAX_FILE_NAME_LEN] = { 0 };
            memset(readPath, 0, MAX_FILE_NAME_LEN);

            // Following line needed to get real path for "stat" call
            _snprintf_s(readPath, MAX_FILE_NAME_LEN, _TRUNCATE, "%s/%s", arSrcPath, spnDirPtr->d_name);
            struct stat st_buf;
            stat(readPath, &st_buf);

            if (S_ISDIR(st_buf.st_mode))
            {
                continue;
            }
            else if (S_ISREG(st_buf.st_mode))
            {
                if (nErrNo == 0)
                    nErrNo = errno;

                char strSrcFileName[MAX_FILE_NAME_LEN] = { 0 };
                memset(strSrcFileName, 0, MAX_FILE_NAME_LEN);

                // Following line needed to get real path for "pnReadFile"
                _snprintf_s(strSrcFileName, MAX_FILE_NAME_LEN, _TRUNCATE, "%s/%s", arSrcPath, spnDirPtr->d_name);

                FILE* pnReadFile;
                errno_t err_read;

                if ((err_read = fopen_s(&pnReadFile, strSrcFileName, "r")) == 0)
                {
                    char strDestFileName[MAX_FILE_NAME_LEN] = { 0 };
                    memset(strDestFileName, 0, MAX_FILE_NAME_LEN);

                    // Following line needed to get real path for "pnWriteFile"
                    _snprintf_s(strDestFileName, MAX_FILE_NAME_LEN, _TRUNCATE, "%s/%s", arDestPath, spnDirPtr->d_name);

                    FILE* pnWriteFile;
                    errno_t err_write;

                    if ((err_write = fopen_s(&pnWriteFile, strDestFileName, "w")) == 0)    /*File Pointer to write in file*/
                    {
                        char buffer[MAX] = { 0 };    /*Buffer to store files content*/

                        while (fgets(buffer, MAX, pnReadFile))
                        {
                            fputs(buffer, pnWriteFile);
                        }
                        fclose(pnWriteFile);
                    }
                    else
                    {
                        pnError = "Error! Unable to open file for writing ";
                        return pnError;
                    }
                    fclose(pnReadFile);
                }
                else
                {
                    pnError = "ERROR! File Could not be open for reading";
                    return pnError;
                }
            }
        }
        if (nErrNo != errno)
        {
            pnError = "ERROR Occurred!";
        }
        else
        {
            pnError = "Process Completed";
        }
    }
    if (pnReadDir)
    {
        closedir(pnReadDir);
    }
    if (pnWriteDir)
    {
        closedir(pnWriteDir);
    }

    return pnError;
}

BOOL DirectoryExists(const char* dirName) {
    DWORD attribs = ::GetFileAttributesA(dirName);
    if (attribs == INVALID_FILE_ATTRIBUTES) {
        return false;
    }
    return (attribs & FILE_ATTRIBUTE_DIRECTORY);
}

对于dll,你打电话给它如下:

VB.Net:

<DllImport("copy_all.dll", CallingConvention:=CallingConvention.Cdecl)>
Public Shared Function copy_all(source As String, dest As String) As StringBuilder
End Function

Sub copyAll()

    Dim source, dest, homedir As String
    homedir = System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
    source = homedir & "\Source"
    dest = homedir & "\Dest"

    If Not My.Computer.FileSystem.DirectoryExists(dest) Then
        My.Computer.FileSystem.CreateDirectory(dest)
    End If

    Dim errorMessage As String
    errorMessage = ""
    Dim sb As New StringBuilder()
    sb = copy_all(source, dest)
    errorMessage = sb.ToString

    If (errorMessage <> "") Then
        MessageBox.Show(errorMessage)
    End If


End Sub

Visual C#:

[DllImport("copy_all.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr copy_all(string source, string dest);

public void copyAll()
{

    string homedir = System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
    string source = homedir + "\\Source";
    string dest = homedir + "\\Dest";
    string error = "";

    if (!Directory.Exists(dest))
        Directory.CreateDirectory(dest);

    IntPtr ptr = copy_all(source, dest);

    error = Marshal.PtrToStringAnsi(ptr);

    if (error != "")

        MessageBox.Show(error);

}

答案 3 :(得分:1)

@Mu Qiao提到boost::filesystem。具体来说,您需要查找copy_file的示例,但您也可以复制目录。

如果您对使用异步I / O感兴趣,我的印象是boost::asio有一些有趣的实现,利用平台功能让您在等待磁盘时使用CPU,就像它一样为网络做的:

How to perform Cross-Platform Asynchronous File I/O in C++

(注意:最近asio库已经开始考虑了很多,但我总是要提供免责声明,我没有在项目中使用它,并且不知道它的局限性是什么所以我带着一点点盐就提到了它。)

还有其他跨平台的库提供这种功能,如果你愿意做买入,总是需要品味和需求。我自己喜欢Qt有很多原因,它确实提供了QFile::copy方法:

http://doc.qt.nokia.com/latest/qfile.html#copy

答案 4 :(得分:1)

/*
 *
 * Module    : Copy Multiple from Src dir to Dest dir
 * Author    : Mohd Asif
 * Date     : 12-March-2013
 * Description    : This code will copy all the files from Src dir to Dest Dir 
 *    instead of onother directory inside src dir
 * */

#include<stdio.h>
#include<stdio.h>
#include<dirent.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/stat.h>
#define MAX 1024

int main()
{
    char    arSrcPath[]    = "/home/mpe4/Src";    /*Source directory path*/
    char    arDestPath[]    = "/home/mpe4/Dest";    /*dest directory path*/
    struct    dirent* spnDirPtr;    /* struct dirent to store all files*/

    DIR* pnOpenDir = NULL;    /*DIR Pointer to open Dir*/
    DIR* pnReadDir = NULL;    /*DIR POinter to read directory*/

    pnOpenDir = opendir(arSrcPath); 

    if(!pnOpenDir)
    printf("\n ERROR! Directory can not be open");

    else
    {    
    int nErrNo = 0;
    while(spnDirPtr = readdir(pnOpenDir))
    {
        if(nErrNo == 0)
        nErrNo = errno;
        printf("\n Now writing %s file...",spnDirPtr->d_name);

        printf("\n dest file name = %s/%s\n", arDestPath, spnDirPtr->d_name);

        struct stat st_buf;
        stat(spnDirPtr->d_name, &st_buf);
        if (S_ISDIR (st_buf.st_mode))
        {
            continue;
        }
        else if (S_ISREG (st_buf.st_mode))
        {
            FILE* pnReadFile = fopen(spnDirPtr->d_name,"r");

            if(pnReadFile)
            {
                printf("\n Now reading %s file...",spnDirPtr->d_name);

                char strDestFileName[MAX] = {0};
                sprintf(strDestFileName, "%s/%s", arDestPath, spnDirPtr->d_name);
                printf("\n dest file name = %s\n", strDestFileName);

                FILE* pnWriteFile  = fopen(strDestFileName, "w");    /*File Pointer to write in file*/
                if(pnWriteFile)
                {
                    char buffer[MAX] = {0};    /*Buffer to store files content*/

                        while(fgets(buffer, MAX, pnReadFile))
                        {
                            fputs(buffer, pnWriteFile);
                        }
                    fclose(pnWriteFile);
                }
            else
            {
                printf("\n Unable to open file %s", strDestFileName);
            }
            fclose(pnReadFile);
    }
    else
    {
        printf ("\nERROR! File Could not be open for reading");
    }
    }
    }
    if(nErrNo != errno)
        printf ("\nERROR Occurred!\n");
    else
        printf ("\nProcess Completed\n");

    }
    closedir(pnOpenDir);
    return 0;
}    

答案 5 :(得分:0)

另一种选择是这样的:

#ifdef SOME_OS
  #define COPY_STR "copy %s %s"  // some sort of OS-specific syntax

#elif defined SOME_OTHER_OS
  #define COPY_STR "%s cpy %s"   // some sort of OS-specific syntax

#else
  #error "error text"
#endif

...

#include <stdio.h>   //sprintf()
#include <stdlib.h>  //system()

char copy_str[LARGE_ENOUGH];
char* source;
char* dest;
...

sprintf (copy_str, COPY_STR, source, dest);
system (copy_str);

答案 6 :(得分:0)

我对@ te7回答做了一些更改,只在MAC上将一个文件从一个文件夹复制到另一个文件夹。我试图修改他的代码只是复制一个文件,但它部分写入文件到目的地。所以我使用不同的代码进行文件读/写

void copyFile(string srcDirPath, string destDirPath, string fileName)
{


string command = "mkdir -p " + destDirPath;
cerr << endl << "Command = " <<  command.c_str() << endl << endl;
system(command.c_str());


DIR* pnWriteDir = NULL;    /*DIR Pointer to open Dir*/
pnWriteDir = opendir(destDirPath.c_str());

if (!pnWriteDir)
    cerr << endl << "ERROR! Write Directory can not be open" << endl;

DIR* pnReadDir = NULL;    /*DIR Pointer to open Dir*/
pnReadDir = opendir(srcDirPath.c_str());

if (!pnReadDir || !pnWriteDir)
    cerr << endl <<"ERROR! Read or Write Directory can not be open" << endl << endl;

else
{
    string srcFilePath = srcDirPath + fileName;
    const char * strSrcFileName = srcFilePath.c_str();
    fstream in, out;
    in.open(strSrcFileName, fstream::in|fstream::binary);

    if (in.is_open()) {
        cerr << endl << "Now reading file " << strSrcFileName << endl;

        string destFilePath = destDirPath + fileName;
        const char * strDestFileName = destFilePath.c_str();
        out.open(strDestFileName, fstream::out);

        char tmp;
        while(in.read(&tmp, 1))
        {
            out.write(&tmp, 1);
        }
        out.close();
        in.close();
    }
    else
        cerr << endl << "ERROR! File Could not be open for reading" << endl;
}
closedir(pnReadDir);
closedir(pnWriteDir);
}