We help IT Professionals succeed at work.

Check out our new AWS podcast with Certified Expert, Phil Phillips! Listen to "How to Execute a Seamless AWS Migration" on EE or on your favorite podcast platform. Listen Now

x

Directory.GetFiles and file access?

davism
davism asked
on
Medium Priority
605 Views
Last Modified: 2012-05-11
Hi all,

I'm doing a Directory.GetFiles(strPath, strType) to get a list of files in a directory.

Then I am going through each file to process it. I'm doing that with a

foreach (string file in Files)
{
   do something
}

*NOTE: I'm assigning the files to an array from teh Directory.GetFiles statements.

Now, the problem is IF a file that I'm working with is being access by somebody or something else then the "do something" will fail.

I want to skip that file then all together.

Was I was thinking about doing was before I "do something" I wanted to see about renaming the file to a file with the same name. So something like File.Move(file, file);

Would/should that work or is there another way?

Any information would be greatly appreciated.

Thanks
Comment
Watch Question

Senior Engineer
CERTIFIED EXPERT
Top Expert 2010
Commented:
Unlock this solution with a free trial preview.
(No credit card required)
Get Preview
Todd GerbertSenior Engineer
CERTIFIED EXPERT
Top Expert 2010

Commented:
Ahh...I think I get it now.  doSomething is a long running process and if somebody else accesses the file after doSomething starts (but before it finishes) you have a problem?

Depending on what exactly constitutes "do something" may simply be able to open the files for exclusive access, thereby preventing any other process from opening them until you've closed'em.

Author

Commented:
That seems to work BUT I don't want it to throw an exception on that. I want it to continue to the next file.

How would/could I do that?
Todd GerbertSenior Engineer
CERTIFIED EXPERT
Top Expert 2010

Commented:
Just leave the catch block empty will cause the loop to simply go-round to the next file.  Exercise caution in doing so though, i.e. make sure you clean up anything that needs to be cleaned up in the catch or finally block (e.g. if you successfully opened the file in the try block, make sure you close it, etc).

Author

Commented:
tgerbert, yes and no. If there are 5 files in the directory for instance.  None of the files are being access but another process or something except for file #2.

Then what happens is the first of the file files process fine (and the "do something" happens). I hit the second file. "do something" will throw the exception because I cannot do something with that file or in that file (like a read or something) and because something else (another program or user or something) has that file open exclusively; an exception will be thrown on my foreach.

The end result is the 3rd, 4th and 5th files are NOT processed because that exception was thrown on the 2nd file.

that's what I'm trying to solve. The File.Move actually throws the exception because the file has exclusive access. I wanted to see about the file move to identify that it's in process (or exclusively access) but I'm not sure how to do that in C#.

Make sense?

Author

Commented:
Maybe I just missed that...tgerbert, you're saying to just left the catch blank? I am not following what you're getting at there.
Carlos VillegasFull Stack .NET Developer

Commented:
tgerbert solution works buddy, that is the way
Carlos VillegasFull Stack .NET Developer

Commented:
foreach (string file in Files)
{
    try
    {
        doSomething(file);
        File.Move // MUST BE HERE
    }
    catch (FileAccessException)
    {
        // LEAVE EMPTY
    }
}
Todd GerbertSenior Engineer
CERTIFIED EXPERT
Top Expert 2010

Commented:
Yes, leave the catch block empty is the basic idea, but there are some caveats. Gimme a few minutes & I'll try to get you a  better example.

Author

Commented:
yv989c.

Actually it didn't. The FileAccessException is an available exception when I am using System.IO; There is an IOException.

But when I do something like this:

try
{
                string[] files = Directory.GetFiles("C:\\", "*.*");

                foreach (string file in files)
                {

                    objFileout = new System.IO.StreamWriter("C:\\Test.txt");
                    File.Move(file, file);
                }
}
catch (IOException ex) //being that FileAccessException wasn't available
{
}

What am I missing there?

Author

Commented:
Or it is that I have the try and catch outside of that foreach?

Author

Commented:
Yep...that was it. :-) DUH!
Carlos VillegasFull Stack .NET Developer
Commented:
Unlock this solution with a free trial preview.
(No credit card required)
Get Preview
Carlos VillegasFull Stack .NET Developer

Commented:
Was clear in the tgerbert example
Todd GerbertSenior Engineer
CERTIFIED EXPERT
Top Expert 2010

Commented:
See my first comment, note that try/catch is inside the foreach loop.

If you step through your current code a line at a time you might see why it behaves the way it does.

After an exception is thrown, execution resumes after the try block.
Todd GerbertSenior Engineer
CERTIFIED EXPERT
Top Expert 2010

Commented:
This example is a little silly, but I just wanted to show how you don't necessarily always want a completely empty catch block, and how there's still sometimes some cleanup that needs to be done even when you can recover from an exception.

Note that you can have more than one catch block, and the first one that the runtime finds with a matching exception type is what runs...so they should be listed in order of least-specific to most-specific.

using System;
using System.IO;

class Program
{
	static void Main(string[] args)
	{
		string strPath = "C:\\temp";
		string strType = "*.txt";

		string[] files = Directory.GetFiles(strPath, strType);

		foreach (string file in files)
		{
			FileStream openedFile = null;
			try
			{
				openedFile = File.Open(file, FileMode.Open);

				SomethingNotFileRelated();

				try
				{
					DoSomething(openedFile);
				}
				catch (Exception ex)
				{
					Console.WriteLine("DoSomething() threw an exception: " + ex.Message);
					Console.Write("Press any key to proceed to the next file...");
					Console.ReadKey();
				}
			}
			catch (IOException ex)
			{
				// This block will catch only IOExceptions thrown
				// EXCEPT exceptions
				// that are handled by the inner try/catch lines,
				// That means this catch block (in THIS example) will
				// only ever catch exceptions thrown by the File.Open
				System.Diagnostics.Debug.WriteLine(
					"File: " + file + ", exception: " + ex.Message + ", proceeding to next file.");
			}
			catch (Exception ex)
			{
				// This catch block will catch any other exceptions
				Console.WriteLine("An unexpected exception was thrown: " + ex.Message);
				Console.Write("Press 'Y' to attempt to continue. ");
				ConsoleKey c = Console.ReadKey().Key;
				if (c != ConsoleKey.Y)
					Environment.Exit(1);
			}
			finally
			{
				// Since it's possible the file open might have succeeded,
				// even if an exception was thrown, it's important
				// to have this finally block
				if (openedFile != null)
				{
					openedFile.Dispose();
					openedFile = null;
				}
			}
		}
	}

	static void DoSomething(FileStream fstream)
	{
		// This method doesn't actually do anything
		// except throw an exception (just for demonstration's sake)
		if (random.Next(0, 2) == 1)
			throw new Exception("DoSomething(): Test Exception Thrown");

		Console.WriteLine("DoSomething() finished successfully.");
	}

	static void SomethingNotFileRelated()
	{
		if (random.Next(0, 2) == 1)
			throw new Exception("NotFileRelated: Test Exception");

		Console.WriteLine("SomethingNotFileRelated() finished successfully.");
	}

	static Random random = new Random();
}

Open in new window

Unlock the solution to this question.
Thanks for using Experts Exchange.

Please provide your email to receive a free trial preview!

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.