handling DirectoryNotFoundException errors - c#

I offer up file downloads from my website to users. When the file exists, it works fine. But if the file is removed for whatever reason, I get the following error in Visual Studio:
An exception of type 'System.IO.DirectoryNotFoundException' occurred in
mscorlib.dll but was not handled in user code
and the users just see a JSON string on the website.
I use this offer up a stream:
var result = new HttpResponseMessage(HttpStatusCode.OK);
result.Content = new StreamContent(
new FileStream(mediaFile.FilesystemLocation, FileMode.Open));
mediaFile.FilesystemLocation is simply this:
public virtual string FilesystemLocation
{
get { return Path.Combine(FilesystemRoot, Id + "." + Extension); }
}
I tried putting the whole thing in a try/catch block but then it lost all it's references to other classes.
So my question is, how can I handle this code and prevent this error?
Ideally, I'd just like to display a message to the user, "File Not Found, please contact your Administrator" or something like that.
Thanks!

System.IO.File.Exists is going to be your friend here. Before you set result.Content call this first. If the file doesn't exist, the method will return false and you can adjust your logic accordingly.
var filepath = mediaFile.FilesystemLocation;
if (!File.Exists(filepath))
{
return new HttpResponseMessage(404);
}
else{
var result = new HttpResponseMessage(HttpStatusCode.OK);
//just in case file has disappeared / or is locked for open,
//wrap in try/catch
try
{
result.Content = new StreamContent(
new FileStream(filepath, FileMode.Open));
}
catch
{
return new HttpResponseMessage(500);
}
return result;
}

Related

Exception: Error getting value from 'Position' on 'Amazon.Runtime.Internal.Util.MD5Stream'

I am facing this exception
Error getting value from 'Position' on 'Amazon.Runtime.Internal.Util.MD5Stream'.
when trying to read file from aws s3 bucket.
Here is my c# code
try
{
var s3ObjectPath = $"users/{email.Id}/emailattachments/{item.AttachedFileName}";
var ifExists = await this.Exists(s3ObjectPath);
if (ifExists)
{
Stream attachment = await s3Client.GetObjectStreamAsync(attachmentS3BucketName, s3ObjectPath, dicData);
Attachment att = new Attachment(attachment, item.AttachedFileName);
attachments.Add(att);
}
}
catch (AmazonS3Exception ex)
{
}
However this is working sometimes. I searched everywhere but didn't find solution.
Thanks in advance!!
This is due to an issue with how Streams work. When you open a Stream you are not actually getting the content of the file, rather you are opening a connection enabling you to access the data.
The error you got is returned when your code is trying to access the stream but doesn't have the ability to do so (a connection being lost / no appropriate credentials in the code accessing the stream or any other reason).
The solution is either to solve the underlaying issue and make sure your code still as access to the Stream or to just read from the stream and return a string rather than a stream
The code addition would look something like this:
...
Stream attachment = await s3Client.GetObjectStreamAsync(attachmentS3BucketName, s3ObjectPath, dicData);
StreamReader reader = new StreamReader(attachment);
string attachmentText = reader.ReadToEnd();
Attachment att = new Attachment(attachmentText, item.AttachedFileName);
attachments.Add(att);

StreamReader Could not find file (Because it is not being created)

