zoukankan      html  css  js  c++  java
  • 从读取Excel文件引申出的问题(下)

    从上一篇的:从读取Excel文件引申出的问题(上)中,对于从Excel文件中抓取的图片读取速度太慢的,问题主要来源于IComObject对象在经过了Copy和Paste后,造成了对内存及各种计算上的消耗后,速度已大大下降鸟。这几天研究来研究去,也没个结果,索性将这个问题再次提起,借众人之力。

    在这一次的实验中,我借助了Marshal类的功能,提取IcomObject对象的指针,通过指针,希望读取Excel文件中图形对象的内容,代码如下:

    代码
    byte[] bytes =null;
    List
    <byte> bs =new List<byte>();
    IntPtr intptr
    = item.GetType().TypeHandle.Value;
    byte b =1;
    int s =0;
    while (b >0) {b = Marshal.ReadByte(intptr, s * Marshal.SizeOf(typeof(IntPtr))); s++;bs.Add(b);}
    bytes
    = bs.ToArray();

    然后 将读取到的对象内容通过流的形式写入文件。

    using (FileStream fs =new FileStream(@"D:\temp\"+ row +".jpg", FileMode.Create, FileAccess.Write))
    {
    fs.Write(bytes,
    0, bytes.Length);
    fs.Flush();
    fs.Close();
    }

    最后发现太失败了,内容是读取出来了,但是基本上只读取了10K的内容,图像是无法显示的。这是什么问题呢?

    本来嘛,希望通过Marshal来获取对象大小的,最后发现无效,抛出了ArgumentException异常:

    int len = Marshal.SizeOf(typeof(Excel.Shape));
    类型“Microsoft.Office.Interop.Excel.Shape”不能作为非托管结构进行封送处理;无法计算有意义的大小或偏移量。

    算了,还是走回老路吧,最后被逼得没办法了,来招狠的,在图像保存格式上下功夫,这次我不再把获取到的Shape强制转换为BitMap对象,因为从DataObject对象中,我们可以获取到剪贴板对象中支持转换的对象格式,如下:

    这下好了,我直接从DataObject对象中获取图片对象,即Image对象,再直接保存,保存的时候会发生一点小问题,即图像格式的问题。

    代码
    DataObject data = (DataObject)Clipboard.GetDataObject();
    Image img
    = data.GetImage();
    img.Save(
    @"D:\temp\aa\"+ row +".jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
    Clipboard.Clear();
    // 清除剪贴板内容

    Clipboard.Clear();  //  清除剪贴板内容

    通过对比,发现保存为GIF格式可获取最高压缩级,Bmp为高保真级存储,消耗的内存和时间还真不是一般的多,当然,我选择了中庸方案:Jpeg格式。下面的数据为同一幅18KB的图片在各种格式下的存储大小,即所谓的压缩比了。

    Jpeg:10KB
    Bmp:145KB
    PNG:18KB
    GIF:7KB
    Tiff:29KB

    到最后的完整代码实际上为六行代码。

    代码
    item.Copy();
    DataObject data
    = (DataObject)Clipboard.GetDataObject();
    Image img
    = data.GetImage();
    img.Save(
    @"D:\temp\aa\"+ row +".jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
    Clipboard.Clear();
    img.Dispose();

    但是还是那句话,效率上还是上不去,唯一可做的是,通过把图片进行有损压缩,达到一定程度的提高速度,但是这不是最终想的结果,因为Image对象在写入文件时,默认单次写入大小最大为:1KB。不知道还有什么可以提高地方。

  • 相关阅读:
    Java 蓝桥杯 算法训练 貌似化学
    Java 蓝桥杯 算法训练 貌似化学
    Java 蓝桥杯 算法训练 字符串的展开 (JAVA语言实现)
    Java 蓝桥杯 算法训练 字符串的展开 (JAVA语言实现)
    Java 蓝桥杯 算法训练 字符串的展开 (JAVA语言实现)
    Java 蓝桥杯 算法训练 字符串的展开 (JAVA语言实现)
    Java 蓝桥杯 算法训练 字符串的展开 (JAVA语言实现)
    JAVA-蓝桥杯-算法训练-字符串变换
    Ceph:一个开源的 Linux PB 级分布式文件系统
    shell 脚本监控程序是否正在执行, 如果没有执行, 则自动启动该进程
  • 原文地址:https://www.cnblogs.com/viter/p/1644102.html
Copyright © 2011-2022 走看看