I am quite new to C#, currently working through a number of pluralSight courses.
I've written a few small things here and there, but never anything that performed an entire purpose/function from start to finish, until now, with this app.
The app lists all the JPEG photos in an import folder and collects the takenDate from the exif, it then sorts it into the following structure:
D:\Photos\2014\12-2014\25-12-2014.
You can check out the full code on github
The app has been tested with around 3-4,000 photos and it churns through them in about 4-5 seconds..
A few things which I am unsure if I have done correctly are as follows:
Have I loaded my main method down with too much?
static void Main(string[] args)
{
log4net.Config.XmlConfigurator.Configure(); //load the logger config settings.
log.Info("Application Started");
string[] Files = FileHandler.ListFiles();
foreach (var f in Files)
{
log.Info("---WORKING WITH THE FOLLOWING FILE---");
log.Info(f);
//collect all the required infomation.
DateTime ExtractedDateTime = ExifParser.getTakenDateTime(f);
string fileName = Path.GetFileName(f);
string originalPath = f;
string targetPath = FilePathBuilder.calculateTargetPath(ExtractedDateTime, fileName);
//Do final move of file.
FileMover.MoveToDestinationFolder(originalPath,targetPath);
}
ApplicationTerminator.SucessfulApplicationEnd();
}
This is also my first implementation using log4net. Some feedback on how it is used would be great!
I am trying to keep my coding in line with things like SOLID and keeping KISS in mind with everything, I feel I have abstracted out the functionality into classes which perform only one function such as these:
public class ExifParser
{
private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
public static DateTime getTakenDateTime(string filePath)
{
ExifReader reader = new ExifReader(filePath);
DateTime datePictureTaken;
try
{
log.Info("Getting Taken Date From Photos EXIF Data");
log.Debug("Processing EXIF Date for the following file:");
log.Debug(filePath);
if (reader.GetTagValue<DateTime>(ExifTags.DateTimeDigitized, out datePictureTaken))
{
log.Debug("EXIF Data Collected Sucessfully");
reader.Dispose();
return datePictureTaken;
}
else
{
reader.Dispose();
log.Error("Failed To Collect EXIF Data, Check the following file for EXIF Data:");
log.Error("" + filePath);
return new DateTime(0001, 01, 01); //The FolderPath builder will recognize a date as 0001 for the year as an error and build a path to the error folder!
}
}
catch (Exception e)
{
log.Error("An Exception Occured While Collecting EXIF Data");
log.Error("Exception Message: " + e.Message);
log.Error("Exception Stack: " + e.StackTrace);
log.Error("Returning the error datetime.");
return new DateTime(0001, 01, 01);
}
}
}
class DirectoryHandler
{
private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
/// <summary>
/// Validates if directory already exists, if it does not it is created
/// </summary>
/// <param name="TargetPath">The Path The Files Target/Destination directory.</param>
public static void ValidateDirectory(string TargetPath)
{
log.Debug("Checking if The following Directory Exists: " + Path.GetDirectoryName(TargetPath));
if (!Directory.Exists(Path.GetDirectoryName(TargetPath)))
{
log.Debug("The Directory Does not Exist, attempting to create it.");
Directory.CreateDirectory(Path.GetDirectoryName(TargetPath)); //path without the extension!
log.Debug("Destination Directory Created!");
}
else
{
log.Debug("The directory Exists!");
}
}
}
Overall, I am quite happy with how the project has gone and the functionality it performs completes the task 100%! However I think some feedback on ways to improve how my code is written is one of the main things I'd like to gain from this review.