You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否将条码列表以MemoryStream存入Hashtable?多条码PDF生成报错

问题描述

需求:读取以下CSV文件,根据Position字段生成对应Item的CODE_128条码,并将条码放置在PDF页面的指定位置。

Item,Position
A,1
B,5
C,7

当前问题:将生成的条码以MemoryStream形式存入Hashtable后,调用GeneratePDF方法时抛出Cannot access a closed stream异常,但单条码生成PDF的逻辑可正常运行。询问该批量生成方案是否可行?

相关代码

批量生成条码存入Hashtable的代码

while (!parser.EndOfData)
{
    fields = parser.ReadFields();

    string item = fields[0];
    int position = Convert.ToInt32(fields[1]);

    BarcodeWriter writer = new BarcodeWriter()
    {
        Format = BarcodeFormat.CODE_128,
        Options = new EncodingOptions
        {
            Height = 100,
            Width = 300,
            PureBarcode = false,
            Margin = 10,
        },
    };

    string item = @"*" + item + "*";
    var bitmap = writer.Write(item);

    bitmap.SetResolution(300,300);
    //bitmap.Save(@"E:\Image.png", System.Drawing.Imaging.ImageFormat.Png);

    using (MemoryStream ms = new MemoryStream())
    {
        bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
        hastable.Add(position, ms);   
    }
}
GeneratePDF(hastable);

GeneratePDF方法代码

PdfDocument document = new PdfDocument();

// Create an empty page
PdfPage page = document.AddPage();

// Get an XGraphics object for drawing
XGraphics gfx = XGraphics.FromPdfPage(page);

MemoryStream ms = new MemoryStream();
string filename = "Barcode.pdf";

foreach (DictionaryEntry values in hashtable)
{
    int position = Convert.ToInt32(values.Key);
    ms = (MemoryStream)values.Value;
    XImage pic = XImage.FromStream(ms);
    pic.Interpolate = false;
    string points = getCoordinates(position);
    string[] axis = points.Split(',');

    int x = Convert.ToInt32(axis[0]);
    int y = Convert.ToInt32(axis[1]);

    gfx.DrawImage(pic, x, y, pic.PointWidth, pic.PointHeight);

解决方案

这个批量生成方案完全可行,报错的核心原因是你用using块包裹了MemoryStream:当using块执行结束时,流会被自动关闭,后续在GeneratePDF中访问已关闭的流就会触发异常。

修复步骤

  1. 替换流存储为字节数组(更安全)
    避免直接存储MemoryStream,转而将流内容转为字节数组存入Hashtable,需要使用时再重建流。这样可以彻底规避流生命周期管理的问题:

    • 批量生成部分修改:
      while (!parser.EndOfData)
      {
          fields = parser.ReadFields();
      
          string item = fields[0];
          int position = Convert.ToInt32(fields[1]);
      
          BarcodeWriter writer = new BarcodeWriter()
          {
              Format = BarcodeFormat.CODE_128,
              Options = new EncodingOptions
              {
                  Height = 100,
                  Width = 300,
                  PureBarcode = false,
                  Margin = 10,
              },
          };
      
          // 修复重复定义变量问题
          item = @"*" + item + "*";
          var bitmap = writer.Write(item);
      
          bitmap.SetResolution(300,300);
      
          using (MemoryStream ms = new MemoryStream())
          {
              bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
              // 存储字节数组而非流
              hastable.Add(position, ms.ToArray());
          }
          bitmap.Dispose(); // 释放Bitmap资源
      }
      GeneratePDF(hastable);
      
    • GeneratePDF方法修改:
      PdfDocument document = new PdfDocument();
      PdfPage page = document.AddPage();
      XGraphics gfx = XGraphics.FromPdfPage(page);
      string filename = "Barcode.pdf";
      
      foreach (DictionaryEntry values in hashtable)
      {
          int position = Convert.ToInt32(values.Key);
          byte[] imageBytes = (byte[])values.Value;
          // 使用时重建流
          using (MemoryStream ms = new MemoryStream(imageBytes))
          {
              XImage pic = XImage.FromStream(ms);
              pic.Interpolate = false;
              string points = getCoordinates(position);
              string[] axis = points.Split(',');
      
              int x = Convert.ToInt32(axis[0]);
              int y = Convert.ToInt32(axis[1]);
      
              gfx.DrawImage(pic, x, y, pic.PointWidth, pic.PointHeight);
          }
      }
      // 补充PDF保存和资源释放
      document.Save(filename);
      document.Dispose();
      
  2. 其他必改细节

    • 原批量代码中存在重复定义string item的错误,需要删除string item = @"*" + item + "*";里的string关键字;
    • 生成PDF后必须调用document.Save和document.Dispose,否则无法得到完整的PDF文件,还会造成内存泄漏。

修改完成后,批量生成条码并插入PDF指定位置的逻辑即可正常运行。

内容的提问来源于stack exchange,提问作者Anonymous

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 13:15:22