C#如何处理100万行而不会崩溃程序? [重复]

问题描述 投票:-2回答:1

这个问题在这里已有答案:

我有一个100万行的文件。如果程序包含用户请求删除的单词之一,我的程序将逐行检查。如果该行包含该单词,则必须将其删除并添加到列表中。每次按下“开始”,程序都会冻结,并且列表框中不显示任何内容。但是,如果我添加像1k它将清理文件并在列表中显示新文件。处理这个问题的最佳方法是什么?

我的代码:

    using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;

namespace BoringAssComboTool
{
    public partial class Form2 : Form
    {
        List<String> list;
        string myFile = null;
        string[] line = null;
        int linecount = 0;
        public Form2()
        {
            InitializeComponent();
        }

        private void groupBox1_Enter(object sender, EventArgs e)
        {

        }

        private void label1_Click(object sender, EventArgs e)
        {

        }

        private void textBox1_TextChanged(object sender, EventArgs e)
        {

        }
        public void button1_Click(object sender, EventArgs e)
        {

            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.RestoreDirectory = true;
            openFileDialog.Multiselect = false;
            openFileDialog.Filter = "Combo List (*.txt)|*.txt";
            openFileDialog.FilterIndex = 1;
            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                myFile = openFileDialog.FileName;
                MessageBox.Show("You selected " + openFileDialog.FileName);



                linecount = File.ReadAllLines(myFile).Length;
                label3.Text = "Total loaded : " + linecount;
                line = File.ReadAllLines(myFile);
                //MessageBox.Show(line[0]);
                //MessageBox.Show(line[4]);
                list = File.ReadAllLines(myFile).ToList();
              //  StreamReader sr = new StreamReader(myFile);
            }

        }

        private void button3_Click(object sender, EventArgs e)
        {
            int removedlines = 0;


            string domainSplitted = textBox1.Text;
            string[] splitDomain = domainSplitted.Split(',');
            //MessageBox.Show(splitDomain[2]);
            //MessageBox.Show(splitDomain[3]);
            //MessageBox.Show(line[2]);
            int sizeOfArray = splitDomain.Length;
            // MessageBox.Show("Length is " + sizeOfArray);
            for (int x = 0; x < sizeOfArray - 1; x++)
            {
              //  for (int i = 0; i < linecount - 1; i++) 
              for ( int i = linecount - 1; i>=0; i--)
                {
                    if (line[i].Contains(splitDomain[x]))
                    {

                        list.RemoveAt(i);
                        string[] lines = list.ToArray();
                        removedlines++;
                        label4.Text = "Total Removed = " + removedlines;
                        listBox1.DataSource = list;
                        // MessageBox.Show("there is a match on " + line[i]);
                    }
                }
            }
          // listBox1.DataSource = list;
        }

        private void pictureBox3_Click(object sender, EventArgs e)
        {
            this.WindowState = FormWindowState.Minimized;
        }

        private void pictureBox2_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }



        private void label3_Click(object sender, EventArgs e)
        {

        }

        private void button2_Click(object sender, EventArgs e)
        {
            // System.IO.File.WriteAllLines("Cleaned Combo File.txt", list);
            SaveFileDialog save = new SaveFileDialog();

            save.FileName = "Cleaned Combo File.txt";

            save.Filter = "Text File | *.txt";

            if (save.ShowDialog() == DialogResult.OK)

            {

                StreamWriter writer = new StreamWriter(save.OpenFile());

                for (int i = 0; i < listBox1.Items.Count; i++)

                {

                    writer.WriteLine(listBox1.Items[i].ToString());

                }

                writer.Dispose();

                writer.Close();

                MessageBox.Show("Saved succesfully");

            }
        }
        // MessageBox.Show("==" + line[27]);

        protected override void WndProc(ref Message m)
        {
            base.WndProc(ref m);
            if (m.Msg == WM_NCHITTEST)
                m.Result = (IntPtr)(HT_CAPTION);
        }

        private const int WM_NCHITTEST = 0x84;
        private const int HT_CLIENT = 0x1;
        private const int HT_CAPTION = 0x2;

        private void Form2_Load(object sender, EventArgs e)
        {

        }
    }
    }
c#
1个回答
3
投票

你不应该把所有文本都读到内存中。而是将程序更改为逐行读取。然后,您可以将每个更新/固定行附加到临时文件中。处理完成后,如有必要,使用临时文件覆盖源文件。

以下是逐行读取文件的方法:

using (StreamReader sr = new StreamReader(path)) 
{
    while (sr.Peek() >= 0) 
    {
        Console.WriteLine(sr.ReadLine());
    }
}

Here是StreamReader / StreamWriter类的文档。

除此之外,我建议你切换到async API。 StreamReader也有一个ReadLineAsync API,以满足这种需求。这将允许避免UI线程的长时间延迟。

© www.soinside.com 2019 - 2024. All rights reserved.