0

How can I copy folders to a directory?

I tried almost everything but I cant manage it to work.

I got examples from other questions but nothing is working.

When I tried to let my application copy a folder it gives me an error:

File does not exist: C:\Users\Loko\Desktop\dir1\New folder (5)

At this line:

Stopwatch stopwatch = Stopwatch.StartNew();

Which probably has nothing to do with it. Anyway can anyone help me? There is just a problem with the folders.

This is my code:

    using System;
    using System.IO;
    using System.Configuration;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Diagnostics;
    using System.Threading;
    using System.Windows.Forms;
    using MySql.Data.MySqlClient;

    namespace ChaloSync
    {
    public partial class Form1 : Form
    {
        private bool pause = false;
        String source = ConfigurationManager.AppSettings[@"Directory1"];
        String target = ConfigurationManager.AppSettings[@"Directory2"];



        public static bool WaitForFileAvailable(string filePath, TimeSpan timeout)
        {
            if (!File.Exists(filePath))
                throw new InvalidOperationException("File does not exist: " + filePath);

            Stopwatch stopwatch = Stopwatch.StartNew();

            while (stopwatch.Elapsed <= timeout)
            {
                try
                {
                    using (new FileStream(filePath, FileMode.Open, FileAccess.Read))
                    {
                        return true;
                    }
                }

                catch { }

                Thread.Sleep(250);
            }

            return false;
        }


        public Form1()
        {
            InitializeComponent();
        }

        static void config()
        {
            foreach (string key in ConfigurationManager.AppSettings)
            {
                string value = ConfigurationManager.AppSettings[key];
                MessageBox.Show(value);
            }
        }

        private void fileSystemWatcher1_Changed(object sender, System.IO.FileSystemEventArgs e)
        {
                listBox1.Items.Add("File changed> " + e.FullPath + " -Date:" + DateTime.Now);
        }

        private void fileSystemWatcher1_Created(object sender, System.IO.FileSystemEventArgs e)
        {
            if (WaitForFileAvailable(e.FullPath, TimeSpan.FromSeconds(10)))
            {
                listBox1.Items.Add("File created> " + e.FullPath + " -Date:" + DateTime.Now);
                File.Copy(e.FullPath, Path.Combine(target, e.Name));
                Directory.GetFiles(e.FullPath, Path.Combine(target, e.Name));
            }
            else // The file failed to become available within 10 seconds.
            {
                // Error handling.
            }
            }

        private void fileSystemWatcher1_Deleted(object sender, System.IO.FileSystemEventArgs e)
        {

                listBox1.Items.Add("File deleted> " + e.FullPath + " -Date:" + DateTime.Now);
                File.Delete(target + e.Name);

        }

        private void fileSystemWatcher1_Renamed(object sender, System.IO.RenamedEventArgs e)
        {
                listBox1.Items.Add("File renamed> " + e.FullPath + " -Date:" + DateTime.Now);
        }

        private void Start_Click(object sender, EventArgs e)
        {
            fileSystemWatcher1.Path = source;
            fileSystemWatcher1.EnableRaisingEvents = false;
            fileSystemWatcher1.EnableRaisingEvents = true;   
            if (!pause)
            {
                pause = true;
                Start.Text = "Pause";

            }
            else
            {
                pause = false;
                Start.Text = "Start";


            }

        }

    }
}

5 Answers5

3

You throw exception explicitly:

 if (!File.Exists(filePath))
            throw new InvalidOperationException("File does not exist: " + filePath);

File.Exists return false, because you check file and file is not directory. You can try

Directory.Exists(filePath) || File.Exists(filePath)

to ensure that path exists.

Tommi
  • 3,199
  • 1
  • 24
  • 38
  • Where should i place this? –  Jun 20 '13 at 11:46
  • In place where you check file on existense ` if (!File.Exists(filePath))` However, your copying code don't use file system api, you read and write streams instead. You can't copy folder in this way. Check @Paul Zahra answer to get right direction. – Tommi Jun 20 '13 at 11:50
2

Judging by the error message you are throwing the path does not exist.

To copy an entire directory use the following:

string sourcePath = @"C:\Users\Public\TestFolder";
string targetPath =  @"C:\Users\Public\TestFolder\SubDir";

if (System.IO.Directory.Exists(sourcePath))
{
    string[] files = System.IO.Directory.GetFiles(sourcePath);

    // Copy the files and overwrite destination files if they already exist. 
    foreach (string s in files)
    {
       // Use static Path methods to extract only the file name from the path.
       fileName = System.IO.Path.GetFileName(s);
       destFile = System.IO.Path.Combine(targetPath, fileName);
       System.IO.File.Copy(s, destFile, true);
    }
}
else
{
    Console.WriteLine("Source path does not exist!");
}

See this MSDN page for more information

Edit: As Tommi says: use File.Exists to check if a file exists... use Directory.Exists to check if a path is a valid folder / directory.

Edit2: This is a useful function:

internal static bool FileOrDirectoryExists(string name)
{
   return (Directory.Exists(name) || File.Exists(name))
}

Edit3: To check if it's a permissions issue take a look at this which contains some simple code to differentiate between Directory Exists and Access Permissions

