Функция для сокращения пути к файлу, чтобы сделать его более читабельным - PullRequest
5 голосов
/ 02 декабря 2011

Есть ли в c # какая-либо функция для указания пути к файлу?

Ввод : "c: \ users \ Windows \ Загруженные программные файлы \ Folder \ Inside \ example \ file.txt"

Вывод : "c: \ users \ ... \ example \ file.txt"

Ответы [ 8 ]

6 голосов
/ 02 декабря 2011

Это выглядит менее читабельным для меня. Во всяком случае, я не думаю, что есть такая функция. разделите его на символ \ и просто оставьте первые два слота и последние два слота, и вы получите его.

Примерно так, хотя этот код не очень элегантный

  string[] splits = path.Split('\\');
  Console.WriteLine( splits[0] + "\\" + splits[1] + "\\...\\" + splits[splits.Length - 2] + "\\" +  splits[splits.Length - 1]);
5 голосов
/ 11 марта 2014

Насреддин ответил почти правильно.Просто укажите размер StringBuilder, в вашем случае:

[DllImport("shlwapi.dll", CharSet = CharSet.Auto)]
static extern bool PathCompactPathEx(
                       [Out] StringBuilder pszOut, 
                       string szPath, 
                       int cchMax, 
                       int dwFlags);

static string PathShortener(string path, int length)
{
    StringBuilder sb = new StringBuilder(length + 1);
    PathCompactPathEx(sb, path, length, 0);
    return sb.ToString();
}
3 голосов
/ 02 декабря 2011

Джефф Этвуд опубликовал решение этого вопроса в своем блоге и вот оно:

[DllImport("shlwapi.dll", CharSet = CharSet.Auto)]
static extern bool PathCompactPathEx([Out] StringBuilder pszOut, string szPath, int cchMax, int dwFlags);

static string PathShortener(string path, int length)
{
    StringBuilder sb = new StringBuilder();
    PathCompactPathEx(sb, path, length, 0);
    return sb.ToString();
}

Используется неуправляемая функция PathCompactPathEx для достижения того, что вы хотите.

3 голосов
/ 02 декабря 2011

Если вы хотите вставить многоточие в зависимости от длины строки пути, используйте этот код:

TextRenderer.MeasureText(path, Font, 
    new System.Drawing.Size(Width, 0),
    TextFormatFlags.PathEllipsis | TextFormatFlags.ModifyString);

Он изменит path на месте.

РЕДАКТИРОВАТЬ : будьте осторожны с этим методом.Это нарушает правило, говоря, что строки в .NET являются неизменяемыми.Фактически, первый параметр метода MeasureText не является параметром ref, что означает, что новая строка не может быть возвращена.Вместо этого существующая строка изменяется.Было бы осторожно работать с копией, созданной с помощью

string temp = String.Copy(path);
2 голосов
/ 02 декабря 2011

Вы можете использовать что-то вроде:

public string ShrinkPath(string path, int maxLength)
{
    List<string> parts = new List<string>(path.Split('\\'));

    string start = parts[0] + @"\" + parts[1];
    parts.RemoveAt(1);
    parts.RemoveAt(0);

    string end = parts[parts.Count-1];
    parts.RemoveAt(parts.Count-1);

    parts.Insert(0, "...");
    while(parts.Count > 1 && 
      start.Length + end.Length + parts.Sum(p=>p.Length) + parts.Count > maxLength)
        parts.RemoveAt(parts.Count-1);

    string mid = "";
    parts.ForEach(p => mid += p + @"\");

    return start+mid+end;
}

Или просто воспользуйтесь решением Olivers, что намного проще; -).

1 голос
/ 11 июля 2018

Если вы хотите написать собственное решение этой проблемы, используйте встроенные классы, такие как: FileInfo , Directory и т. Д., Что делает его менее подверженным ошибкам.

Следующий код создает сокращенный путь "VS style", например: "C: \ ... \ Folder \ File.ext".

public static class PathFormatter
{
    public static string ShrinkPath(string absolutePath, int limit, string spacer = "…")
    {
        if (string.IsNullOrWhiteSpace(absolutePath))
        {
            return string.Empty;
        }
        if (absolutePath.Length <= limit)
        {
            return absolutePath;
        }

        var parts = new List<string>();

        var fi = new FileInfo(absolutePath);
        string drive = Path.GetPathRoot(fi.FullName);

        parts.Add(drive.TrimEnd('\\'));
        parts.Add(spacer);
        parts.Add(fi.Name);

        var ret = string.Join("\\", parts);
        var dir = fi.Directory;

        while (ret.Length < limit && dir != null)
        {
            if (ret.Length + dir.Name.Length > limit)
            {
                break;
            }

            parts.Insert(2, dir.Name);

            dir = dir.Parent;
            ret = string.Join("\\", parts);
        }

        return ret;
    }
}
1 голос
/ 02 мая 2017
    private string ShrinkPath(string path, int maxLength)
    {
        var parts = path.Split('\\');
        var output = String.Join("\\", parts, 0, parts.Length);
        var endIndex = (parts.Length - 1);
        var startIndex = endIndex / 2;
        var index = startIndex;
        var step = 0;

        while (output.Length >= maxLength && index != 0 && index != endIndex)
        {
            parts[index] = "...";
            output = String.Join("\\", parts, 0, parts.Length);
            if (step >= 0) step++;
            step = (step * -1);
            index = startIndex + step;
        }
        return output;
    }
1 голос
/ 19 сентября 2015

Я только что столкнулся с этой проблемой, поскольку длинные пути становились полными болями в глазах. Вот то, что я собрал вместе очень быстро (не обращая внимания на разгильдяйство), но он выполняет свою работу.

private string ShortenPath(string path, int maxLength)
{
    int pathLength = path.Length;

    string[] parts;
    parts = label1.Text.Split('\\');

    int startIndex = (parts.Length - 1) / 2;
    int index = startIndex;

    string output = "";
    output = String.Join("\\", parts, 0, parts.Length);

    decimal step = 0;
    int lean = 1;

    do
    {
        parts[index] = "...";

        output = String.Join("\\", parts, 0, parts.Length);

        step = step + 0.5M;
        lean = lean * -1;

        index = startIndex + ((int)step * lean);
    }
    while (output.Length >= maxLength && index != -1);

    return output;
}

Results

EDIT

Ниже приведено обновление с исправлениями Merlin2001.

private string ShortenPath(string path, int maxLength)
{
    int pathLength = path.Length;

    string[] parts;
    parts = path.Split('\\');

    int startIndex = (parts.Length - 1) / 2;
    int index = startIndex;

    String output = "";
    output = String.Join("\\", parts, 0, parts.Length);

    decimal step = 0;
    int lean = 1;

    while (output.Length >= maxLength && index != 0 && index != -1)
    {
        parts[index] = "...";

        output = String.Join("\\", parts, 0, parts.Length);

        step = step + 0.5M;
        lean = lean * -1;

        index = startIndex + ((int)step * lean);
    }

    return output;
}
...