Есть задача удалить слишком длинные имена с пути, чтобы обойти exception:
The specified path, file name, or both are too long.
The fully qualified file name must be less than 260 characters,
and the directory name must be less than 248 characters.
Решение было принято использовать алгоритм:
1. Удалять с каждого сегмента (папки \ подпапки \ документа) по 20 символов,
начиная с конца (документа)
2. Если этого недостаточно - удалять по 10, потом 5 потом 2 символа.
3. Если все равно недостаточно - бросить Exception.
Реализация выглядит так:
private FileInfo GetFileInfo(string path)
{
int MAX_DIR_PATH = 248;
string[] subPaths = path.Split('\\');
string filename = subPaths[subPaths.Length - 1];
string extension = Path.GetExtension(filename);
StringBuilder sbFileName = new StringBuilder(filename);
sbFileName.Remove(sbFileName.Length - extension.Length, extension.Length);
StringBuilder sbPath = new StringBuilder(path.Remove(path.Length - sbFileName.Length));
StringBuilder sbNewPath = new StringBuilder();
int[] cuttingLength = new int[4] { 20, 10, 5, 2 };
for (int i = 0; i < cuttingLength.Length; i++)
{
int fileNameLength = sbFileName.Length;
if (sbPath.Length + fileNameLength + extension.Length >= MAX_DIR_PATH)
{
int cuttingLengthItem = cuttingLength[i];
if (sbFileName.Length > cuttingLengthItem)
{
int removeCount = fileNameLength - cuttingLengthItem;
sbFileName.Remove(removeCount, cuttingLength[i]);
}
}
else
{
sbNewPath.Append($"{ sbPath }{ sbFileName }{ extension }");
break;
}
}
if (sbNewPath.Length < 1)
{
subPaths = subPaths.Take(subPaths.Length - 1).ToArray();
for (int i = 0; i < cuttingLength.Length; i++)
{
if (sbPath.Length + sbFileName.Length + extension.Length >= MAX_DIR_PATH)
{
// 4 - потому что папки, который идут до - нельзя резать.
for (int idx = subPaths.Length - 1; idx > subPaths.Length - 4; idx--)
{
int cuttingLengthItem = cuttingLength[i];
if (subPaths[idx].Length > cuttingLengthItem)
{
string currentFolder = subPaths[idx];
int removeCount = currentFolder.Length - cuttingLengthItem;
subPaths[idx] = currentFolder.Remove(removeCount, cuttingLengthItem);
sbPath.Replace(sbPath.ToString(), string.Join("\\", subPaths));
break;
}
}
}
else
{
sbNewPath.Append($"{ sbPath }{ sbFileName }{ extension }");
break;
}
}
}
if (sbNewPath.Length < 1)
{
throw new ArgumentOutOfRangeException("The filepath is too long");
}
return new FileInfo(sbNewPath.ToString());
}
Вопросы: Есть ли более правильное решение такого алгоритма?
Или как можна отрефакторить/улучшить данный код?
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости