Comment renommer des fichiers et des dossiers en .rar .7z, .tar, .zip en utilisant C #

12

J'ai un fichier compressé .rar .7z, .tar et .zip et je veux renommer le nom de fichier physique disponible en compressé ci-dessus en utilisant C #.

J'ai essayé cela en utilisant une bibliothèque sharpcompress mais je ne trouve pas une telle fonctionnalité pour renommer un fichier ou un nom de dossier dans .rar .7z, .tar et .zip.

J'ai également essayé d'utiliser la bibliothèque DotNetZip mais son seul support.Zip voir ce que j'ai essayé d'utiliser la bibliothèque DotNetZip.

private static void RenameZipEntries(string file)
        {
            try
            {
                int renameCount = 0;
                using (ZipFile zip2 = ZipFile.Read(file))
                {

                    foreach (ZipEntry e in zip2.ToList())
                    {
                        if (!e.IsDirectory)
                        {
                            if (e.FileName.EndsWith(".txt"))
                            {
                                var newname = e.FileName.Split('.')[0] + "_new." + e.FileName.Split('.')[1];
                                e.FileName = newname;
                                e.Comment = "renamed";
                                zip2.Save();
                                renameCount++;
                            }
                        }
                    }
                    zip2.Comment = String.Format("This archive has been modified. {0} files have been renamed.", renameCount);
                    zip2.Save();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }

        }

Mais en fait, la même chose que ci-dessus, je veux aussi pour .7z, .rar et .tar, j'ai essayé de nombreuses bibliothèques mais je n'ai toujours pas obtenu de solution précise.

Aidez-moi, s'il vous plaît.

Nikunj Satasiya
la source
Il y a un var result = Path.ChangeExtension(myffile, ".jpg");-> docs.microsoft.com/en-us/dotnet/api/…
panoskarajohn
Salut panoskarajohn, je veux le faire sur fichier dans l'archive répertoriée sur la question, y a-t-il une solution que vous pouvez suggérer?
Nikunj Satasiya
Je suis désolé, je n'ai pas de solution propre pour cela, je suis sûr que vous pouvez le faire the renameaprès l'extraction () en tant que zip.
panoskarajohn
1
Oui, je veux renommer les fichiers à l'intérieur de l'archive zippée sans extraire l'archive et le formatage de l'archive peut être n'importe quoi .rar .7z, .tar ou .zip.
Nikunj Satasiya
4
Dans la plupart des formats, sinon tous, les noms de fichiers et de répertoires sont codés avec une taille variable dans le fichier binaire résultant, vous ne pouvez donc pas simplement le "patcher", vous devez reconstruire certaines parties du fichier. Les bibliothèques standard ne font pas cela. Vous devrez entrer dans chaque format d'archive et voir comment vous pouvez le faire. Tâche difficile. Exemple: stackoverflow.com/questions/32829839/…
Simon Mourier

Réponses:

3

Il s'agit d'une application console simple pour renommer des fichiers en .zip

using System;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;

namespace Renamer
{
    class Program
    {
        static void Main(string[] args)
        {
            using var archive = new ZipArchive(File.Open(@"<Your File>.zip", FileMode.Open, FileAccess.ReadWrite), ZipArchiveMode.Update);
            var entries = archive.Entries.ToArray();

            //foreach (ZipArchiveEntry entry in entries)
            //{
            //    //If ZipArchiveEntry is a directory it will have its FullName property ending with "/" (e.g. "some_dir/") 
            //    //and its Name property will be empty string ("").
            //    if (!string.IsNullOrEmpty(entry.Name))
            //    {
            //        var newEntry = archive.CreateEntry($"{entry.FullName.Replace(entry.Name, $"{RandomString(10, false)}{Path.GetExtension(entry.Name)}")}");
            //        using (var a = entry.Open())
            //        using (var b = newEntry.Open())
            //            a.CopyTo(b);
            //        entry.Delete();
            //    }
            //}

            Parallel.ForEach(entries, entry =>
            {
                //If ZipArchiveEntry is a directory it will have its FullName property ending with "/" (e.g. "some_dir/") 
                //and its Name property will be empty string ("").
                if (!string.IsNullOrEmpty(entry.Name))
                {
                    ZipArchiveEntry newEntry = archive.CreateEntry($"{entry.FullName.Replace(entry.Name, $"{RandomString(10, false)}{Path.GetExtension(entry.Name)}")}");
                    using (var a = entry.Open())
                    using (var b = newEntry.Open())
                        a.CopyTo(b);
                    entry.Delete();
                }
            });
        }

        //To Generate random name for the file
        public static string RandomString(int size, bool lowerCase)
        {
            StringBuilder builder = new StringBuilder();
            Random random = new Random();
            char ch;
            for (int i = 0; i < size; i++)
            {
                ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65)));
                builder.Append(ch);
            }
            if (lowerCase)
                return builder.ToString().ToLower();
            return builder.ToString();
        }
    }
}
Binara Thambugala
la source
Merci, Binara, pour votre réponse mais comme je peux le voir dans votre précieuse réponse, vous avez raison, nous pouvons renommer un fichier dans l'archive zip comme vous l'avez montré dans votre réponse, mais si mon fichier est volumineux, alors? il ouvrira le fichier d'origine, copiera tout le contenu de celui-ci et écrit le même contenu dans un autre fichier et enregistrera le nouveau fichier, je pense que ce sera un processus long. Avez-vous une autre solution, s'il vous plaît?
Nikunj Satasiya
1
Essayez Parallel.ForEach au lieu de boucle séquentielle. J'ai changé le code en conséquence.
Binara Thambugala
Merci Binara, je vais essayer cette solution pour renommer le fichier dans l'archive .zip, mais encore, il y a un problème comme quand je modifierai n'importe quel fichier dans l'archive alors il recompressera tout mon zip alors y a-t-il une solution pour cela?
Nikunj Satasiya
3

