Jump to content

MOVE FILE

- - - - -

  • Please log in to reply
2 replies to this topic

#1
psm

psm

    Newbie

  • Members
  • Pip
  • 4 posts
Hi, I want to move a file, when it is created. I have filewatcher and I know filemove function, but I dont know how I can create condition, that the file will be moved, when it is create. Can you help me please?
This is my source code:

#include "stdafx.h" 

#using <System.dll> 


using namespace System;

using namespace System::IO;

using namespace System::Security::Permissions;


public ref class Watcher

{

private:

   static void OnChanged( Object ^ sender, FileSystemEventArgs^ e ) 

   {															

      Console::WriteLine( "Súbor: {0} {1}", e->FullPath, e->ChangeType );  

   }


   static void OnRenamed( Object ^ sender, RenamedEventArgs^ e ) 

     

      Console::WriteLine( "Súbor: {0} bol premenovaný na {1}", e->OldFullPath, e->FullPath );

   }


public:

   [PermissionSet(SecurityAction::Demand, Name="FullTrust")] //???

   int static run()

   {

     

	  String^args = "C:\\..."; 


      

	  FileSystemWatcher^ watcher = gcnew FileSystemWatcher;

	  watcher->Path = args; 


      watcher->NotifyFilter = static_cast<NotifyFilters>(NotifyFilters::LastAccess |    

            NotifyFilters::LastWrite | NotifyFilters::FileName | NotifyFilters::DirectoryName);


      

      watcher->Filter = "*.txt"; 


	  watcher->Changed += gcnew FileSystemEventHandler( Watcher::OnChanged ); 

	  watcher->Created += gcnew FileSystemEventHandler( Watcher::OnChanged ); 

	  watcher->Deleted += gcnew FileSystemEventHandler( Watcher::OnChanged );

	  watcher->Renamed += gcnew RenamedEventHandler( Watcher::OnRenamed );


      watcher->EnableRaisingEvents = true;


      // Wait for the user to quit the program.

      Console::WriteLine( "Press \'q\' to quit the sample." );

      while ( Console::Read() != 'q' );


      return 0;

   }

};


int main() 

{

   Watcher::run();


CONDITION???????


{ 

String^ path = "C:\\...\\test.txt";

String^ path2 = "C:\\...\\test.txt";

   try

   {

      // Move the file.

      File::Move( path, path2 );

      Console::WriteLine( "{0} was moved to {1}.", path, path2 );


      // See if the original exists now.

      if ( File::Exists( path ) )

      {

         Console::WriteLine( "The original file still exists, which is unexpected." );

      }

      else

      {

         Console::WriteLine( "The original file no longer exists, which is expected." );

      }

   }

   catch ( Exception^ e ) 

   {

      Console::WriteLine( "The process failed: {0}", e );

   }

}

}



#2
BlackRabbit

BlackRabbit

    Programming Professional

  • Members
  • PipPipPipPipPip
  • 265 posts
  • Location:ten steps forward
Here i have a couple of answers for you :

- The condition you are looking for is the OnCreated event, which i strongly suggest you implement, since you are sending the OnChange, OnCreate and OnDelete to the same event handler, which might mess up with your program's heap

so do the following :

watcher->Created += gcnew FileSystemEventHandler( Watcher::OnCreated );  

and of course implement the delegate :

static void OnCreated( Object ^ sender, FileSystemEventArgs^ e )  
{ 																													
	  Console::WriteLine( "Súbor: {0} {1}", e->FullPath, e->ChangeType );  
  }


Now the big deal, you will rarely able to move a file at the moment it is created, why ? cause there is another program that is using it and will not release the file until its job is done.

What to do ?
before moving the file check if it is in use, the easy way ? try catch it.

Advise :

. Making sleeps in event delegates messes with the heap, best way to get it done is to have an array with the recently created files and a thread which works that list up and sleeps.
. Don't move the file to any directory under the watch of the filewatcher cause that will make it crash.
. Don't implement OnChanged for this particular purpose, it fires a lot when a program is using the file and it adds nothing towards your goal.

Edited by Roger, 08 April 2012 - 11:35 AM.
added code blocks


#3
kernelcoder

kernelcoder

    Programming Professional

  • Members
  • PipPipPipPipPip
  • 309 posts
  • Location:Dhaka
  • Programming Language:C, Java, C++, C#, Visual Basic .NET
  • Learning:Objective-C, PHP, Python, Delphi/Object Pascal
I'm totally agree with BlackRabbit.

While you will follow the steps, you will face the Producer & Consumer problem -- one thread will put the file in a buffer, another will eat it. There few ways in .NET to solve it. However, to me, the easiest one is using the ArrayList class as, it is already thread-safe (if you use with ArrayList::Synchornized method).

I was trying to write the application with Managed C++ during writing the answer and It took a bit longer than in C# as I usually don't write code with Managed C++. However, following is the code that finally come to an end. Note that _textFileWatcher watcher is created by dragging the component from toolbox and the form class is Form1.

private:
String^ _storePath;
ArrayList^ _filesToMove;
BackgroundWorker^ _fileRunner;

System::Void Form1_Load(System::Object^  sender, System::EventArgs^  e)
{
_storePath = L"D:\\Moved\\";
_filesToMove = ArrayList::Synchronized(gcnew ArrayList());
_fileRunner = gcnew BackgroundWorker();

_fileRunner->DoWork += gcnew DoWorkEventHandler(this, &Form1::MoveFileInThread);
_fileRunner->RunWorkerAsync();

_textFileWatcher->Created += gcnew System::IO::FileSystemEventHandler(this, &Form1::OnTextFileCreated);
	_textFileWatcher->Path = L"D:\\Watched";
	_textFileWatcher->Filter = "*.txt";
	_textFileWatcher->EnableRaisingEvents = true;
}



System::Void OnTextFileCreated(Object^ sender, System::IO::FileSystemEventArgs^ e)
{
System::Threading::Monitor::Enter(_filesToMove->SyncRoot);
try {
	_filesToMove->Add(e->FullPath);
}
catch(Exception^){}
finally {System::Threading::Monitor::Exit(_filesToMove->SyncRoot);}
}



System::Void MoveFileInThread(Object^ sender, DoWorkEventArgs^ e)
{
	while (true) {
String^ file = String::Empty;
System::Threading::Monitor::Enter(_filesToMove->SyncRoot);
try {
			if (_filesToMove->Count > 0) {
				file = (cli::safe_cast<String^  >(_filesToMove[0]));
				_filesToMove->RemoveAt(0);
			}
		}
catch(Exception^){}
finally {System::Threading::Monitor::Exit(_filesToMove->SyncRoot);}

if (String::IsNullOrEmpty(file)) {
System::Threading::Thread::Sleep(500);
		}
		else {
			while (!MoveFile(file)) {
				System::Threading::Thread::Sleep(200);
			}
		}
	}
}


bool MoveFile(String^ fullName)
{
	try {
if (System::IO::File::Exists(fullName)) {
			int fileNamePos = fullName->LastIndexOf("\\") + 1;
			String^ name = fullName->Substring(fileNamePos, fullName->Length - fileNamePos);
			System::IO::File::Move(fullName, _storePath + name);
		}
	}
catch (Exception^) {
		return false;
	}

	return true;
}





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users