<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      dotnet C# 做一個(gè)壓縮包和解壓縮出來的文件夾內(nèi)容對比工具

      本文記錄的工具能夠?qū)崿F(xiàn)以下情況的對比:

      • 文件夾里面丟失了某個(gè)在壓縮包里面記錄的文件
      • 文件夾里面的文件和壓縮包里面的文件的內(nèi)容不相同
      • 文件夾多出了壓縮包里面沒有的文件

      我這里新建的是一個(gè) .NET 9 的 WPF 應(yīng)用,只有簡單的界面,理論上核心代碼可以應(yīng)用在任何 UI 框架上,甚至控制臺項(xiàng)目也可以

      界面代碼如下,非常簡單,只有兩個(gè)輸入框,用來分別輸入壓縮包文件路徑和解壓縮的文件夾路徑,和一個(gè)按鈕

          <Grid>
              <Grid HorizontalAlignment="Center" VerticalAlignment="Center">
                  <Grid.RowDefinitions>
                      <RowDefinition Height="Auto"></RowDefinition>
                      <RowDefinition Height="Auto"></RowDefinition>
                      <RowDefinition Height="Auto"></RowDefinition>
                  </Grid.RowDefinitions>
                  <Grid.ColumnDefinitions>
                      <ColumnDefinition Width="Auto"></ColumnDefinition>
                      <ColumnDefinition MinWidth="200"></ColumnDefinition>
                  </Grid.ColumnDefinitions>
      
                  <TextBlock VerticalAlignment="Center" Text="壓縮包路徑:"></TextBlock>
                  <TextBox x:Name="ZipFilePathTextBox" Grid.Row="0" Grid.Column="1" VerticalAlignment="Center" Text="C:\lindexi\Work\Source.zip"></TextBox>
      
                  <TextBlock Grid.Row="1" Grid.Column="0" Margin="0,10,0,0" VerticalAlignment="Center" Text="解壓縮文件夾:"></TextBlock>
                  <TextBox x:Name="UnzipFolderPathTextBox" Grid.Row="1" Grid.Column="1" Margin="0,10,0,0" VerticalAlignment="Center" Text="C:\lindexi\Work\Unzip\"></TextBox>
      
                  <Button Grid.Row="2" Grid.Column="1" Margin="10,10,0,10" HorizontalAlignment="Right" Content="對比" Click="Button_OnClick"></Button>
              </Grid>
          </Grid>
      

      我編寫了一個(gè) ZipComparer 類型,用這個(gè)類型可以用來對比壓縮包文件和解壓縮文件夾里面的內(nèi)容,按鈕的 Button_OnClick 代碼如下

          private async void Button_OnClick(object sender, RoutedEventArgs e)
          {
              try
              {
                  var zipCompareOptions = new ZipCompareOptions(ReturnFast: true, IgnoreExtra: false);
      
                  var result = await ZipComparer.Compare(new FileInfo(ZipFilePathTextBox.Text), new DirectoryInfo(UnzipFolderPathTextBox.Text), zipCompareOptions);
      
                  if (result.IsSuccess)
                  {
                      MessageBox.Show("文件一致");
                  }
                  else
                  {
                      var stringBuilder = new StringBuilder();
                      stringBuilder.AppendLine("文件不一致");
                      foreach (var item in result.DifferenceList)
                      {
                          stringBuilder.AppendLine(item.RelativeFilePath);
                          stringBuilder.AppendLine(item.DifferenceType.ToString());
                      }
                      MessageBox.Show(stringBuilder.ToString());
                  }
              }
              catch
              {
                  // 忽略
              }
          }
      

      核心代碼是 ZipComparer 類,代碼如下

      
      public static class ZipComparer
      {
          public static async Task<ZipCompareResult> Compare(FileInfo zipFile, DirectoryInfo unzipFolder, ZipCompareOptions options)
          {
              HashSet<string/*RelativePath*/>? visitedFileSet = null;
              if (!options.IgnoreExtra)
              {
                  visitedFileSet = [];
              }
      
              List<ZipCompareDifferenceFileInfo>? differenceList = null;
      
              await using var fileStream = zipFile.OpenRead();
              using var zipArchive = new System.IO.Compression.ZipArchive(fileStream, System.IO.Compression.ZipArchiveMode.Read, leaveOpen: true);
              foreach (var zipArchiveEntry in zipArchive.Entries)
              {
                  var name = zipArchiveEntry.FullName;
                  visitedFileSet?.Add(name);
                  var filePath = Path.Join(unzipFolder.FullName, name);
      
                  if (!File.Exists(filePath))
                  {
                      // 文件不存在
                      AddDifference(new ZipCompareDifferenceFileInfo(name, ZipCompareDifferenceType.Miss));
      
                      if (options.ReturnFast)
                      {
                          break;
                      }
                      else
                      {
                          continue;
                      }
                  }
      
                  var fileInfo = new FileInfo(filePath);
                  if (fileInfo.Length != zipArchiveEntry.Length)
                  {
                      // 文件大小不同
                      AddDifference(new ZipCompareDifferenceFileInfo(name, ZipCompareDifferenceType.ContentLengthDifference));
                      if (options.ReturnFast)
                      {
                          break;
                      }
                      else
                      {
                          continue;
                      }
                  }
      
                  // 先不引入 Crc32 對比邏輯。要真正想用,需要引入 System.IO.Hashing 包
                  //var crc32 = zipArchiveEntry.Crc32;
                  //if (crc32 != 0 && Crc32.IsSupported)
                  //{
                  //    var fileCrc32 = await GetFileZipCrcAsync(fileInfo);
                  //    if (crc32 == fileCrc32)
                  //    {
                  //        continue;
                  //    }
                  //    else
                  //    {
                  //        // CRC32 不同
                  //        AddDifference(new ZipCompareDifferenceFileInfo(name, ZipCompareDifferenceType.ContentDifference));
                  //        if (options.ReturnFast)
                  //        {
                  //            break;
                  //        }
                  //        else
                  //        {
                  //            continue;
                  //        }
                  //    }
                  //}
      
                  // 開始對比文件內(nèi)容
                  await using var zipStream = zipArchiveEntry.Open();
                  await using var currentFileStream = fileInfo.OpenRead();
                  var success = await CompareStream(zipStream, currentFileStream);
                  if (!success)
                  {
                      // 文件內(nèi)容不同
                      AddDifference(new ZipCompareDifferenceFileInfo(name, ZipCompareDifferenceType.ContentDifference));
                      if (options.ReturnFast)
                      {
                          break;
                      }
                  }
              }
      
              var isDifferenceFastReturn = options.ReturnFast && differenceList is { Count: > 0 };
      
              if (!options.IgnoreExtra
                  // 如果是快速返回,則不需要檢查額外的文件,此時(shí)已經(jīng)存在不相同的文件
                  && !isDifferenceFastReturn)
              {
                  // 如果不能忽略額外的文件,則需要檢查解壓縮文件夾中是否有額外的文件
                  Debug.Assert(visitedFileSet != null);
      
                  foreach (var file in unzipFolder.EnumerateFiles("*", new EnumerationOptions()
                  {
                      RecurseSubdirectories = true
                  }))
                  {
                      var relativePath = Path.GetRelativePath(unzipFolder.FullName, file.FullName);
                      if (!visitedFileSet.Contains(relativePath))
                      {
                          // 額外的文件
                          AddDifference(new ZipCompareDifferenceFileInfo(relativePath, ZipCompareDifferenceType.Extra));
                          if (options.ReturnFast)
                          {
                              break;
                          }
                      }
                  }
              }
      
              return new ZipCompareResult
              {
                  DifferenceList = differenceList,
              };
      
              void AddDifference(ZipCompareDifferenceFileInfo info)
              {
                  differenceList ??= new List<ZipCompareDifferenceFileInfo>();
                  differenceList.Add(info);
              }
          }
      
          //private static async ValueTask<uint> GetFileZipCrcAsync(FileInfo fileInfo)
          //{
          //    const int bufferLength = 4 * 1024;
          //    var buffer = ArrayPool<byte>.Shared.Rent(bufferLength);
          //    uint crc = 0;
          //    try
          //    {
          //        await using var fileStream = fileInfo.OpenRead();
          //        var memory = buffer.AsMemory(0, bufferLength);
      
          //        while (true)
          //        {
          //            var readLength = await fileStream.ReadAsync(memory);
      
          //            if (readLength == 0)
          //            {
          //                return crc;
          //            }
      
          //            for (int i = 0; i < readLength; i++)
          //            {
          //                crc = Crc32.ComputeCrc32(crc, memory.Span[i]);
          //            }
          //        }
          //    }
          //    finally
          //    {
          //        ArrayPool<byte>.Shared.Return(buffer);
          //    }
          //}
      
          private static async ValueTask<bool> CompareStream(Stream a, Stream b)
          {
              const int bufferLength = 4 * 1024;
              var bufferA = ArrayPool<byte>.Shared.Rent(bufferLength);
              var bufferB = ArrayPool<byte>.Shared.Rent(bufferLength);
      
              try
              {
                  while (true)
                  {
                      var memoryA = bufferA.AsMemory(0, bufferLength);
      
                      var readLength = await a.ReadAsync(memoryA);
                      if (readLength == 0)
                      {
                          // 讀取完畢
                          return true;
                      }
      
                      var memoryB = bufferB.AsMemory(0, readLength);
                      await b.ReadExactlyAsync(memoryB);
      
                      if (!memoryA.Span.Slice(0, readLength).SequenceEqual(memoryB.Span))
                      {
                          return false;
                      }
                  }
              }
              finally
              {
                  ArrayPool<byte>.Shared.Return(bufferA);
                  ArrayPool<byte>.Shared.Return(bufferB);
              }
          }
      }
      
      /// <summary>
      /// 比較的選項(xiàng)
      /// </summary>
      /// <param name="ReturnFast">找到第一個(gè)差異就立刻結(jié)束</param>
      /// <param name="IgnoreExtra">忽略額外的文件。忽略解壓縮文件夾存在,但壓縮包不存在的文件</param>
      public readonly record struct ZipCompareOptions(bool ReturnFast, bool IgnoreExtra);
      
      public readonly record struct ZipCompareResult
      {
          [MemberNotNullWhen(false, nameof(DifferenceList))]
          public bool IsSuccess => DifferenceList is null || DifferenceList.Count == 0;
      
          public IReadOnlyList<ZipCompareDifferenceFileInfo>? DifferenceList { get; internal init; }
      }
      
      public readonly record struct ZipCompareDifferenceFileInfo(string RelativeFilePath, ZipCompareDifferenceType DifferenceType);
      
      public enum ZipCompareDifferenceType
      {
          /// <summary>
          /// 文件不存在
          /// </summary>
          Miss,
      
          /// <summary>
          /// 文件大小不同
          /// </summary>
          ContentLengthDifference,
      
          /// <summary>
          /// 文件內(nèi)容不同
          /// </summary>
          ContentDifference,
      
          /// <summary>
          /// 額外的文件,即解壓縮文件夾存在,但壓縮包不存在的文件
          /// </summary>
          Extra,
      }
      

      本文代碼放在 githubgitee 上,可以使用如下命令行拉取代碼。我整個(gè)代碼倉庫比較龐大,使用以下命令行可以進(jìn)行部分拉取,拉取速度比較快

      先創(chuàng)建一個(gè)空文件夾,接著使用命令行 cd 命令進(jìn)入此空文件夾,在命令行里面輸入以下代碼,即可獲取到本文的代碼

      git init
      git remote add origin https://gitee.com/lindexi/lindexi_gd.git
      git pull origin 88e3c7fe8009b4ad239481404c2c4b5089f05953
      

      以上使用的是國內(nèi)的 gitee 的源,如果 gitee 不能訪問,請?zhí)鎿Q為 github 的源。請?jiān)诿钚欣^續(xù)輸入以下代碼,將 gitee 源換成 github 源進(jìn)行拉取代碼。如果依然拉取不到代碼,可以發(fā)郵件向我要代碼

      git remote remove origin
      git remote add origin https://github.com/lindexi/lindexi_gd.git
      git pull origin 88e3c7fe8009b4ad239481404c2c4b5089f05953
      

      獲取代碼之后,進(jìn)入 WPFDemo/CardawnarheaCahichemga 文件夾,即可獲取到源代碼

      更多技術(shù)博客,請參閱 博客導(dǎo)航

      posted @ 2025-04-10 09:04  lindexi  閱讀(51)  評論(0)    收藏  舉報(bào)
      主站蜘蛛池模板: 国产中文99视频在线观看| 国产亚洲精品第一综合另类灬| 国产精品老年自拍视频| 国产精品久久蜜臀av| 国产无遮挡又黄又爽不要vip软件| 人妻少妇精品久久| 国产福利社区一区二区| 欧美 亚洲 另类 丝袜 自拍 动漫| 美女一区二区三区亚洲麻豆| 99在线精品国自产拍中文字幕| 国产精品一区二区不卡视频| 亚洲欧洲精品国产二码| 国产国语一级毛片| 国产999久久高清免费观看| 一区二区免费高清观看国产丝瓜| 中文字幕在线视频不卡| 国产一区二区三区麻豆视频| 亚洲AV毛片一区二区三区| 美女爽到高潮嗷嗷嗷叫免费网站| 黑人异族巨大巨大巨粗| 精品人妻日韩中文字幕| 国产午夜福利高清在线观看 | 中文字幕精品久久久久人妻红杏1| 亚洲 日本 欧洲 欧美 视频| 亚洲国产永久精品成人麻豆| 少妇性l交大片| 久久人妻国产精品| 欧美激情一区二区三区成人| 久久人与动人物a级毛片| 在线综合亚洲欧洲综合网站| 国产精品国产片在线观看| 国产精品二区中文字幕| 荥经县| 人人妻碰人人免费| 午夜免费无码福利视频麻豆| 久久精品免视看国产成人| 亚洲美免无码中文字幕在线| 九九热精彩视频在线免费| 国产一级毛片高清完整视频版| 国产精品一品二区三区日韩| 波多野结衣的av一区二区三区|