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

使用ZXing在C#中按二维码拆分文档时解决‘文件被占用’错误

问题:ZXing识别二维码后移动文件提示“文件被另一进程占用”

需求说明

我想通过二维码拆分文档:所有无二维码的页面归入首个二维码所在文件夹,之后创建新文件夹并对下一个二维码执行相同操作。但使用ZXing识别二维码后,移动带二维码的文件时提示“文件被另一进程占用”。

原代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ZXing;
using System.Drawing;
using ZXing.QrCode;
using System.Threading;
using System.IO;

namespace zxing_qr
{
    internal class Program
    {
        static void Main(string[] args)
        {
            string srcDir = @"C:\Users\tirocinio2\Documents\moduli d'intervento";           
            string[] filenames = System.IO.Directory.GetFiles(srcDir);
            List<string> buffer = new List<string>(2);            

            for (int i = 0;i< filenames.Length;i++)
            { 
                string res = decode(filenames, i);

                Thread.Sleep(50);
                if (res != null)
                {
                    buffer.Add(filenames[i]);
                    string dest = creaCartella();
                    for (int j = 0; j < buffer.Count; j++)
                    {
                        FileInfo file = new FileInfo(buffer[j]);
                        file.MoveTo($@{dest}" + buffer[j].Substring(buffer[j].LastIndexOf('\\')));
                    }
                    buffer.Clear();                  
                }
                else
                {
                    buffer.Add(filenames[i]);
                }
            }
            Console.WriteLine("premi un tasto per continuare");
            Console.ReadKey();
        }

        static string creaCartella()
        {
            string destDir = DateTime.Now.ToString().Replace(" ","").Replace("/","_").Replace(":","-");
            destDir = @"C:\Users\tirocinio2\Documents\output moduli\" + destDir;
            System.IO.Directory.CreateDirectory(destDir);
            return destDir;
        }
        static string decode(string[] filenames,int i)
        {
            BarcodeReader barcodeReader = new BarcodeReader();
            Bitmap barcodeBitmap = (Bitmap)Bitmap.FromFile(filenames[i]);
            Result barcodeResult = barcodeReader.Decode(barcodeBitmap);
            return barcodeResult.ToString();
        }
    }
}

问题原因

  1. 文件资源未释放:decode方法中用Bitmap.FromFile加载图片后,未及时释放Bitmap对象,导致系统一直占用文件句柄,移动文件时触发“被另一进程占用”提示。
  2. 空引用风险:若未识别到二维码,barcodeResult为null,直接调用ToString()会抛出空引用异常。
  3. 路径拼接错误:file.MoveTo($@{dest}" + ...)的插值语法错误,会导致目标路径格式异常。

修复后的代码

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using ZXing;
using ZXing.QrCode;

namespace zxing_qr
{
    internal class Program
    {
        static void Main(string[] args)
        {
            string srcDir = @"C:\Users\tirocinio2\Documents\moduli d'intervento";           
            string[] filenames = Directory.GetFiles(srcDir);
            List<string> buffer = new List<string>();            

            for (int i = 0; i < filenames.Length; i++)
            { 
                string res = DecodeQrCode(filenames[i]);

                if (!string.IsNullOrEmpty(res))
                {
                    buffer.Add(filenames[i]);
                    string destDir = CreateTargetDirectory();
                    foreach (var filePath in buffer)
                    {
                        string fileName = Path.GetFileName(filePath);
                        string destPath = Path.Combine(destDir, fileName);
                        File.Move(filePath, destPath);
                    }
                    buffer.Clear();                  
                }
                else
                {
                    buffer.Add(filenames[i]);
                }
            }

            // 处理最后一批未遇到二维码的文件
            if (buffer.Count > 0)
            {
                string destDir = CreateTargetDirectory();
                foreach (var filePath in buffer)
                {
                    string fileName = Path.GetFileName(filePath);
                    string destPath = Path.Combine(destDir, fileName);
                    File.Move(filePath, destPath);
                }
            }

            Console.WriteLine("操作完成,按任意键继续");
            Console.ReadKey();
        }

        static string CreateTargetDirectory()
        {
            string dirName = DateTime.Now.ToString("yyyyMMddHHmmssfff");
            string destDir = Path.Combine(@"C:\Users\tirocinio2\Documents\output moduli", dirName);
            Directory.CreateDirectory(destDir);
            return destDir;
        }

        static string DecodeQrCode(string filePath)
        {
            // using语句自动释放Bitmap资源,释放文件句柄
            using (Bitmap barcodeBitmap = (Bitmap)Bitmap.FromFile(filePath))
            {
                var barcodeReader = new BarcodeReader
                {
                    Options = new QrCodeEncodingOptions
                    {
                        TryHarder = true // 提升二维码识别成功率
                    }
                };
                Result barcodeResult = barcodeReader.Decode(barcodeBitmap);
                return barcodeResult?.ToString(); // 空值安全访问
            }
        }
    }
}

关键修改点

  • 资源自动释放:用using包裹Bitmap,确保识别完成后立即释放文件句柄,解决文件占用问题。
  • 空值安全处理:使用barcodeResult?.ToString()避免空引用异常。
  • 路径拼接优化:用Path.Combine和Path.GetFileName替代手动字符串拼接,避免路径格式错误。
  • 剩余文件处理:增加循环结束后处理缓冲区剩余文件的逻辑,避免遗漏最后一批无二维码的文件。
  • 简化文件夹命名:用yyyyMMddHHmmssfff格式生成唯一文件夹名,省去特殊字符替换的繁琐操作。

内容的提问来源于stack exchange,提问作者Ricc.g

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 09:38:21