8
votes

Fonction pour rétrécir le chemin de fichier pour être plus lisible par l'homme

Y a-t-il une fonction en C # pour désigner un chemin de fichier?

Entrée : "C: \ Utilisateurs \ Windows \ Fichiers de programme téléchargé \ Dossier \ Inside \ Exemple \ File.txt"

sortie : "c: \ utilisateurs \ \ \ exemple \ file.txt"


3 commentaires

Est-ce pour Winforms ou voulez-vous juste une ficelle plus courte? (Je demande parce que .NET soutient cela pour le dessin uniquement, qui s'applique uniquement aux winforms et aux images).


Pourquoi voudriez-vous prendre la voie complète? Si c'était le cas, l'utilisateur ne serait pas en mesure de trouver le fichier. Si vous n'êtes pas inquiet à ce sujet - N'affichez pas du tout le chemin - juste le nom du fichier.


User946874: Vous êtes les bienvenus. De plus, depuis que vous êtes nouveau sur Stackoverflow, j'aimerais vous informer que vous pouvez accepter une réponse qui vous a tout aidé en vérifiant la marque à côté de la réponse.


9 Réponses :


6
votes

qui semble moins humain lisible pour moi. Quoi qu'il en soit, je ne pense pas qu'il y ait une telle fonction. Débitez-le sur le caractère \ et gardez simplement les deux premiers emplacements et les deux derniers emplacements et vous l'avez.

Quelque chose comme ça, bien que ce code ne soit pas très élégant P>

  string[] splits = path.Split('\\');
  Console.WriteLine( splits[0] + "\\" + splits[1] + "\\...\\" + splits[splits.Length - 2] + "\\" +  splits[splits.Length - 1]);


2 commentaires

J'ajouterais également un si (divisez.length> 4) test là-bas aussi.


Ceci n'est absolument pas rétrécissant le chemin ... pensez avoir un chemin comme c: \ françaisveryveryverlong \ supersupersuperlong \ a \ b \ c \ d.txt ... Quelle sera exactement votre solution?



4
votes

Si vous le souhaitez, insérez-vous des ellipsis dépendant de la longueur de la chaîne de chemin, puis utilisez ce code: xxx

Il modifiera chemin en place.

EDIT : Soyez prudent avec cette méthode. Il enfreint la règle, disant que des chaînes de .NET sont immuables. En fait, le premier paramètre de la méthode mesteutext n'est pas un paramètre ref , ce qui signifie qu'aucune nouvelle chaîne ne peut être renvoyée. Au lieu de cela, la chaîne existante est modifiée. Il serait prudent de travailler sur une copie créée avec xxx


0 commentaires

2
votes

Vous pouvez utiliser quelque chose comme: xxx

ou utilisez simplement une solution d'olivers, ce qui est beaucoup plus facile; -).


0 commentaires

6
votes

Jeff Atwood Posted une solution à Ceci sur son blog et ici c'est: xxx

Il utilise la fonction non géographique PathCompactPathex pour réaliser ce que vous voulez.


3 commentaires

Mystérieusement, cela fonctionnait génial dans le cadre 3.5, j'ai mis à jour à VS 2010 et à Cadre 4 et je reçois désormais un crash ultérieur sur cette ligne. (Visual Studio est occupé ...) Passez à Charset.ansi "Résolu" (?) Le problème.


@ V.Oddou Il m'a écrasé pour moi aussi jusqu'à ce que je sentais La solution de Daniele qui utilise un autre constructeur: SB = New StringBuilder (longueur + 1) .


Méfiez-vous: Cela se bloque (au moins avec des récents frameworks .NET), car stringbuilder par Par défaut alloue 16 caractères , qui ne suffit souvent pas à stocker le résultat. Vous devez utiliser la longueur ou le max_path = 260 pour éviter la corruption de la mémoire possible.



8
votes

La réponse Nasreddine était presque correcte. Il suffit de spécifier StringBuilder Taille, dans votre cas:

[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();
}


0 commentaires

2
votes

J'étais juste confronté à cette question en tant que longues chemins devenant des yeux. Voici ce que j'ai jeté ensemble réel rapide (pensez à la négligence), mais cela fait le travail.

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);
    }
    // result can be longer than maxLength
    return output.Substring(0, Math.Min(maxLength, output.Length));  
}


8 commentaires