I am trying to create a file for the further write to and read from.
I use Directory.CreateDirectory and File.Create but neither path nor file are being created.
On the Page which part I show here below I check if File exists, and if not, I create a File. On Second Page (that I dont show here) I add new lines to the file using StreamWrite. When saved, first Page comes to focus again and lists the content of the File(only one row in this study).
Here is my code for the part in question:
public async Task ReadFileAsync()
{
string directoryName = Path.GetDirectoryName(#"C:\Users\...\DataBase\");
Task.Run(async() => Directory.CreateDirectory(directoryName));
Task.Run(async() => File.Create(directoryName + "ProductsDatabase.txt"));
//code for reading from file
string path = (directoryName + "ProductsDatabase.txt");
using (StreamReader ProductsDatabaseRead = new StreamReader(File.OpenRead(path)))
{
ProductOneTextBlock.Text = ProductsDatabaseRead.ReadLine();
}
if (ProductOneTextBlock.Text == "")
{
ProductOneTextBlock.Text = "Nothing to show";
}
}
The file and folder are not being created.
I don't get any error.
I tried also different folders on the drive in case if there was READ ONLY folder in solution folder. No difference.
Anyone could help?
(I found many threads about this problem but here I cannot resolve it with none of the solutions.
Physical file is not being created.
When I attempt to write to it (from another page) I get error that the file could not be found(because it is not there indeed).
It seems that program loses itself somewhere between
Task.Run(async() => Directory.CreateDirectory(directoryName));
Task.Run(async() => File.Create(directoryName + "ProductsDatabase.txt"));
and:
using (StreamReader ProductsDatabaseRead = new StreamReader(File.OpenRead(path)))
{
ProductOneTextBlock.Text = ProductsDatabaseRead.ReadLine();
}
, as TextBlock is not being updated even if ProductsDatabaseRead is null.
If I put
ProductOneTextBlock.Text = "Nothing to show";
a the begining of the method, TextBlock gets updated.
SO, why the
using (StreamReader ProductsDatabaseRead = new StreamReader(File.OpenRead(path)))
does not work?
You're not waiting for Task.Run to complete. Your directory creation, file creation and attempt to open a "as you think newly created file" are out of order. That's why you're probably not able to open a file (it still does not exist at this point).
Task.Run returns a task that will be completed when the work is done. You need to wait for completion.
public void ReadFile()
{
string folderPath = #"C:\Users\patri\source\repos\DietMate\";
string fileName = "ProductsDatabase.txt";
string fullPath = Path.Combine(folderPath, fileName);
//insert code to check whether file exists.
// use Exists()
if (!Directory.Exists(folderPath))
{
Directory.CreateDirectory(folderPath);
File.Create(fullPath);
}
//if yes, follow with code below
//insert code for reading from file
using (StreamReader ProductsDatabaseRead = new StreamReader(fullPath))
{
ProductTest.Text = ProductsDatabaseRead.ReadLine();
}
}

Xamarin Android, read a simple text file from internal storage/Download

I'm using Xamarin, and according to previous answers, this shall work:
string path = Path.Combine(Android.OS.Environment.DirectoryDownloads, "families.txt");
File.WriteAllText(path, "Write this text into a file!");
But it doesn't, I get and unhandled exception. I have set the permissions to read and write to external storage (even though this is internal).
I also tried it with this:
string content;
using (var streamReader = new StreamReader(#"file://" + path )) // with and without file://
{
content = streamReader.ReadToEnd();
}
But I got the same unhandled exception.
UPDATE: The path is the problem, since I get the else part here:
Java.IO.File file = new Java.IO.File(path);
if (file.CanRead())
testText.Text = "The file is there";
else
testText.Text = "The file is NOT there\n" + path;
Which is weird, because the path seems to be correct. The exceptions: Could not find a part of the path: /Download/families.txt
UPDATE2: On external storage, it works, with the same code... Might it be my device's problem? That would be great, cause I tested the external storage version on my friend's phone, but mine doesn't have external storage (OnePlus One), so I'm still looking for a solution (if there's any).
Finally found a solution.
var path = global::Android.OS.Environment.ExternalStorageDirectory.AbsolutePath;
var filename = Path.Combine(path.ToString(), "myfile.txt");
The path was the problem, now with a simple streamwriter it works like magic.
try
{
using (var streamWriter = new StreamWriter(filename, true))
{
streamWriter.WriteLine("I am working!");
}
}
catch { ... }

Catch "FileNotFoundException"

I have a method to get the folder path of a particular file:
string filePath = Path.Combine(Environment.GetFolderPath(
Environment.SpecialFolder.MyDocuments), "file.txt");
And later, I use this to read the text in the file:
StreamReader rdr = new StreamReader(filePath); // "C:\Users\<user>\Documents\file.txt"
string myString = rdr.ReadToEnd();
Trouble is, if the file doesn't exist, it throws a FileNotFoundException (obviously). I want to hopefully use an if/else to catch the error, in which the user can browse to find the file directly, but I'm not sure what to use to verify if filePath is valid or not.
For example, I can't use:
if (filePath == null)
because the top method to retrieve the string will always return a value, whether or not it is valid. How can I solve this?
While File.Exists() is appropriate as a start, please note that ignoring the exception can still lead to an error condition if the file becomes inaccessible (dropped network drive, file opened by another program, deleted, etc.) in the time between the call to File.Exists() and new StreamReader().
You can use File.Exists:-
if(File.Exists(filePath))
{
//Do something
}
else
{
}
string filePath = Path.Combine(Environment.GetFolderPath(
Environment.SpecialFolder.MyDocuments), "file.txt");
if(!File.Exists(filePath))
{
/* browse your file */
}
else
{
StreamReader rdr = new StreamReader(filePath); // "C:\Users\<user>\Documents\file.txt"
string myString = rdr.ReadToEnd();
}

File in use error when deleting a folder

I am trying to delete a folder but am getting the following error message:
The process cannot access the file .it is being used by another process.
string target_dir="D:\\projectpath\\page";
if (Directory.Exists(target_dir))
Directory.Delete(target_dir, false);
How can I resolve this error?
It looks like the file is locked by some other process. This could happen if when reading/writing to it you forgot to dispose the stream reader/writer and you leaked the unmanaged handler to the file.
For example if you used the following code to read from the file:
StreamReader reader = new StreamReader(fileName);
string contents = reader.ReadToEnd();
and you never release the reader, the file will be locked. The proper way is to wrap IDisposable resources such as Streams and StreamReaders in using statements:
using (StreamReader reader = new StreamReader(fileName))
{
string contents = reader.ReadToEnd();
}
If on the other hand the file is locked by some other external process to your application then there's very little you could do about it, other than killing this process.
I think on the surface, your problem should be apparent: the file is in use by something else, so you can't delete the directory it resides in. If there was a way to "force delete" the file, it could cause other programs to crash. I'd recommend catching the error and either logging it or displaying it to the user, so they can decide if they really want to delete the in-use file.
If you MUST delete the file, you could take a look at:
Using C#, how does one figure out what process locked a file?
And once you know what the process is, you can then kill it, which should free up the file. Again, this isn't a good practice and should only be used in exceptional circumstances.
To delete the diectory you must have the correct Permissions.
var target_dir = "D:\\projectpath\page";
var isWriteAccess = false;
try
{
var collection = Directory.GetAccessControl(target_dir)
.GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount));
if (collection.Cast<FileSystemAccessRule>().Any(rule => rule.AccessControlType == AccessControlType.Allow))
{
isWriteAccess = true;
}
}
catch (UnauthorizedAccessException ex)
{
isWriteAccess = false;
}
catch (Exception ex)
{
isWriteAccess = false;
}
if (!isWriteAccess)
{
MessageBox.Show("no access to directory.");
// Handle here close and kill the blocking process
}
else
{
Directory.Delete(target_dir, false);
}
}

Categories