C#を使用して.rar .7z、.tar、.zip内のファイルとフォルダーの名前を変更する方法


12

圧縮ファイル.rar .7z、.tar、および.zipがあり、C#を使用して上記の圧縮アーカイブで使用できる物理ファイル名を変更したい。

私は、sharpcompressライブラリを使用してこれを試しましたが、.rar .7z、.tar、および.zipファイル内のファイル名またはフォルダー名を変更するためのそのような機能を見つけることができません。

また、DotNetZipライブラリを使用してみましたが、その唯一のサポートです。Zipは、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());
            }

        }

しかし、実際には上記と同じですが、.7z、.rar、および.tarにも必要です。多くのライブラリを試しましたが、それでも正確な解決策がありませんでした。

私を助けてください。


ありvar result = Path.ChangeExtension(myffile, ".jpg");> - docs.microsoft.com/en-us/dotnet/api/...
panoskarajohn

こんにちはpanoskarajohn、質問にリストされているアーカイブ内のファイルでこれを実行したいのですが、提案できる解決策はありますか?
Nikunj Satasiya

申し訳ありませんが、これに対する明確な解決策がありませんthe rename。Extract()の後に実行できると確信していますzip
panoskarajohn

1
はい、アーカイブを抽出せずにzipアーカイブ内のファイルの名前を変更します。アーカイブ形式は、.rar .7z、.tar、または.zipにすることができます。
Nikunj Satasiya

4
ほとんどの形式では、ファイル名とディレクトリ名は、生成されるバイナリファイルで可変サイズでエンコードされているため、単に「パッチ」するだけではなく、ファイルの一部を再構築する必要があります。標準ライブラリはそれを行いません。それぞれのアーカイブ形式を理解し、その方法を確認する必要があります。難しい仕事。例:stackoverflow.com/questions/32829839/...
サイモンMourier

回答:


3

これは、.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、あなたの返答に感謝しますが、あなたの貴重な答えでわかるように、あなたが答えで示したようにzipアーカイブ内のファイルの名前を変更できますが、私のファイルが大きい場合は?それは元のファイルを開き、そこからコンテンツ全体をコピーし、同じコンテンツを別のファイルに書き込んで新しいファイルを保存します。これは時間のかかるプロセスになると思います。他に解決策はありますか?
Nikunj Satasiya

1
シーケンシャルループの代わりにParallel.ForEachを試してください。私はそれに応じてコードを変更しました。
Binara Thambugala

Binaraのおかげで、.zipアーカイブ内のファイルの名前を変更するためにこの解決策を試しますが、それでも、アーカイブ内のファイルを変更すると、zip全体が再圧縮されるので、そのための解決策はありますか?
Nikunj Satasiya

3

7zipsharpを検討してください。

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

7zip自体は多くのアーカイブ形式をサポートし(私はあなたが言ったすべてを信じます)、7zipsharpは実際の7zipを使用します。私は.7zファイルのみに7zipsharpを使用しましたが、他のファイルでも機能すると思います。

ここに、ModifyArchiveメソッドを使用してファイルの名前を変更するように見えるテストのサンプルがあります。その中で学校に行くことをお勧めします。

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

これは、コードを少し簡略化したものです。テストは、テスト用に7zファイルを圧縮することに注意してください。.txtなどの場合は重要ではありません。また、ModifyArchiveに渡されたディクショナリでインデックスによってファイルを検索することにも注意してください。ファイル名からそのインデックスを取得する方法については、ドキュメントを参照してください(おそらくループして比較する必要があります)。

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

こんにちはFastAI、ご回答ありがとうございます。以前にもこのライブラリを試したことはありますが、一般にアーカイブ内のファイルを変更するときは、コンテンツまたは名前のいずれかである場合、アーカイブは再圧縮されるため、アーカイブが大きい場合は再圧縮に時間がかかります。答えにサンプルコードが与えられているので、最初に「ExtractArchive」を使用してアーカイブを抽出し、その後さらに変更を加えたと思いますが、これは信頼できる解決策ではありません。魔女が標準的な他の方法を提案できますか?そのため、パフォーマンスを向上させることもできます。
Nikunj Satasiya

1
@NikunjSatasiya-遅くなってすみません。アーカイブを書き直すことなくこれを行う方法はありません。何が起こらなければならないかを考えてください。アーカイブファイルには、ファイル名と圧縮されたコンテンツへのインデックスを含むディレクトリがあります。これは、長さを変更できる「埋め込み」/固定長のエントリではありません。おそらくバイナリエディタを使用することもできますが、「ディレクトリ」からのファイルとその圧縮データのインデックスがねじ込まれます。たぶんあなたはそのようにファイル名を変更して同じ長さを保つことができます。深刻なクラッジ、機能はありそうもない。
FastAl

1
次に、ファイルのディレクトリが圧縮されているか暗号化されているかを検討します。外部からの変更は不可能です。.7zファイル形式が最初からインプレースの名前変更を処理するように設計されていて、これがプロジェクトの開発者によって行われた場合、これは可能かもしれませんが、私たちはそれからずっと先に進んでいます。あなたの痛みが分かります!
FastAl
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.