Initial commit: Add ShadowStream media application with file scanning and classification
This commit is contained in:
51
file finder test/FileMangerModules/FileClassifier.cs
Normal file
51
file finder test/FileMangerModules/FileClassifier.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace file_finder__test;
|
||||
|
||||
public class FileClassifier
|
||||
{
|
||||
public async Task<(List<string> musicFiles, List<string> videoFiles)> ClassifyFilesAsync(
|
||||
List<string> allFiles,
|
||||
List<string> musicExtensions,
|
||||
List<string> videoExtensions)
|
||||
{
|
||||
int coreCount = Environment.ProcessorCount;
|
||||
int totalFiles = allFiles.Count;
|
||||
int chunkSize = (int)Math.Ceiling((double)totalFiles / coreCount);
|
||||
|
||||
var musicBag = new ConcurrentBag<string>();
|
||||
var videoBag = new ConcurrentBag<string>();
|
||||
|
||||
var tasks = new List<Task>();
|
||||
|
||||
for (int i = 0; i < coreCount; i++)
|
||||
{
|
||||
int start = i * chunkSize;
|
||||
int end = Math.Min(start + chunkSize, totalFiles);
|
||||
|
||||
tasks.Add(Task.Run(() =>
|
||||
{
|
||||
for (int j = start; j < end; j++)
|
||||
{
|
||||
string file = allFiles[j];
|
||||
string ext = Path.GetExtension(file)?.ToLowerInvariant();
|
||||
|
||||
if (ext == null)
|
||||
continue;
|
||||
|
||||
if (musicExtensions.Contains(ext))
|
||||
musicBag.Add(file);
|
||||
else if (videoExtensions.Contains(ext))
|
||||
videoBag.Add(file);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
await Task.WhenAll(tasks);
|
||||
return (new List<string>(musicBag), new List<string>(videoBag));
|
||||
}
|
||||
}
|
79
file finder test/FileMangerModules/FileScanner.cs
Normal file
79
file finder test/FileMangerModules/FileScanner.cs
Normal file
@@ -0,0 +1,79 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
public class FileScanner
|
||||
{
|
||||
private readonly string[] _extensions;
|
||||
private readonly ConcurrentBag<string> _foundFiles = new ConcurrentBag<string>();
|
||||
|
||||
public FileScanner(string[] extensions)
|
||||
{
|
||||
_extensions = extensions.Select(e => e.ToLower()).ToArray();
|
||||
}
|
||||
|
||||
public async Task<List<string>> ScanAllDrivesAsync()
|
||||
{
|
||||
var drives = new List<string>();
|
||||
|
||||
foreach (var drive in DriveInfo.GetDrives())
|
||||
{
|
||||
if (!drive.IsReady) continue;
|
||||
|
||||
Console.WriteLine($"Scanning {drive.Name} ...");
|
||||
|
||||
string root = drive.RootDirectory.FullName;
|
||||
drives.Add(root);
|
||||
}
|
||||
|
||||
return drives.ToList();
|
||||
}
|
||||
|
||||
public async Task<List<string>> ScanDriveParallel(string rootPath)
|
||||
{
|
||||
var folderQueue = new ConcurrentQueue<string>();
|
||||
folderQueue.Enqueue(rootPath);
|
||||
|
||||
var folderWorkers = new List<Task>();
|
||||
//add Preformance testing here later
|
||||
int maxWorkers = Environment.ProcessorCount/2;
|
||||
|
||||
for (int i = 0; i < maxWorkers; i++)
|
||||
{
|
||||
folderWorkers.Add(Task.Run(() =>
|
||||
{
|
||||
while (folderQueue.TryDequeue(out string currentPath))
|
||||
{
|
||||
try
|
||||
{
|
||||
// Check files
|
||||
foreach (var file in Directory.GetFiles(currentPath))
|
||||
{
|
||||
if (_extensions.Any(ext => file.EndsWith(ext, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
//Console.WriteLine(file);
|
||||
_foundFiles.Add(file);
|
||||
}
|
||||
}
|
||||
|
||||
// Enqueue subdirectories
|
||||
foreach (var dir in Directory.GetDirectories(currentPath))
|
||||
{
|
||||
folderQueue.Enqueue(dir);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Skip inaccessible folders silently
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
Task.WaitAll(folderWorkers.ToArray());
|
||||
return _foundFiles.ToList();
|
||||
}
|
||||
}
|
49
file finder test/FileMangerModules/VideoSeparator.cs
Normal file
49
file finder test/FileMangerModules/VideoSeparator.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
public class VideoSeparator
|
||||
{
|
||||
private readonly Regex episodePattern = new Regex(@"E\d{1,3}", RegexOptions.IgnoreCase);
|
||||
|
||||
public async Task<(List<string> seriesFiles, List<string> movieFiles)> SeparateVideosAsync(List<string> videoFiles)
|
||||
{
|
||||
int coreCount = Environment.ProcessorCount;
|
||||
int totalFiles = videoFiles.Count;
|
||||
int chunkSize = (int)Math.Ceiling((double)totalFiles / coreCount);
|
||||
|
||||
var seriesBag = new ConcurrentBag<string>();
|
||||
var movieBag = new ConcurrentBag<string>();
|
||||
var tasks = new List<Task>();
|
||||
|
||||
for (int i = 0; i < coreCount; i++)
|
||||
{
|
||||
int start = i * chunkSize;
|
||||
int end = Math.Min(start + chunkSize, totalFiles);
|
||||
|
||||
tasks.Add(Task.Run(() =>
|
||||
{
|
||||
for (int j = start; j < end; j++)
|
||||
{
|
||||
string path = videoFiles[j];
|
||||
string filename = Path.GetFileNameWithoutExtension(path);
|
||||
|
||||
if (filename == null)
|
||||
continue;
|
||||
|
||||
if (episodePattern.IsMatch(filename))
|
||||
seriesBag.Add(path);
|
||||
else
|
||||
movieBag.Add(path);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
await Task.WhenAll(tasks);
|
||||
|
||||
return (new List<string>(seriesBag), new List<string>(movieBag));
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user