Правильный способ копирования файлов в C ++ с использованием dirent.h приведен ниже. Обратите внимание, что dirent.h является частью Linux, но не включен в Windows. Для Windows смотрите здесь .
Для 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);
}