zip 读取代码 (备份)
5小时前

using System;
using System.Collections.ObjectModel;
using System.IO;
using System.IO.Compression;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Imaging;
using System.Collections.Generic;

namespace ImageViewer;

/// <summary>
/// 图片项数据模型
/// </summary>
public class ImageItem
{
    public string FileName { get; set; }
    public BitmapImage Thumbnail { get; set; }
    public BitmapImage FullImage { get; set; }
}

/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    private ObservableCollection<ImageItem> images = new ObservableCollection<ImageItem>();
    
    public MainWindow()
    {
        InitializeComponent();
        
        // 加载图片
        LoadImagesFromZip();
    }
    
    /// <summary>
    /// 从ZIP文件加载图片
    /// </summary>
    private void LoadImagesFromZip()
    {
        try
        {
            statusText.Text = "正在读取PRGUSE文件...";
            
            string zipPath = @"c:\Users\ye\Desktop\ceshixiangmu\prguse.zip";
            
            if (!File.Exists(zipPath))
            {
                statusText.Text = "错误:prguse.zip文件不存在";
                MessageBox.Show("prguse.zip文件不存在", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }
            
            // 直接尝试读取文件,不检查ZIP格式
            statusText.Text = "正在尝试读取文件...";
            
            try
            {
                // 尝试作为标准ZIP文件打开
                using (ZipArchive archive = ZipFile.OpenRead(zipPath))
                {
                    int imageCount = 0;
                    
                    // 遍历ZIP中的所有条目
                    foreach (ZipArchiveEntry entry in archive.Entries)
                    {
                        // 检查是否为图片文件
                        if (IsImageFile(entry.Name))
                        {
                            statusText.Text = $"正在加载图片:{entry.Name}...";
                            
                            // 创建图片项
                            ImageItem imageItem = new ImageItem
                            {
                                FileName = entry.Name
                            };
                            
                            // 读取图片数据
                            using (Stream stream = entry.Open())
                            {
                                // 创建完整图片
                                BitmapImage fullImage = new BitmapImage();
                                fullImage.BeginInit();
                                fullImage.StreamSource = stream;
                                fullImage.CacheOption = BitmapCacheOption.OnLoad;
                                fullImage.EndInit();
                                fullImage.Freeze();
                                
                                imageItem.FullImage = fullImage;
                                
                                // 重置流位置,创建缩略图
                                stream.Position = 0;
                                BitmapImage thumbnail = new BitmapImage();
                                thumbnail.BeginInit();
                                thumbnail.StreamSource = stream;
                                thumbnail.CacheOption = BitmapCacheOption.OnLoad;
                                thumbnail.DecodePixelWidth = 120;
                                thumbnail.EndInit();
                                thumbnail.Freeze();
                                
                                imageItem.Thumbnail = thumbnail;
                            }
                            
                            // 添加到集合
                            images.Add(imageItem);
                            imageCount++;
                        }
                    }
                    
                    // 设置列表数据源
                    imageList.ItemsSource = images;
                    
                    // 自动选择第一张图片
                    if (images.Count > 0)
                    {
                        imageList.SelectedIndex = 0;
                    }
                    
                    statusText.Text = $"共加载 {imageCount} 张图片";
                }
            }
            catch (Exception zipEx)
            {
                // 如果标准ZIP读取失败,检查是否为SDO自定义资源格式
                statusText.Text = "标准ZIP读取失败,检查SDO自定义格式...";
                
                // 检查文件头是否为SDO格式
                bool isSdoFormat = CheckSdoFormat(zipPath);
                
                if (isSdoFormat)
                {
                    // 尝试使用自定义SDO解析器
                    statusText.Text = "尝试使用SDO自定义格式解析...";
                    
                    // 实现简单的SDO格式解析
                    if (TryParseSdoFormat(zipPath))
                    {
                        return;
                    }
                    else
                    {
                        statusText.Text = "错误:SDO格式解析失败";
                        MessageBox.Show("SDO格式解析失败,当前版本不支持此格式\n\n建议使用专业的SDO资源解析工具", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                    }
                }
                else
                {
                    statusText.Text = "错误:不支持的文件格式";
                    MessageBox.Show($"不支持的文件格式,错误:{zipEx.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        }
        catch (Exception ex)
        {
            statusText.Text = $"错误:{ex.Message}";
            MessageBox.Show($"加载图片失败:{ex.Message}\n\n{ex.StackTrace}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
        }
    }
    
    /// <summary>
    /// 检查是否为SDO自定义资源格式
    /// </summary>
    private bool CheckSdoFormat(string filePath)
    {
        using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
        {
            byte[] header = new byte[12];
            int bytesRead = fs.Read(header, 0, header.Length);
            
            if (bytesRead < 12)
                return false;
            
            // 检查文件头是否为"www.sdo.com" + null + 0x3B
            string sdoHeader = Encoding.ASCII.GetString(header, 0, 11);
            return sdoHeader.StartsWith("www.sdo.com");
        }
    }
    
    /// <summary>
    /// 尝试解析SDO自定义资源格式
    /// </summary>
    private bool TryParseSdoFormat(string filePath)
    {
        try
        {
            // SDO格式解析:直接读取文件中的图片数据
            using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
            {
                // 读取文件头
                byte[] header = new byte[12];
                fs.Read(header, 0, header.Length);
                
                statusText.Text = "正在解析SDO资源格式...";
                
                // 搜索文件中的所有PNG图片
                List<long> pngOffsets = FindPngImages(fs);
                
                if (pngOffsets.Count == 0)
                {
                    statusText.Text = "错误:未找到PNG图片";
                    return false;
                }
                
                int imageCount = 0;
                
                // 读取每个PNG图片
                foreach (long offset in pngOffsets)
                {
                    fs.Seek(offset, SeekOrigin.Begin);
                    
                    // 读取PNG图片数据
                    byte[] pngData = ReadPngImage(fs);
                    if (pngData != null && pngData.Length > 0)
                    {
                        statusText.Text = $"正在加载图片 {imageCount + 1}...";
                        
                        // 创建图片项
                        ImageItem imageItem = new ImageItem
                        {
                            FileName = $"image_{imageCount + 1}.png"
                        };
                        
                        // 创建完整图片
                        using (MemoryStream ms = new MemoryStream(pngData))
                        {
                            BitmapImage fullImage = new BitmapImage();
                            fullImage.BeginInit();
                            fullImage.StreamSource = ms;
                            fullImage.CacheOption = BitmapCacheOption.OnLoad;
                            fullImage.EndInit();
                            fullImage.Freeze();
                            
                            imageItem.FullImage = fullImage;
                        }
                        
                        // 创建缩略图
                        using (MemoryStream ms = new MemoryStream(pngData))
                        {
                            BitmapImage thumbnail = new BitmapImage();
                            thumbnail.BeginInit();
                            thumbnail.StreamSource = ms;
                            thumbnail.CacheOption = BitmapCacheOption.OnLoad;
                            thumbnail.DecodePixelWidth = 120;
                            thumbnail.EndInit();
                            thumbnail.Freeze();
                            
                            imageItem.Thumbnail = thumbnail;
                        }
                        
                        // 添加到集合
                        images.Add(imageItem);
                        imageCount++;
                    }
                }
                
                // 设置列表数据源
                imageList.ItemsSource = images;
                
                // 自动选择第一张图片
                if (images.Count > 0)
                {
                    imageList.SelectedIndex = 0;
                }
                
                statusText.Text = $"共加载 {imageCount} 张图片";
                return true;
            }
        }
        catch (Exception ex)
        {
            statusText.Text = $"SDO解析错误:{ex.Message}";
            return false;
        }
    }
    
    /// <summary>
    /// 查找文件中的所有PNG图片
    /// </summary>
    private List<long> FindPngImages(FileStream fs)
    {
        List<long> pngOffsets = new List<long>();
        
        // PNG文件签名
        byte[] pngSignature = new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A };
        
        // 从当前位置开始搜索
        long currentPosition = fs.Position;
        byte[] buffer = new byte[4096];
        int bytesRead;
        
        while ((bytesRead = fs.Read(buffer, 0, buffer.Length)) > 0)
        {
            // 搜索缓冲区中的PNG签名
            for (int i = 0; i < bytesRead - 7; i++)
            {
                bool isPng = true;
                for (int j = 0; j < 8; j++)
                {
                    if (buffer[i + j] != pngSignature[j])
                    {
                        isPng = false;
                        break;
                    }
                }
                
                if (isPng)
                {
                    // 计算PNG文件在原始文件中的偏移量
                    long pngOffset = currentPosition + i;
                    pngOffsets.Add(pngOffset);
                }
            }
            
            // 保留缓冲区末尾的7个字节,用于下一次搜索
            long remainingBytes = currentPosition + bytesRead - fs.Length;
            if (remainingBytes < 0)
            {
                fs.Seek(-7, SeekOrigin.Current);
                currentPosition = fs.Position;
            }
        }
        
        return pngOffsets;
    }
    
    /// <summary>
    /// 读取PNG图片数据
    /// </summary>
    private byte[] ReadPngImage(FileStream fs)
    {
        try
        {
            // 保存当前位置
            long startPosition = fs.Position;
            
            // 读取PNG文件头
            byte[] header = new byte[8];
            fs.Read(header, 0, header.Length);
            
            // 检查是否为PNG文件
            if (header[0] != 0x89 || header[1] != 0x50 || header[2] != 0x4E || header[3] != 0x47)
            {
                return null;
            }
            
            // 读取PNG块,直到找到IEND块
            while (true)
            {
                // 读取块长度(4字节,大端序)
                byte[] lengthBytes = new byte[4];
                fs.Read(lengthBytes, 0, 4);
                int length = (lengthBytes[0] << 24) | (lengthBytes[1] << 16) | (lengthBytes[2] << 8) | lengthBytes[3];
                
                // 读取块类型(4字节)
                byte[] typeBytes = new byte[4];
                fs.Read(typeBytes, 0, 4);
                string type = Encoding.ASCII.GetString(typeBytes);
                
                // 跳过块数据和CRC
                fs.Seek(length + 4, SeekOrigin.Current);
                
                // 检查是否为IEND块
                if (type == "IEND")
                {
                    break;
                }
            }
            
            // 计算PNG图片大小
            long endPosition = fs.Position;
            long pngSize = endPosition - startPosition;
            
            // 读取完整的PNG图片数据
            fs.Seek(startPosition, SeekOrigin.Begin);
            byte[] pngData = new byte[pngSize];
            fs.Read(pngData, 0, (int)pngSize);
            
            return pngData;
        }
        catch (Exception ex)
        {
            statusText.Text = $"读取PNG图片错误:{ex.Message}";
            return null;
        }
    }
    
    /// <summary>
    /// 从ZIP文件中获取所有图片名称
    /// </summary>
    private List<string> GetAllImageNamesFromZip(string zipPath)
    {
        List<string> imageNames = new List<string>();
        
        using (ZipArchive archive = ZipFile.OpenRead(zipPath))
        {
            foreach (ZipArchiveEntry entry in archive.Entries)
            {
                if (IsImageFile(entry.Name))
                {
                    imageNames.Add(entry.Name);
                }
            }
        }
        
        return imageNames;
    }
    
    /// <summary>
    /// 检查是否为标准ZIP文件
    /// </summary>
    private bool IsStandardZipFile(string filePath)
    {
        using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
        {
            if (fs.Length < 4) return false;
            
            byte[] header = new byte[4];
            fs.Read(header, 0, 4);
            
            // 标准ZIP文件的头部是 "50 4B 03 04"
            return header[0] == 0x50 && header[1] == 0x4B && header[2] == 0x03 && header[3] == 0x04;
        }
    }
    
    /// <summary>
    /// 获取文件头部信息
    /// </summary>
    private string GetFileHeader(string filePath)
    {
        using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
        {
            byte[] header = new byte[16];
            int bytesRead = fs.Read(header, 0, 16);
            
            // 创建十六进制字符串
            string hex = BitConverter.ToString(header, 0, bytesRead).Replace("-", " ");
            
            // 创建ASCII字符串
            StringBuilder asciiBuilder = new StringBuilder();
            for (int i = 0; i < bytesRead; i++)
            {
                byte b = header[i];
                if (b >= 32 && b <= 126) // 可打印ASCII字符
                {
                    asciiBuilder.Append((char)b);
                }
                else
                {
                    asciiBuilder.Append('.');
                }
            }
            string ascii = asciiBuilder.ToString();
            
            return $"{hex} (ASCII: '{ascii}')";
        }
    }
    
    /// <summary>
    /// 检查是否为图片文件
    /// </summary>
    private bool IsImageFile(string fileName)
    {
        string extension = Path.GetExtension(fileName).ToLower();
        return extension == ".jpg" || extension == ".jpeg" || extension == ".png" || 
               extension == ".bmp" || extension == ".gif" || extension == ".tif" || extension == ".tiff";
    }
    
    /// <summary>
    /// 图片列表选择变更事件
    /// </summary>
    private void imageList_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        if (imageList.SelectedItem is ImageItem selectedImage)
        {
            imagePreview.Source = selectedImage.FullImage;
            statusText.Text = $"正在查看:{selectedImage.FileName}";
        }
    }
}
最新回复 (0)
返回