Idée intelligente! Mais vous remplacez toujours au moins une partie du chemin même si elle s'adapterait à la longueur totale. Et aussi, vous pouvez rencontrer un indexautofrangeException si le chemin ne correspond pas à même avec toutes les pièces remplacées par ... . To correction ceci (et conserver au moins la lettre de lecteur et le dernier répertoire), je vais suggérer de modifier le do.. ou code> à un pendant et Vérifiez que index! = 0 && index au lieu de index! = -1 . De cette façon, vous n'exécutez pas dans des exceptions et n'ajoutez pas d'ellipses superfluses.


@ Merlin2001 Merci beaucoup et bonne prise! Vos suggestions amélioreront certainement mon code. Je serai sûr de faire les mises à jour appropriées.


Vous devez promouvoir l'utilisation des alias de type, au lieu d'utiliser les noms de type. Donc int au lieu de int32


Désolé, je préfère que cela soit probablement dû à mes préférences de fond et personnelles. Les vieilles habitudes ont la vie dure. Par souci d'argument, je ferai de mon mieux lors de la publication des extraits de code pour se conformer aux attentes majoritaires.


Édité pour autoriser uniquement les caractères maxlength (il peut casser à un mauvais point, mais il ne dépassera pas la longueur spécifiée de l'appelant)


@ J.chriscompton, votre édition semble être valide à 100% mais cela aiderait vraiment si vous pouviez fournir un exemple spécifique qu'il corrige.


@Chrishaas exemple où la soustrine est nécessaire: raccourci (@ "C: \ Temp \ a dossier dossier \ b dossier \ d dossier dossier \ e dossier \ e dossier \", 20) sans la sous-chaîne du résultat est 35 Personnages c: \ \ \ \ \ \ \ \ \ \ ... \ ... \ f dossier


C'est la mauvaise manière. Vous ne prenez pas compte de la largeur de chaque personnage. Les caractères de 30 "W" ont la même chose avec des caractères de 90 "I", en outre, cela dépend de la police que vous utilisez.



1
votes
    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 commentaires

Beau code. Également très facile à modifier pour fonctionner avec une largeur de pixel et mesurstring . Merci.



0
votes

Si vous souhaitez vous écrire une solution à ce problème, utilisez la construction de classes comme: fileInfo strong>, répertoire strong>, etc ... ce qui le rend moins sujet aux erreurs.

Le code suivant produit un chemin raccourci "VS Style" comme: "C: \ ... \ dossier \ File.ext". P>

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;
    }
}


0 commentaires

0
votes

Presque toutes les réponses ici raccourcissent la chaîne de chemin en comptant les caractères. Mais cette approche ne tient pas compte de la largeur de chaque caractère

Ce sont 30 'W' caractères:.

WWWWWWWWWWWWWWWWWWWWWWWWWWWWWW

Ce sont 30 'i' caractères:

IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIX

Comme vous le voyez, Compter les caractères n'est pas vraiment utile.

Et il n'est pas nécessaire d'écrire votre propre code car l'API Windows a cette fonctionnalité depuis Windows 95 . Le nom de cette fonctionnalité est "Path Ellipsis". L'API Windows DrewTextW () a un drapeau dt_path_ellipsis qui fait exactement cela. Dans le fichier .NET FRAMWork Ceci est disponible (sans la nécessité d'utiliser Pinvoke) dans la classe TexTrenderer CLASSE.

Il y a 2 façons comment cela peut être utilisé: < HR>

1.) Dessinez le chemin directement dans une étiquette: xxx

Cette étiquette nécessite de tourner Autoellipsis Désactivé dans Visual Studio Designer et assignez une largeur de fixation à l'étiquette (la largeur maximale que votre chemin devrait occuper).

Vous voyez même le chemin tronqué dans Visual Studio Designer .

J'ai entré dans un long chemin qui ne rentre pas dans l'étiquette:

C: \ Windows \ installateur {40BF1E83-20EB-11D8-97C5-0009C5020658} \ ARPPRODUCTICTICONN.exe < / p>

Même dans Visual Studio Designer, il est affiché comme celui-ci:

 étiquette avec chemin ellipsis en c #


2.) raccourcir le chemin sans le dessiner à l'écran: xxx

le drapeau TextFormatFlags.Modifystring Insère un caractère '\ 0' dans la chaîne. Il est très inhabituel qu'une chaîne est modifiée dans C #. Normalement, les chaînes sont somptuelles. En effet, l'API sous-jacente DrewTextW () fonctionne de cette façon. Mais comme la chaîne n'est raccourcie et ne sera jamais plus longue, il n'y a aucun risque de débordement tampon.

Le code suivant xxx

entraînera " C: \ Windows \ installateur {40BF1E83-20EB-1 ... \ arppproducticon.exe "


0 commentaires