I'm really getting stuck on how to design my program, in simple term, it needs to create a list of file in a given path and then sorts them for now by date creating the respective subdirectory. The problem arises since the files are uploaded by the phone in a NAS and their creation date gets modified when uploaded to this drive. Since we are talking about photos-video or audio I tried using metadata and the best way I found to retrieve some common date stored in the metadata based on this answer is this:
internal static class FileInSorting
{
private static List<string> arrHeaders;
private static List<int> date = new List<int>() { 197, 3, 4, 5, 12, 198, 287, 208 };
private static List<FileToSort> fileToSort = new List<FileToSort>();
public static List<FileToSort> GetFilesToSort(string path)
{
Folder objFolder;
LoadHeader(path, out arrHeaders, out objFolder);
//I search for each file inside his extended property for the true creation date
//If none is found I default to what FileInfo thinks is right
foreach (Shell32.FolderItem2 item in objFolder.Items())
{
List<DateTime> tmp = new List<DateTime>();
DateTime SelectedDate;
foreach (int h in date)
{
string l = objFolder.GetDetailsOf(item, h);
if (!string.IsNullOrEmpty(l))
{
string asAscii = Encoding.ASCII.GetString(
Encoding.Convert(
Encoding.UTF8,
Encoding.GetEncoding(
Encoding.ASCII.EncodingName,
new EncoderReplacementFallback(string.Empty),
new DecoderExceptionFallback()),
Encoding.UTF8.GetBytes(l)
)
);
tmp.Add(DateTime.Parse(asAscii.Substring(0, 11)));
}
}
if (tmp.Count == 0)
SelectedDate = File.GetCreationTime(item.Path);
else
SelectedDate = tmp.Min();
fileToSort.Add(new FileToSort(item.Name, item.Path, SelectedDate));
}
return fileToSort;
}
public static void LoadHeader(string path, out List<string> arrHeaders, out Folder objFolder)
{
arrHeaders = new List<string>();
Shell32.Shell shell = new Shell32.Shell();
objFolder = shell.NameSpace(path);
for (int i = 0; i < short.MaxValue; i++)
{
string header = objFolder.GetDetailsOf(null, i);
if (!String.IsNullOrEmpty(header))
arrHeaders.Add(header);
}
}
}
I made this class just for easy use during sort but it could be completely redundant
public class FileToSort
{
public string nome { get; set; }
public string path { get; set; }
public DateTime sortDate { get; set; }
public FileToSort(string nome,string path,DateTime data)
{
this.nome = nome;
this.path = path;
this.sortDate = data;
}
}
The problem using this COM object is that is slow and not so easy to handle(maybe I'm just not able to) and as turned out on another question of mine it's not thread-safe, blocking out the option for parallel operation on multiple folders after the first sort.
For example, i'm first sorting all files in a tree structure "[YEAR]/[Month]/[Full date]" but then I would have to recreate the COM object for each "Full date" folder and sort those by type. I'm aware that after the first date sort I could start using Directory.EnumerateFile()
for each of the newly created folders but I would like to see if there is a better way to "design" the code so it can be reused without writing 2 separate methods for the date sort and for the type sort, so is there a way to avoid using the Com object entirely?
Quick edit I forgot another why I'm searching for another solution:
this is a WPF application and I would really like to use a ListView
binded with a single collection perhaps a FileInfo
collection