Paul Zahra
  • 9,522
  • 8
  • 54
  • 76
  • this doesn't work. There is something wrong with the timer. the timer should only apply when i am using a file but it's crashing when i use a folder. –  Jun 20 '13 at 11:45
  • It seems your real issue is you are confusing files with directories throughout your code. – Paul Zahra Jun 20 '13 at 11:52
  • Can you please help me with my code cause right now i am so stuck. I have no idea how to change it so it checks if its a file or a folder. I dont know where to put it in my code. Im really stuck right now. –  Jun 20 '13 at 11:55
  • for a start, use the function I put in Edit2 above and instead of if (!File.Exists(filePath)) use if (!FileOrDirectoryExists(filePath)) – Paul Zahra Jun 20 '13 at 12:10
  • I suspect that the directory is innaccessible due to permissions... test it with a public folder – Paul Zahra Jun 20 '13 at 13:40
1

This line is wrong.

Directory.GetFiles(e.FullPath, Path.Combine(target, e.Name));

The first parameter should be a path not a path with a file, the second parameter should be a pattern not again a full path.

It is not clear what you are trying to do here because you don't read the values returned but as it stands it raise an IOException

Directory.GetFiles

However your intial exception is caused by the file creation still in progress. When you receive the Created event you react immediately checking for file existence but at this point in time the OS doesn't allow you to call this File.Exists (expecially if the file is big). Try to put a delay before calling the test

    public static bool WaitForFileAvailable(string filePath, TimeSpan timeout)
    {
        Stopwatch stopwatch = Stopwatch.StartNew();
        while (stopwatch.Elapsed <= timeout)
        {
            Thread.Sleep(250);
            try
            {
                return File.Exists(filePath);
            }
            catch 
            {  
                // Not a very good thing to do, but I suppose that in the context of 
                // the call from the FileSystemWatcher Created event could be allowed
            }

        }
        return false;
    }
Steve
  • 213,761
  • 22
  • 232
  • 286
  • What do you mean with pattern? –  Jun 20 '13 at 11:52
  • Directory.GetFiles(@"C:\temp", "*.txt"); – Steve Jun 20 '13 at 11:54
  • However your intial exception is caused by the file creation still in progress. When you receive the Created event you react immediately checking for file existence but at this point in time the OS doesn't allow you to call this File.Exists. Try to put a delay before calling the test – Steve Jun 20 '13 at 11:56
  • @Steve You should be able to call `File.Exists()` for a file that's in use. – Matthew Watson Jun 20 '13 at 11:57
  • @MatthewWatson I agree, but in this context? Just after receiving the event Created from the FileSystemWatcher? Difficult to reproduce so a bit of delay could help. – Steve Jun 20 '13 at 12:03
  • What are the NotifyFilters and the Filter property on the FileSystemWatcher? – Steve Jun 20 '13 at 12:32
0

I guess the folder is not exist,or deleted at the time of copying.
Hope this will help you.
http://www.codeproject.com/Articles/3210/Function-to-copy-a-directory-to-another-place-noth

Vijay Hulmani
  • 969
  • 8
  • 17
0

I think that your fileSystemWatcher1_Created() method can be called for both a changed file and a changed folder.

Therefore you will probably want to handle files and folders differently, something like this (you'll have to modify this to suit - this is just to get the idea across).

Note how e.FullPath might be a file or it might be a folder, and we can see if it's a folder using Directory.Exists():

private void fileSystemWatcher1_Created(object sender, System.IO.FileSystemEventArgs e)
{
    if (Directory.Exists(e.FullPath)) // Is it a folder?
    {
        // Do whatever you want to do with a folder instead of a file.

        // You'll need to check if target is right: It needs to be the name of an exisitng folder.
        CopyDirectories(e.FullPath, target);
    }
    else
    {
        if (WaitForFileAvailable(e.FullPath, TimeSpan.FromSeconds(10)))
        {
            listBox1.Items.Add("File created> " + e.FullPath + " -Date:" + DateTime.Now);
            File.Copy(e.FullPath, Path.Combine(target, e.Name));
        }
        else // The file failed to become available within 10 seconds.
        {
            // Error handling.
        }
    }
}

To copy a directory, you can use code like this:

public void CopyDirectories(string sourceDir, string destinationDir)
{
    foreach (string dir in Directory.GetDirectories(sourceDir, "*", SearchOption.AllDirectories))
        Directory.CreateDirectory(destinationDir + dir.Substring(sourceDir.Length));

    foreach (string fileName in Directory.GetFiles(sourceDir, "*.*", SearchOption.AllDirectories))
        File.Copy(fileName, destinationDir + fileName.Substring(sourceDir.Length));
}

Which I got from here: https://stackoverflow.com/a/8022011/106159

Community
  • 1
  • 1
Matthew Watson
  • 104,400
  • 10
  • 158
  • 276
  • i want to copy the directory. How do i do that? –  Jun 20 '13 at 12:46
  • @JohnSmith I've added a sample method to copy directories. – Matthew Watson Jun 20 '13 at 13:00
  • In my case i have to put source instead of sourcedir and target as destinationdir? –  Jun 20 '13 at 13:04
  • The folder wont bring the files with the folder. + the 2nd foreach doesn't work. When I just use the first foreach it works but doesn't bring the files in the folder to the directory. –  Jun 20 '13 at 13:11