I've just signed up to the website so I have probably put this wrong. Anyways, I am trying to use the try and catch in C# to catch my file if it not found. Here is my code for it at the moment. To repeat myself, I want the program to read the file in, as it does- but then if the file is not found, I would like it to give an error saying "cannot find the file" or something along those lines, not simply just crash. (I've just started learning C#)
Thanks for the help!
string file = #"C:\Users\Henry\Desktop\Assessments\Programming and data structures\grades_multiple.txt";
try
{
file = #"C:\Users\Henry\Desktop\Assessments\Programming and data structures\grades_multiple.txt";
}
catch
{
Console.WriteLine("Could not find the file - grades_multiple.txt");
}
//ARRAY for string lines
string[] Line = new string[6];
Line[0] = File.ReadLines(file).Skip(1).Take(1).First();
You should read the file inside the try catch and catch FileNotFoundException, like this:
var file = #"C:\Users\Henry\Desktop\Assessments\Programming and data structures\grades_multiple.txt";
string[] lines;
try
{
lines = File.ReadAllLines(file);
}
catch (FileNotFoundException exnotfound)
{
// file not found exception
}
catch (Exception ex)
{
// handle other exceptions
}
You need to put the code that is error prone inside of try block.
try
{
Line[0] = File.ReadLines(file).Skip(1).Take(1).First();
}
catch(Exception ex)
{
Console.WriteLine("Could not find the file - grades_multiple.txt");
}
BTW, you can handle this situation by checking if file exists first using File.Exists method.There is no need to catch exception for that.
Try catch just doesn't work like this.
You are trying to catch a line of code that changes a string and doesn't change a file, so the file doesn't need to exist, so it will never throw an exception (in your case), and it will never catch it.
You should surround code that can go wrong: File.ReadLines
Your code will become like this:
string file = #"C:\Users\Henry\Desktop\Assessments\Programming and data structures\grades_multiple.txt";
//can go wrong
try
{
//ARRAY for string lines
string[] Line = new string[6];
Line[0] = File.ReadLines(file).Skip(1).Take(1).First();
}
//File.ReadLines is null
catch
{
Console.WriteLine("Could not find the file - grades_multiple.txt");
}
I also think it is even better practice to check it with an if statement, instead of catching it when it goes wrong:
//if file exists
if(File.Exists(file))
{
//ARRAY for string lines
string[] Line = new string[6];
Line[0] = File.ReadLines(file).Skip(1).Take(1).First();
}
//File does not exist
else
{
Console.WriteLine("Could not find the file - grades_multiple.txt");
}
When ever possible you should try to avoid throwing exceptions just to display a message to the user or for conditions that can be easily tested. This is primarily a performance consideration as throwing an exception is expensive. Additionally performance can be impacted by loading the entire file into memory unless you know that the file is relatively small..
Here is a quick and raw example on how you may test for the condition and handle it.
void Main()
{
var filePath ="C:\\TEST.DAT";
if(!File.Exists(filePath)){ DisplayFileNotFoundError(filePath); }
try
{
var lines = GetFileLines(filePath);
if(lines == null) { DisplayFileNotFoundError(filePath);}
// do work with lines;
}
catch (Exception ex)
{
DisplayFileReadException(ex);
}
}
void DisplayErrorMessageToUser(string filePath)
{
Console.WriteLine("The file does not exist");
}
void DisplayFileReadException(Exception ex){
Console.WriteLine(ex.Message);
}
string[] GetFileLines(string filePath){
if(!File.Exists(filePath)){ return null; }
string[] lines;
try
{
lines = File.ReadLines(filePath);
return lines;
}
catch (FileNotFoundException fnf){
Trace.WriteLine(fnf.Message);
return null;
}
catch (Exception ex)
{
Trace.WriteLine(ex.Message);
throw ex;
}
}
Performance Test, FileNotFoundException vs File.Exists
void Main()
{
int max = 100000;
long[] feSampling = new long[max];
long[] exSampling = new long[max];
String pathRoot ="C:\\MISSINGFILE.TXT";
String path = null;
Stopwatch sw = new Stopwatch();
for (int i = 0; i < max; i++)
{
path = pathRoot + i.ToString();
sw.Start();
File.Exists(pathRoot);
sw.Stop();
feSampling[i] = sw.ElapsedTicks;
sw.Reset();
}
StreamReader sr = null;
sw.Reset();
for (int i = 0; i < max; i++)
{
path = pathRoot + i.ToString();
try
{
sw.Start();
sr = File.OpenText(path);
}
catch (FileNotFoundException)
{
sw.Stop();
exSampling[i] = sw.ElapsedTicks;
sw.Reset();
if(sr != null) { sr.Dispose();}
}
}
Console.WriteLine("Total Samplings Per Case: {0}", max);
Console.WriteLine("File.Exists (Ticsk) - Min: {0}, Max: {1}, Mean: {2}", feSampling.Min(), feSampling.Max(), feSampling.Average ());
Console.WriteLine("FileNotFoundException (Ticks) - Min: {0}, Max: {1}, Mean: {2}", exSampling.Min(), exSampling.Max(), exSampling.Average ());
}
Related
Consider a C# code snippet like this (fileexcpt.py):
static void test1()
{
try
{
string text1 = File.ReadAllText(#"dir1\text1.txt");
string text2 = File.ReadAllText("text2.txt");
}
catch (IOException ex)
{
Console.Out.WriteLine(string.Format("Error reading file: {0}", ex.error_filename));
}
}
I hope ex.error_filename or something alike can tell me what file(filepath) caused the IO exception. Can I?
I see examples from https://learn.microsoft.com/en-us/dotnet/standard/io/handling-io-errors, but no such information found.
As for Python, it is natural, like this:
try:
text1 = open(r"dir1\text1.txt", "r").read();
text2 = open("text2.txt", "r").read();
except IOError as ex:
print("Error reading file: {0}".format(ex.filename));
You should avoid programming-by-exception where possible. And when you do need to catch exceptions then isolate the code into a single failing unit - don't catch across multiple points of failure.
Try this, as an example:
static void test1()
{
string text1 = ReadAllTextGuarded(#"dir1\text1.txt");
string text2 = ReadAllTextGuarded("text2.txt");
if (text1 != null & text2 != null)
{
//Success
}
}
static string ReadAllTextGuarded(string filename)
{
try
{
return File.ReadAllText(filename);
}
catch (IOException ex)
{
Console.Out.WriteLine(string.Format("Error reading file: {0}", filename));
}
return null;
}
Why don't you use simply ex whose output's the first line will tell you which gives rise to the error?
try
{
string text1 = File.ReadAllText("text1.txt");
string text2 = File.ReadAllText("text2.txt");
}
catch (FileNotFoundException ex)
{
// If you wish to get absolute path
//Console.Out.WriteLine($"Error reading file: {ex.FileName}");
// relative path
Console.Out.WriteLine($"Error reading file: {ex.FileName.Substring(ex.FileName.LastIndexOf('\\') + 1)}");
// No worry for the Substring exception because LastIndexOf returns -1 if not found, then plus 1 to start from 0.
}
catch (IOException ex)
{
Console.Out.WriteLine($"Error reading file: {ex}");
}
I am coding in C# .NET Core 2.2. I am trying to replace Excel Interop with EPPlusCore in my code for reliability and for portablilty. I have a series of invoices I am opening with EPPlus, but some of them throw a "Null Reference" exception when accessing the Workbook property of the Excel package.
This only happens when running the code without debugging it. When debugging, if I hover over the ExcelPackage item, it refreshes the reference to the Workbook and I am able to run the rest of the code.
public object[,] GetExcelDataEpplus(string filePath, int index,
bool sheetByName = false, string name = null, string password = null)
{
var remoteFileInfo = new FileInfo(filePath);
if (!remoteFileInfo.Exists)
{
throw new Exception("File does not exist: " + filePath);
}
var currentPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "temp-excel");
if (!Directory.Exists(currentPath))
{
Directory.CreateDirectory(currentPath);
}
var localFileInfo = new FileInfo(Path.Combine(currentPath, remoteFileInfo.Name));
if (!localFileInfo.Exists)
{
File.Copy(filePath, localFileInfo.FullName);
}
object[,] values = null;
try
{
if (!File.Exists(localFileInfo.FullName))
{
_logger.LogInformation(DbLog, "Cannot find file : " + localFileInfo.FullName);
return null;
}
else
{
_logger.LogInformation(DbLog, "Found file : " + localFileInfo.FullName);
}
_logger.LogInformation(DbLog, "Initializing EPPlus...");
using (var package = string.IsNullOrEmpty(password)
? new ExcelPackage(localFileInfo)
: new ExcelPackage(localFileInfo, password))
{
_logger.LogInformation(DbLog, "Opening Workbook...");
//todo Error Thrown Here
try
{
package.Workbook.FormulaParserManager.LoadFunctionModule(new ImporterFunctionModule());
}
catch (Exception e)
{
_logger.LogWarning(DbLog, e, $"Could not load workbook : Loading file again...");
try
{
System.Threading.Thread.Sleep(1000);
package.Workbook.FormulaParserManager.LoadFunctionModule(new ImporterFunctionModule());
}
catch (Exception ex)
{
_logger.LogError(DbLog, ex, "Could not load workbook");
throw;
}
}
var workbook = package.Workbook;
_logger.LogInformation(DbLog, $"Calculating formulas...");
workbook.Calculate();
_logger.LogInformation(DbLog, "Finding Worksheet...");
var worksheet = sheetByName ? workbook.Worksheets.FirstOrDefault(x => x.Name == name) : workbook.Worksheets[index];
if (worksheet == null)
{
throw new Exception($"Could not find worksheet : {name}");
}
_logger.LogInformation(DbLog, $"Reading from worksheet : {worksheet.Name}...");
var start = worksheet.Dimension.Start;
var end = worksheet.Dimension.End;
values = worksheet.Cells[start.Row, start.Column, end.Row, end.Column].ToMultiDimensionalArray();
}
}
catch (Exception e)
{
_logger.LogError(DbLog, e, $"GetExcelInvoiceDataEpplus from {filePath} ({localFileInfo.FullName})"); //todo propogate error
}
finally
{
File.Delete(localFileInfo.FullName);
}
var rowCount = values?.GetLength(0) ?? 0;
_logger.LogInformation(DbLog, $"EPPLus found {rowCount} rows in the spreadsheet");
return values;
}
On most files, this works correctly, and I get a multidimensional array of the values from the specified worksheet tab. However, on some files, it does not work and I am at a loss as to why.
The closest similar problem I've been able to find is this: https://github.com/JanKallman/EPPlus/issues/416
But if this is accurate, how would I know what worksheet names have bad references without accessing the workbook first?
I found the solution. The excel files that were having problems were ones that were larger than average.
The solution was just to wait longer for them.
try
{
package.Workbook.FormulaParserManager.LoadFunctionModule(new ImporterFunctionModule());
}
catch (Exception e)
{
for (var i=1; i < 6; i++)
{
_logger.LogWarning(DbLog, e, $"Could not load workbook : Loading file again (Attempt #{i})...");
try
{
System.Threading.Thread.Sleep(2000);
package.Workbook.FormulaParserManager.LoadFunctionModule(new ImporterFunctionModule());
break;
}
catch (Exception ex)
{
if (i < 5) continue;
_logger.LogError(DbLog, ex, "Could not load workbook after 5 attempts");
throw;
}
}
}
I created folder with no name using (alt + 0160) while I search with c# it stuck in infinite loop and create exception of "Stack Over Flow"
My method is given which i am using for Search.
public void getTotatFoldersAndFilesCount(DirectoryInfo objDirs, System.ComponentModel.BackgroundWorker worker)
{
try{
if (worker.CancellationPending == true)
{ return; }
FileInfo[] objFiles = null;
numFoldersCount++;
if ((objDirs.Attributes & FileAttributes.ReparsePoint) != 0)
{ return;}
try
{
objFiles = objDirs.GetFiles(searchPatteren);
}
catch (UnauthorizedAccessException e)
{ }
catch (System.IO.DirectoryNotFoundException e)
{ }
catch (System.StackOverflowException ex)
{ }
if (objFiles != null)
{
foreach (FileInfo objFile in objFiles)
{
numFilesCount++;
}
foreach (DirectoryInfo objDir in objDirs.GetDirectories())
{
getTotatFoldersAndFilesCount(objDir, worker);
}
}
objFiles = null;
}
catch (Exception ex)
{
ErrorLogger("Error in Total Folder and File Count - Directory Name: " + objDirs.Name);
ErrorLogger(ex.Message);
}
}
This can be avoided by a simple change:
In the directory enumeration code, change the for loop to:
foreach (DirectoryInfo objDir in new DirectoryInfo(objDirs.FullName + Path.DirectorySeparatorChar).GetDirectories(searchPatteren))
{
getTotatFoldersAndFilesCount(objDir, worker);
}
When enumerating blank folder, the directory name is a white space. When initializing the DirectoryInfo object, the whitespace is trimmed causing the function to always loop trough the same directory. Adding the DirectorySeperatorChar ("\") in most of the cases solves the issue.
I google this question and find the solution by given link.
by adding single slash at the end of the directory path it will not go into infinite loop.
first i was doing this.
getTotatFoldersAndFilesCount(objDir, worker);
and now replace it with this. It solved my problem,
DirectoryInfo nDI = new DirectoryInfo(objDir.FullName + #"\");
getTotatFoldersAndFilesCount(nDI, worker);
link is given.
http://tiku.io/questions/4277530/getdirectories-fails-to-enumerate-subfolders-of-a-folder-with-255-name
How to replace tabs with ? I try it like this:
foreach (var url in urlList)
{
try
{
stopwatch.Start();
requester.DownloadString(url);
url.Replace("\n",string.Empty);
if (url.Contains("/select/"))
{
url.Replace(string.Empty, "?");
}
}
catch (Exception e)
{
Console.WriteLine("An error occured while attempting to connect to {0}", url);
}
finally
{
stopwatch.Stop();
//We use the counter for a friendlier url as the current ones are unwieldly
times.Add("Url " + counter, stopwatch.Elapsed);
counter++;
stopwatch.Reset();
}
}
But this: url.Replace("\n","?"); doesnt do the job. So how to manage that? My post has to much code. But I dont have text to type
Thank you
this is the complete code:
public class Program
{
static void Main(string[] args)
{
//Consider making this configurable
const string sourceFile = "testSolar.txt";
var requester = new WebClient();
var times = new Dictionary<string, TimeSpan>();
var stopwatch = new System.Diagnostics.Stopwatch();
//Add header so if headers are tracked, it will show it is your application rather than something ambiguous
requester.Headers.Add(HttpRequestHeader.UserAgent, "Response-Tester-Client");
var urlList = new List<string>();
//Loop through the lines in the file to get the urls
try
{
stopwatch.Start();
using (var reader = new StreamReader(sourceFile))
{
while (!reader.EndOfStream)
{
urlList.Add(reader.ReadLine());
urlList.Remove("\n");
}
}
}
catch (Exception e)
{
Console.WriteLine("An error occured while attempting to access the source file at {0}", sourceFile);
}
finally
{
//Stop, record and reset the stopwatch
stopwatch.Stop();
times.Add("FileReadTime", stopwatch.Elapsed);
stopwatch.Reset();
}
//Try to connect to each url
var counter = 1;
foreach (var url in urlList)
{
try
{
stopwatch.Start();
requester.DownloadString(url);
url.Replace("\t","?");
if (url.Contains("/select/"))
{
url.Replace(string.Empty, "?");
}
}
catch (Exception e)
{
Console.WriteLine("An error occured while attempting to connect to {0}", url);
}
finally
{
stopwatch.Stop();
//We use the counter for a friendlier url as the current ones are unwieldly
times.Add("Url " + counter, stopwatch.Elapsed);
counter++;
stopwatch.Reset();
}
}
//Release the resources for the WebClient
requester.Dispose();
//Write the response times
foreach (var key in times.Keys)
{
Console.WriteLine("{0}: {1}", key, times[key].TotalSeconds);
}
Console.ReadKey();
}
}
This was doing the work:
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
line = line.Replace("\t", "?");
urlList.Add(line);
}
Issue here is you are not re-assinging the string back to variable:
url = url.Replace("\n",string.Empty);
and to replace tabs try \t as mentioned by others:
url = url.Replace("\t","?");
A tab string is represent by \t.
So if you want to replace tab by question mark:
url.Replace("\t","?");
Should do the job.
Edit:
Right, as explain by Zaheer Ahmed, you need also to reaffect the result of the Replace function...
I am moving some images (filenames are(1).PNG, (2).PNG and so on) from one directory to another. I am using the following code:
for (int i = 1; i < n; i++)
{
try
{
from = "E:\\vid\\(" + i + ").PNG";
to = "E:\\ConvertedFiles\\" + i + ".png";
File.Move(from, to); // Try to move
Console.WriteLine("Moved"); // Success
}
catch (IOException ex)
{
Console.WriteLine(ex); // Write error
}
}
However, I am getting the following error:
A first chance exception of type System.IO.FileNotFoundException occurred in mscorlib.dll
System.IO.FileNotFoundException: Could not find file 'E:\vid\(1).PNG'.
Also, I am planning to rename the files so that the converted file name will be 00001.png, 00002.png, ... 00101.png and so on.
I suggest you to use '#' in order to escape slashes in a more readable way. Use also Path.Combine(...) in order to concatenate paths and PadLeft in order to have your filenames as your specifics.
for (int i = 1; i < n; i++)
{
try
{
from = System.IO.Path.Combine(#"E:\vid\","(" + i.ToString() + ").PNG");
to = System.IO.Path.Combine(#"E:\ConvertedFiles\",i.ToString().PadLeft(6,'0') + ".png");
File.Move(from, to); // Try to move
Console.WriteLine("Moved"); // Success
}
catch (IOException ex)
{
Console.WriteLine(ex); // Write error
}
}
Why don't you use something like this?
var folder = new DirectoryInfo(#"E:\vid\"));
if (folder.Exists)
{
var files = folder.GetFiles(".png");
files.toList().ForEach(f=>File.Move(from,to));
}
The exception means that the file E:\vid(1).PNG doesn't exist. Do you mean E:\vid1.PNG?
Use System.IO.Path class for constructing paths, it's better than concatenating strings. You don't have to worry about escapting backslashes.
I just ran this in Visual Studio. It worked.
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication2
{
class Program
{
static void Main()
{
int n = 3;
for (int i = 1; i < n; i++)
{
string from = "C:\\vid\\(" + i + ").PNG";
string to = "C:\\ConvertedFiles\\" + i + ".png";
{
try
{
File.Move(from, to); // Try to move
Console.WriteLine("Moved"); // Success
}
catch (System.IO.FileNotFoundException e)
{
Console.WriteLine(e); // Write error
}
}
}
}
}
}
Maybe when you were moving files into vid directory to begin the test, windows shaved off the parenthesis. (1).png became 1.png... I got a file not found error from that phenomenon... otherwise, your code is solid. My version is almost identical.
i.ToString()
might help you. You are passing
from = "E:\\vid\\(" + i + ").PNG";
to = "E:\\ConvertedFiles\\" + i + ".png";
I as integer and concatenation doesn't work due to that
and instead of using \\, add # like this
from = #"E:\vid\(" + i + ").PNG";
var folder = new DirectoryInfo(sourcefolder);
if (folder.Exists)
{
var files = folder.GetFiles("*.png");
files.ToList().ForEach(f => File.Move(sourcefolder + f, newFolderName + f));
}
I believe this will help.