处理文件时内存使用量增加

本文关键字:使用量 增加 内存 文件 处理 | 更新日期: 2023-09-27 18:06:37

我正在开发一个应用程序,它读取xml文件文件夹,每个文件都要做一些检查,并根据一些标准复制到一个新文件夹。

但是当它到达foreach循环时,内存使用继续增长,我认为不应该发生这种情况,因为变量在每次迭代中不会增加,只是被覆盖。

下面是我的代码:
using System;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using System.Xml;
namespace XMLOrganizer
{
    public partial class Form1 : Form
    {
        string selectedFolder;
        public Form1()
        {
            InitializeComponent();
            comboBox1.DropDownStyle = ComboBoxStyle.DropDownList;
            comboBox1.SelectedIndex = 0;
        }
        private void button1_Click(object sender, EventArgs e)
        {
            folderBrowserDialog1.ShowDialog();
            selectedFolder = folderBrowserDialog1.SelectedPath;
            organizeBtn.Enabled = true;
        }
        private void organizeBtn_Click(object sender, EventArgs e)
        {
            if (comboBox1.SelectedIndex == -1)
            {
                MessageBox.Show("Selecione o tipo de nota", "Erro!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation,
                    MessageBoxDefaultButton.Button1);
                return;
            }
            if (comboBox1.SelectedIndex != 2)
            {
                OrganizeXml(label2, selectedFolder, comboBox1);
            }
            //ORGANIZAR LOTES
            else
            {
                string folder = selectedFolder;
                label2.Text = "Arquivos sendo processados, aguarde...";
                label2.Refresh();
                string[] files = Directory.GetFiles(folder, "*.xml", SearchOption.AllDirectories);
                int atualFile = 1, totalXML = files.Length;
                foreach (string file in files)
                {
                    XmlDocument xmlDocument = new XmlDocument();
                    xmlDocument.Load(file);
                    XmlNodeList enviNFe = xmlDocument.GetElementsByTagName("enviNFe");
                    string versao = ((XmlElement)enviNFe[0]).Attributes["versao"].Value;
                    XmlNodeList NFe = ((XmlElement)enviNFe[0]).GetElementsByTagName("NFe");
                    Directory.CreateDirectory(selectedFolder + @"'NOTAS");
                    label2.Text = "Processando arquivo " + atualFile + " de " + totalXML;
                    string notaXML;
                    foreach (XmlElement nota in NFe)
                    {
                        notaXML = "<?xml version='"1.0'" encoding='"UTF-8'"?><nfeProc versao='"" + versao + "'" xmlns='"http://www.portalfiscal.inf.br/nfe'">" + nota.OuterXml + "</nfeProc>";
                        XmlNodeList infNFe = nota.GetElementsByTagName("infNFe");
                        string chave = infNFe[0].Attributes["Id"].Value.Replace("NFe", "");
                        File.WriteAllText(selectedFolder + "''NOTAS''" + chave + ".xml", notaXML);
                    }

                }
                OrganizeXml(label2, selectedFolder + "''NOTAS", comboBox1);

            }
        }
        private static void OrganizeXml(Label label2, string selectedFolder, ComboBox comboBox1)
        {
            string folderMove = String.Empty;
            string folder = selectedFolder;
            label2.Text = "Arquivos sendo processados, aguarde...";
            label2.Refresh();
            string[] files = Directory.GetFiles(folder, "*.xml", SearchOption.AllDirectories);
            int i = 1, arquivos = files.Length;

            Directory.CreateDirectory(folder + @"'ORGANIZADO");
            if (comboBox1.SelectedIndex != 2)
            {
                Directory.CreateDirectory(folder + @"'ORGANIZADO'OUTROS");
                Directory.CreateDirectory(folder + @"'ORGANIZADO'LOTES");
            }
            foreach (string file in files)
            {
                XmlDocument xmlDocument = new XmlDocument();
                try
                {
                    xmlDocument.Load(file);
                    if (xmlDocument.DocumentElement.Name != "nfeProc")
                    {
                        XmlNodeList NFe = xmlDocument.GetElementsByTagName("NFe");
                        var nota = ((XmlElement) NFe[0]);
                        if (nota != null)
                        {
                            XmlNodeList infNFe = ((XmlElement) NFe[0]).GetElementsByTagName("infNFe");
                            string chave = infNFe[0].Attributes["Id"].Value.Replace("NFe", "");
                            string versao = infNFe[0].Attributes["versao"].Value;
                            string notaXML = "<?xml version='"1.0'" encoding='"UTF-8'"?><nfeProc versao='"" + versao +
                                             "'" xmlns='"http://www.portalfiscal.inf.br/nfe'">" + nota.OuterXml +
                                             "</nfeProc>";
                            string dirNote = Path.GetDirectoryName(file);
                            File.WriteAllText(dirNote + "''fix_" + chave + ".xml", notaXML);
                        }
                    }

                    //
                    //
                    //
                }
                catch (XmlException)
                {
                    XmlDocument doc = new XmlDocument();
                    string arquivo = ReadFileToString(file);
                    arquivo = RemoveSpecialCharacters(arquivo);
                    if (arquivo == "")
                    {
                        File.Move(file, folder + @"'ORGANIZADO'OUTROS'corrupt_" + Path.GetFileName(file));
                        continue;
                    }
                    try
                    {
                        doc.LoadXml(arquivo);
                        doc.PreserveWhitespace = true;
                        doc.Save(file);
                    }
                    catch (XmlException)
                    {
                        File.Move(file, folder + @"'ORGANIZADO'OUTROS'corrupt_" + Path.GetFileName(file));
                        files = files.Where(f => f != file).ToArray();
                    }
                }
            }
            foreach (string file in files)
            {
                string arquivoLoad = file;
                XmlDocument xmlDocument = new XmlDocument();
                xmlDocument.Load(arquivoLoad);
                XmlNodeList NFe = xmlDocument.GetElementsByTagName("NFe");
                XmlNodeList enviNFe = xmlDocument.GetElementsByTagName("enviNFe");

                if (NFe.Count == 0)
                {
                    if (File.Exists(folder + @"'ORGANIZADO'OUTROS'no_NFe_" + Path.GetFileName(arquivoLoad)))
                    {
                        Random rnd = new Random();
                        File.Copy(arquivoLoad,
                            folder + @"'ORGANIZADO'OUTROS'no_NFe_" + rnd.Next(1, 5000) + Path.GetFileName(arquivoLoad));
                    }
                    else
                    {
                        File.Copy(arquivoLoad, folder + @"'ORGANIZADO'OUTROS'no_NFe_" + Path.GetFileName(arquivoLoad));
                    }
                    continue;
                }
                XmlNodeList infNFe = ((XmlElement)NFe[0]).GetElementsByTagName("infNFe");
                string chave = infNFe[0].Attributes["Id"].Value.Replace("NFe", "");

                if (xmlDocument.DocumentElement.Name != "nfeProc")
                {
                    File.Move(arquivoLoad, folder + @"'ORGANIZADO'OUTROS'no_nfeProc_" + Path.GetFileName(arquivoLoad));
                    arquivoLoad = Path.GetDirectoryName(file) + "''fix_" + chave + ".xml";
                }
                if (enviNFe.Count > 0)
                {
                    if (File.Exists(folder + @"'ORGANIZADO'LOTES'" + Path.GetFileName(arquivoLoad)))
                    {
                        Random rnd = new Random();
                        File.Copy(arquivoLoad, folder + @"'ORGANIZADO'LOTES'" + rnd.Next(1, 5000) + Path.GetFileName(arquivoLoad));
                    }
                    else
                    {
                        File.Copy(arquivoLoad, folder + @"'ORGANIZADO'LOTES'" + Path.GetFileName(arquivoLoad));
                    }
                    continue;
                }
                //XmlNodeList infNFe = ((XmlElement)NFe[0]).GetElementsByTagName("infNFe");
                XmlNodeList ide = ((XmlElement)infNFe[0]).GetElementsByTagName("ide");

                string tpNF = ((XmlElement)ide[0]).GetElementsByTagName("tpNF")[0].InnerText;
                //if (tpNF == "0") continue;

                XmlNodeList emit = ((XmlElement)infNFe[0]).GetElementsByTagName("emit");
                string emitInfoCod;
                if (((XmlElement)emit[0]).GetElementsByTagName("CNPJ").Count > 0)
                {
                    emitInfoCod = ((XmlElement)emit[0]).GetElementsByTagName("CNPJ")[0].InnerText;
                }
                else if (((XmlElement)emit[0]).GetElementsByTagName("CPF").Count > 0)
                {
                    emitInfoCod = ((XmlElement)emit[0]).GetElementsByTagName("CPF")[0].InnerText;
                }
                else
                {
                    emitInfoCod = "0";
                }
                string ide_dEmi = (((XmlElement)ide[0]).GetElementsByTagName("dEmi").Count > 0)
                    ? ((XmlElement)ide[0]).GetElementsByTagName("dEmi")[0].InnerText
                    : ((XmlElement)ide[0]).GetElementsByTagName("dhEmi")[0].InnerText;
                string[] data = ide_dEmi.Split('-');
                string folderName = data[0] + "''" + data[1];
                string organizeStyle = String.Empty;
                if (comboBox1.SelectedIndex == 0 || comboBox1.SelectedIndex == 2)
                {
                    organizeStyle = folder + @"'ORGANIZADO'" + emitInfoCod + @"'" + folderName;
                }
                else
                {
                    organizeStyle = folder + @"'ORGANIZADO'" + folderName + @"'" + emitInfoCod;
                }

                if (!Directory.Exists(organizeStyle))
                {
                    Directory.CreateDirectory(organizeStyle);
                }
                folderMove = organizeStyle + "''";


                if (!File.Exists(folderMove + chave + ".xml"))
                {
                    File.Copy(arquivoLoad, folderMove + chave + ".xml");
                }

                label2.Text = "Arquivos sendo processados, aguarde... (" + i + " / " + arquivos + ")";
                label2.Refresh();
                i++;

            }

            label2.Text = "Notas organizadas com sucesso!";
            label2.Refresh();
        }
        public static string ReadFileToString(string filePath)
        {
            using (StreamReader streamReader = new StreamReader(filePath))
            {
                string text = streamReader.ReadToEnd();
                streamReader.Close();
                return text;
            }
        }
        public static string RemoveSpecialCharacters(string str)
        {
            return Regex.Replace(str, @"[^'u0000-'u007F]", string.Empty);
        }
        private void exitBtn_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }
    }
}

我怎么知道发生了什么?

处理文件时内存使用量增加

指向引用类型的变量的值根本不是对象,它只是该对象所在的内存地址。

所以当你做以下操作时:

while (true)
{
    var myVariable = new MyReferenceType();
}

你真正重用的唯一内存是变量本身(想想32位或64位指针)。但是在每次迭代中,你都要分配足够的内存空间来容纳你刚刚创建的新对象,并且这些内存绝对不是为前一个对象保留的内存。

这就是内存使用增长的本质原因。以前迭代中没有活动引用的"旧"对象最终将被GC收集,但如果GC认为它有足够的可用内存来避免它,则可能永远不会收集。