So benennen Sie Dateien und Ordner in .rar .7z, .tar, .zip mit C # um

12

Ich habe eine komprimierte Datei .rar .7z, .tar und .zip und möchte den physischen Dateinamen umbenennen, der in der oben komprimierten Datei verfügbar ist, die mit C # archiviert wurde.

Ich habe dies mit einer Sharpcompress-Bibliothek versucht, kann jedoch keine solche Funktion zum Umbenennen von Datei- oder Ordnernamen in .rar .7z-, .tar- und .zip-Dateien finden.

Ich habe auch versucht, die DotNetZip-Bibliothek zu verwenden, aber sie wird nur unterstützt. Zip zeigt, was ich mit der DotNetZip-Bibliothek versucht habe.

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

        }

Aber genau wie oben möchte ich auch für .7z, .rar und .tar. Ich habe viele Bibliotheken ausprobiert, aber trotzdem keine genaue Lösung gefunden.

Bitte hilf mir.

Nikunj Satasiya
quelle
Es gibt eine var result = Path.ChangeExtension(myffile, ".jpg");-> docs.microsoft.com/en-us/dotnet/api/…
panoskarajohn
Hallo panoskarajohn, ich möchte dies in dem Archiv tun, das in der Frage aufgeführt ist. Gibt es eine Lösung, die Sie vorschlagen können?
Nikunj Satasiya
Es tut mir leid, dass ich keine saubere Lösung dafür habe. Ich bin sicher, dass Sie dies the renamenach Extract () as tun können zip.
Panoskarajohn
1
Ja, ich möchte die Dateien im komprimierten Archiv umbenennen, ohne das Archiv zu extrahieren, und das Archivformat kann beliebig .rar .7z, .tar oder .zip sein.
Nikunj Satasiya
4
In den meisten Formaten, wenn nicht allen, werden Datei- und Verzeichnisnamen in der resultierenden Binärdatei mit einer variablen Größe codiert. Sie können sie also nicht einfach "patchen", sondern müssen einige Teile der Datei rekonstruieren. Standardbibliotheken machen das nicht. Sie müssen in jedes Archivformat wechseln und sehen, wie Sie dies tun können. Schwierige Aufgabe. Beispiel: stackoverflow.com/questions/32829839/…
Simon Mourier

Antworten:

3

Dies ist eine einfache Konsolenanwendung zum Umbenennen von Dateien 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();
        }
    }
}
Binara Thambugala
quelle
Vielen Dank, Binara, für Ihre Antwort, aber wie ich in Ihrer wertvollen Antwort sehen kann, haben Sie Recht. Wir können eine Datei im Zip-Archiv umbenennen, wie Sie in Ihrer Antwort gezeigt haben. Aber wenn meine Datei dann groß ist? Es wird die Originaldatei öffnen, den gesamten Inhalt daraus kopieren und denselben Inhalt in eine andere Datei schreiben und die neue Datei speichern. Ich denke, es wird ein zeitaufwändiger Prozess sein. Haben Sie bitte eine andere Lösung?
Nikunj Satasiya
1
Versuchen Sie Parallel.ForEach anstelle der sequentiellen Schleife. Ich habe den Code entsprechend geändert.
Binara Thambugala
Vielen Dank, Binara, ich werde diese Lösung ausprobieren, um die Datei im ZIP-Archiv umzubenennen. Dennoch gibt es ein Problem: Wenn ich eine Datei im Archiv ändere, wird meine gesamte Zip-Datei erneut komprimiert. Gibt es dafür eine Lösung?
Nikunj Satasiya
3

Betrachten Sie 7zipsharp:

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

7zip selbst unterstützt viele Archivformate (ich glaube alles, was Sie erwähnt haben) und 7zipsharp verwendet das echte 7zip. Ich habe 7zipsharp nur für .7z-Dateien verwendet, aber ich wette, es funktioniert für andere.

Hier ist ein Beispiel eines Tests, bei dem eine Datei mithilfe der ModifyArchive-Methode umbenannt zu werden scheint. Ich schlage vor, dass Sie darin zur Schule gehen:

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

Hier ist der Code etwas vereinfacht. Beachten Sie, dass der Test eine 7z-Datei für den Test komprimiert. Das ist unerheblich, es könnte sich um .txt usw. handeln. Beachten Sie auch, dass die Datei nach Index im an ModifyArchive übergebenen Wörterbuch gefunden wird. In der Dokumentation erfahren Sie, wie Sie diesen Index aus einem Dateinamen abrufen können (möglicherweise müssen Sie eine Schleife erstellen und vergleichen).

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
quelle
Hallo FastAI, vielen Dank für Ihre Antwort, aber ich habe diese Bibliothek bereits zuvor ausprobiert. Wenn wir jedoch eine Datei im Archiv ändern, entweder den Inhalt oder den Namen, wird das Archiv erneut komprimiert, sodass es einige Zeit dauert, bis es erneut komprimiert wird, wenn das Archiv groß ist . Da Sie in Ihrer Antwort einen Beispielcode erhalten haben, haben Sie das Archiv wahrscheinlich zuerst mit 'ExtractArchive' extrahiert und dann weitere Änderungen vorgenommen. Dies ist jedoch keine zuverlässige Lösung. Können Sie bitte eine andere alternative Methode vorschlagen, die kanonisch ist? so kann es auch die Leistung verbessern.
Nikunj Satasiya
1
@ NikunjSatasiya - Tut mir leid, dass ich so spät zurückkomme. Es gibt keine Möglichkeit, dies zu tun, ohne das Archiv neu zu schreiben. Überlegen Sie, was passieren muss. In der Archivdatei befindet sich ein Verzeichnis mit den Dateinamen und ein Index für den komprimierten Inhalt. Dies ist kein 'gepolsterter' / fester Längeneintrag, bei dem Sie die Länge ändern können. Vielleicht könnten Sie mit einem Binäreditor - aber dann würden Anzeigen von Dateien und deren komprimierten Daten aus dem 'Verzeichnis' verschraubt. Vielleicht könnten Sie den Dateinamen so ändern und die gleiche Länge beibehalten. Ernsthafter Kludge, kein Merkmal wahrscheinlich.
FastAl
1
Und dann überlegen Sie, ob das Dateiverzeichnis komprimiert oder verschlüsselt ist. Änderungen von außen wären nicht möglich. Ich nehme an, wenn das .7z-Dateiformat von Anfang an für die direkte Umbenennung konzipiert wurde und dies von einem Entwickler des Projekts durchgeführt wurde, ist dies möglicherweise möglich, aber wir sind weit davon entfernt. Ich fühle deinen Schmerz!
FastAl