在c#中处理大量图像文件的最快或最有效的方法

时间:2014-03-06 20:20:41

标签: c#

我必须阅读并找出存储在我们网络中的大约450,000个图像文件的压缩类型。这是我到目前为止所做的,它正在按预期工作,但我观察到的是在一小时内处理大约2000个文件。是否可以更加优化以使其更有效。缓慢的原因之一可能是因为文件是从共享网络位置读取的,但是没有解决方法。

任何建议都将受到赞赏。

using System;
using System.Configuration;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.Globalization;
using System.Data;
using System.IO;
using FileHelpers;
using System.Threading.Tasks;

namespace CompressionTypeOfEDMSTiffs
{
    public static class ImageProcessor
    {
        private static readonly object lockObject = new object();

        public static void Process()
        {
            string docNumber = "";
            try
            {
                Stopwatch _stopwatch = new Stopwatch();

                _stopwatch.Start();

                var filename = ConfigurationManager.AppSettings["filePath"].Trim();

                var dtCsv = CsvEngine.CsvToDataTable(filename, ',');

                dtCsv.Columns.Add("CompressionType");
                dtCsv.Columns["CompressionType"].SetOrdinal(dtCsv.Columns.Count - 1);

                //One-by one
                //for (var rowNum = 0; rowNum < dtCsv.Rows.Count; rowNum++)
                //{
                //    var imgPath = dtCsv.Rows[rowNum]["Path"].ToString();

                //    if (!string.IsNullOrWhiteSpace(imgPath) && imgPath.LastIndexOf(".") != -1)
                //    {
                //        if (imgPath.Substring(imgPath.LastIndexOf(".")).ToUpper().Equals(".TIF"))
                //        {
                //            docNumber = dtCsv.Rows[rowNum]["DOCNUMBER"].ToString();

                //            var compression = GetCompressionTypeFromImage(imgPath);

                //            dtCsv.Rows[rowNum]["CompressionType"] = compression;

                //            //if (Enum.IsDefined(typeof(CompressionTypes), compression))
                //            //    dtCsv.Rows[rowNum]["CompressionType"] = compression.ToString();
                //            //else
                //            //{
                //            //    dtCsv.Rows[rowNum]["CompressionType"] = "UnRecognised";
                //            //}

                //            Console.WriteLine(string.Format("Counter = {0}, docnumber = {1} , path = {2},  CT = {3}", rowNum, docNumber, imgPath, compression));
                //        }
                //    }
                //}

                //Multi-tasking
                Parallel.ForEach(dtCsv.AsEnumerable(), drow =>
                {
                    var imgPath = drow["Path"].ToString();

                    if (!string.IsNullOrWhiteSpace(imgPath) && imgPath.LastIndexOf(".") != -1)
                    {
                        if (imgPath.Substring(imgPath.LastIndexOf(".")).ToUpper().Equals(".TIF"))
                        {
                            docNumber = drow["DOCNUMBER"].ToString();

                            var compression = GetCompressionTypeFromImage(imgPath);

                            drow["CompressionType"] = compression;

                            Console.WriteLine(string.Format("docnumber = {0} , path = {1},  CT = {2}", docNumber, imgPath, compression));
                        }
                    }
                });

                if (File.Exists(filename))
                    File.Delete(filename);

                //write CSV
                var tempTable = dtCsv.Copy();
                var headerRow = tempTable.NewRow();

                foreach (DataColumn col in dtCsv.Columns)
                    headerRow[col.ColumnName] = col.ColumnName;

                headerRow[headerRow.ItemArray.Length - 1] = "CompressionType";

                tempTable.Rows.InsertAt(headerRow, 0);

                CsvEngine.DataTableToCsv(tempTable, ConfigurationManager.AppSettings["filePath"].Trim());

                _stopwatch.Stop();

                Console.WriteLine(string.Format("Time elapsed in the process {0} minutes", _stopwatch.Elapsed.TotalMinutes.ToString("#.##")));

                Console.ReadLine();
            }
            catch (Exception exception)
            {
                Console.WriteLine(!string.IsNullOrWhiteSpace(docNumber)
                                      ? string.Format("Error in document No {0} and the error is {1} stack trace {2}",
                                                      docNumber, exception.Message, exception.StackTrace)
                                      : string.Format("Error is {0} stack trace {1}", exception.Message,
                                                      exception.StackTrace));
                Console.ReadLine();
            }
        }


        private static string GetCompressionTypeFromImage(string path)
        {
            string compression = "";
            try
            {
                lock (lockObject)
                {
                    using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read))
                    {
                        using (Image sourceImage = Image.FromStream(fs))
                        {
                            var compressionTagIndex = Array.IndexOf(sourceImage.PropertyIdList, 0x103);
                            PropertyItem compressionTag = sourceImage.PropertyItems[compressionTagIndex];

                            var compressionType = (CompressionTypes)Enum.Parse(typeof(CompressionTypes),
                                                            BitConverter.ToInt16(compressionTag.Value, 0).ToString(CultureInfo.InvariantCulture));

                            if (Enum.IsDefined(typeof(CompressionTypes), compressionType))
                                compression = compressionType.ToString();
                            else
                            {
                                compression = "UnRecognised";
                            }
                        }
                    } 
                }
            }
            catch (Exception exFileStream)
            {
                compression = exFileStream.Message;
            }

            return compression;
            //using (var sourceImage = Image.FromFile(path))
            //{
            //    var compressionTagIndex = Array.IndexOf(sourceImage.PropertyIdList, 0x103);
            //    PropertyItem compressionTag = sourceImage.PropertyItems[compressionTagIndex];
            //    return (CompressionTypes)Enum.Parse(typeof(CompressionTypes), BitConverter.ToInt16(compressionTag.Value, 0).ToString(CultureInfo.InvariantCulture));
            //}
        }
    }

    public enum CompressionTypes
    {
        NoCompression = 1,
        CcittGroup3 = 2,
        FacsimilecompatibleCcittGroup3 = 3,
        CcittGroup4 = 4,
        Lzw = 5,
        UnRecognised = 6,
        ExceptionInFilehandling = 7
    }
}

3 个答案:

答案 0 :(得分:3)

您可以在托管文件的服务器上运行程序,而不是通过网络读取文件吗?

如果没有,我会有一个程序从网络复制文件到本地文件夹作为队列。然后让第二个程序从本地队列文件夹中读取图像,确定压缩,然后删除该文件。这将网络IO时间与文件处理时间分开。

答案 1 :(得分:1)

这些是我想到的几件事:

  1. Parallel.For代替for查看列表。
  2. 安装了Async CTP的.net 4.5或.net 4中的
  3. async / await。主题太广泛了,不能在这里讨论它。您可以在此处查看Async/await
  4. TPL DataFlow还可以帮助并行化流程。

答案 2 :(得分:0)

您没有描述问题或问题。这在社区中是不可接受的。尝试编辑您的问题,更准确地解决您的问题以及您想要做的事情。

如果您的瓶颈是您的CPU,请尝试一次在多个线程中完成工作。

如果您的瓶颈是文件访问权限,您可以将图像移动到SSD驱动器或内存驱动器中,然后从那里访问它们。