Создаю код бекапа заменяемых файлов. Имеется:
array<String^>^ FilesToCopy = System::IO::Directory::GetFiles(Path::Combine(pc->OBMFolder(), modName), "*.*", IO::SearchOption::AllDirectories);
/* Создаем бекап */
if (makeBackUp){
array<String^>^ FilesInGame = System::IO::Directory::GetFiles(Path::Combine(getGP->ModsFolder(), "SP2", "data"), "*.*", IO::SearchOption::AllDirectories);
for (int i = 0; i < FilesToCopy->Length; i++){
String^ FileToCopy = Path::GetFileName(FilesToCopy[i]);
for (int j = 0; j < FilesInGame->Length; j++){
String^ FileInGame = Path::GetFileName(FilesInGame[j]);
if (FileToCopy == FileInGame){
String^ NewPackFolder = Path::Combine(pc->OBMFolder(), wnd->GetInputText());
if (!Directory::Exists(NewPackFolder)) Directory::CreateDirectory(NewPackFolder);
ТУТ ПРОБЛЕМА, Нужно получить максимально возможную общуй часть для двух входных путей, и скопировать файл в новую папку сохраняя иерархию каталогов.
}
}
}
}
А проблема в следующем: Нужно сравнить два полных имени файла и вернуть их максимально общую часть с конца строк.
Например:
Путь А: С:\Folder\docs\file.txt
Путь Б: E:\Directory\Folder1\docs\file.txt
Нужно получить на выходе
docs\file.txt
Пока не очень понимаю как правильно реализовать данную функцию. Нужен алгоритм с примером. Не важно C# или C++CLI, я адаптирую под себя сам, просто на C# больше народу.
Ну как же, вопрос с меткой C# и никто не предложил Linq-вариант?
Исправляем:
var s1 = @"С:\Folder\docs\file.txt";
var s2 = @"E:\Directory\Folder1\docs\file.txt";
var s3 = new string(
s1.Reverse()
.Zip(s2.Reverse(), (c1, c2) => c1 == c2 ? c1 : -1)
.TakeWhile(x => x > -1)
.Reverse()
.Select(x => (char)x)
.ToArray());
Console.WriteLine(s3);
Выведет \docs\file.txt
Если вместо -1 использовать (char)0 и в TakeWhile поправить условие, то можно выкинуть Select
В C++/CLI переведете сами.
Почти то же самое, но сравниваем по секциям (специфично именно для путей), более правильное решение:
var s1 = @"C:\Folder\docs\file.txt";
var s2 = @"E:\Directory\Folder1\docs\file.txt";
var s3 = string.Join("\\",
EnumerateParts(s1)
.Zip(EnumerateParts(s2), (p1, p2) => p1 == p2 ? p1 : null)
.TakeWhile(p => p != null)
.Reverse());
Console.WriteLine(s3);
Где EnumerateParts:
static IEnumerable<string> EnumerateParts(string path)
{
while (path != null)
{
yield return Path.GetFileName(path);
path = Path.GetDirectoryName(path);
}
}
Вот вам указание на то, как можно сделать:
void Main()
{
var common = this.GetCommonPathFromEnd(@"А: С:\Folder\docs\file.txt", @"E:\Directory\Folder1\docs\file.txt");
common.Dump();
}
// Define other methods and classes here
public string GetCommonPathFromEnd(string path1, string path2)
{
//path1.Length.Dump();
//path2.Length.Dump();
var commonSymbols = 0;
for(var i = commonSymbols; i < path1.Length || i < path2.Length ; i++)
{
//path1.Substring(path1.Length - i).Dump();
//path2.Substring(path2.Length - i).Dump();
if(!string.Equals(path1.Substring(path1.Length - i), path2.Substring(path2.Length - i)))
break;
commonSymbols = i;
//"".Dump();
}
//commonSymbols.Dump();
return path1.Substring(path1.Length - commonSymbols);
}
Вывод:
t
t
xt
xt
txt
txt
.txt
.txt
e.txt
e.txt
le.txt
le.txt
ile.txt
ile.txt
file.txt
file.txt
\file.txt
\file.txt
s\file.txt
s\file.txt
cs\file.txt
cs\file.txt
ocs\file.txt
ocs\file.txt
docs\file.txt
docs\file.txt
\docs\file.txt
\docs\file.txt
r\docs\file.txt
1\docs\file.txt
Закомментирован вспомогательный вывод.
Сборка персонального компьютера от Artline: умный выбор для современных пользователей