Considérez 7zipsharp:

https://www.nuget.org/packages/SevenZipSharp.Net45/

7zip lui-même prend en charge de nombreux formats d'archives (je crois que tout ce que vous avez mentionné) et 7zipsharp utilise le vrai 7zip. J'ai utilisé 7zipsharp pour les fichiers .7z uniquement, mais je parie que cela fonctionne pour les autres.

Voici un exemple de test qui semble renommer un fichier à l'aide de la méthode ModifyArchive, je vous suggère d'y aller à l'école:

https://github.com/squid-box/SevenZipSharp/blob/f2bee350e997b0f4b1258dff520f36409198f006/SevenZip.Tests/SevenZipCompressorTests.cs

Voici le code un peu simplifié. Notez que le test comprime un fichier 7z pour son test; cela n'a pas d'importance, il peut s'agir de .txt, etc. Notez également qu'il trouve le fichier par index dans le dictionnaire passé à ModifyArchive. Consultez la documentation pour savoir comment obtenir cet index à partir d'un nom de fichier (vous devrez peut-être boucler et comparer).

var compressor = new SevenZipCompressor( ... snip ...);

compressor.CompressFiles("tmp.7z", @"Testdata\7z_LZMA2.7z");

compressor.ModifyArchive("tmp.7z", new Dictionary<int, string> { { 0, "renamed.7z" }});

using (var extractor = new SevenZipExtractor("tmp.7z"))
{
    Assert.AreEqual(1, extractor.FilesCount);
    extractor.ExtractArchive(OutputDirectory);
}

Assert.IsTrue(File.Exists(Path.Combine(OutputDirectory, "renamed.7z")));
Assert.IsFalse(File.Exists(Path.Combine(OutputDirectory, "7z_LZMA2.7z")));
FastAl
la source
Salut FastAI, Merci pour votre réponse, mais j'ai également essayé cette bibliothèque auparavant, mais généralement lorsque nous modifions un fichier à l'intérieur de l'archive, que ce soit son contenu ou son nom, l'archive est recompressée, donc il faut du temps pour la recompresser si l'archive est volumineuse . Comme vous recevez un exemple de code dans votre réponse, je pense que vous avez d'abord extrait l'archive à l'aide de 'ExtractArchive', puis vous apportez des modifications supplémentaires, mais ce n'est pas une solution fiable, pouvez-vous suggérer une autre manière alternative qui soit canonique? il peut donc également améliorer les performances.
Nikunj Satasiya
1
@NikunjSatasiya - Désolé de revenir si tard. Il n'y a aucun moyen de le faire sans réécrire l'archive. Pensez à ce qui doit arriver. Il y a un répertoire dans le fichier d'archive avec les noms de fichiers et un index du contenu compressé. Ce n'est pas une entrée de longueur «rembourrée» / fixe où vous pouvez modifier la longueur. Peut-être que vous pourriez avec un éditeur binaire - mais alors les indices de fichiers et leurs données compressées du «répertoire» seraient vissés. Vous pourriez peut-être changer le nom de fichier comme ça et garder la même longueur. Coup sérieux, peu probable.
FastAl
1
Et puis, vérifiez si le répertoire des fichiers est compressé ou chiffré. Aucun changement de l'extérieur ne serait possible. Je suppose que si le format de fichier .7z a été conçu dès le début pour gérer les renommages sur place, et cela a été fait par un développeur du projet, cela pourrait être possible, mais nous sommes loin de cela. Je ressens ta douleur!
FastAl