Come rinominare file e cartelle in .rar .7z, .tar, .zip usando C #


12

Ho un file compresso .rar .7z, .tar e .zip e voglio rinominare il nome del file fisico disponibile in sopra compresso archiviato usando C #.

Ho provato questo usando una libreria sharpcompress ma non riesco a trovare una tale funzione per rinominare il file o il nome della cartella all'interno dei file .rar .7z, .tar e .zip.

Ho anche provato ad usare la libreria DotNetZip ma il suo unico supporto. Zip vedi cosa ho provato usando la libreria 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());
            }

        }

Ma in realtà lo stesso di cui sopra voglio anche per .7z, .rar e .tar, ho provato molte librerie ma ancora non ho ottenuto alcuna soluzione accurata.

Mi aiuti per favore.


C'è un var result = Path.ChangeExtension(myffile, ".jpg");-> docs.microsoft.com/en-us/dotnet/api/…
panoskarajohn il

Ciao panoskarajohn, voglio farlo su un file all'interno dell'archivio elencato sulla domanda, c'è qualche soluzione che puoi suggerire?
Nikunj Satasiya il

Mi dispiace non avere una soluzione pulita per questo, sono sicuro che puoi fare the renamedopo l'Estratto () come zip.
Panoskarajohn,

1
Sì, voglio rinominare i file all'interno dell'archivio zippato senza estrarre l'archivio e il formato dell'archivio può essere qualsiasi cosa .rar .7z, .tar o .zip.
Nikunj Satasiya,

4
Nella maggior parte dei formati, se non in tutti, i nomi di file e directory sono codificati con una dimensione variabile nel file binario risultante, quindi non puoi semplicemente "correggerlo", devi ricostruire alcune parti del file. Le librerie standard non lo fanno. Dovrai entrare in ogni formato di archivio e vedere come puoi farlo. Compito difficile. Esempio: stackoverflow.com/questions/32829839/…
Simon Mourier,

Risposte:


3

Questa è una semplice applicazione console per rinominare i file in .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();
        }
    }
}

Grazie, Binara, per la tua risposta, ma come posso vedere nella tua preziosa risposta hai ragione, possiamo rinominare un file nell'archivio zip come mostrato nella tua risposta, ma se il mio file è grande allora? aprirà il file originale, ne copierà l'intero contenuto e scriverà lo stesso contenuto in un altro file e salverà il nuovo file, penso che sarà un processo che richiede tempo. Hai qualche altra soluzione per favore?
Nikunj Satasiya il

1
Prova Parallel.ForEach anziché Loop sequenziale. Ho modificato il codice di conseguenza.
Binara Thambugala,

Grazie Binara, proverò questa soluzione per rinominare il file all'interno dell'archivio .zip, ma c'è ancora un problema come quando modificherò qualsiasi file all'interno dell'archivio quindi comprimerà nuovamente la mia intera zip quindi c'è una soluzione per questo?
Nikunj Satasiya il

3

Considera 7zipsharp:

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

7zip stesso supporta molti formati di archivio (credo tutto quello che hai menzionato) e 7zipsharp utilizza il vero 7zip. Ho usato 7zipsharp solo per file .7z ma scommetto che funziona per altri.

Ecco un esempio di un test che sembra rinominare un file usando il metodo ModifyArchive, ti suggerisco di andare a scuola in esso:

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

Ecco il codice semplificato un po '. Si noti che il test comprime un file 7z per il suo test; è irrilevante che potrebbe essere .txt, ecc. Nota inoltre che trova il file per indice nel dizionario passato a ModifyArchive. Consulta la documentazione su come ottenere quell'indice da un nome file (forse devi eseguire il ciclo e il confronto).

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")));

Ciao FastAI, grazie per la tua risposta, ma ho anche provato questa libreria prima, ma in genere quando modifichiamo qualsiasi file all'interno dell'archivio sia il contenuto che il nome, l'archivio si sta comprimendo nuovamente, quindi ci vuole tempo per ricomprimere se l'archivio è grande . Dato che ti è stato fornito un codice di esempio nella tua risposta, penso che tu abbia estratto prima l'archivio usando 'ExtractArchive' e poi fai ulteriori modifiche, ma questa non è una soluzione affidabile, potresti suggerire qualche altro modo alternativo in cui la strega è canonica? quindi può anche migliorare performance.also.
Nikunj Satasiya il

1
@NikunjSatasiya - Mi dispiace tornare così tardi. Non c'è modo di farlo senza riscrivere l'archivio. Pensa a cosa deve succedere. C'è una directory nel file di archivio con i nomi dei file e un indice per il contenuto compresso. Questa non è una voce 'imbottita' / a lunghezza fissa in cui è possibile modificare la lunghezza. Forse potresti farlo con un editor binario, ma le indicazioni dei file e dei loro dati compressi dalla "directory" verrebbero rovinate. Forse potresti cambiare il nome del file in questo modo e mantenere la stessa lunghezza. Kludge serio, probabilmente non una caratteristica.
FastAl

1
E quindi considerare se la directory dei file è compressa o crittografata. Nessun cambiamento dall'esterno sarebbe possibile. Suppongo che se il formato del file .7z fosse stato progettato fin dall'inizio per gestire le rinominazioni sul posto, e questo fosse stato fatto da uno sviluppatore sul progetto, questo potrebbe essere possibile, ma siamo molto lontani da questo. Condivido il tuo dolore!
FastAl
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.