3

このコードを使用して、テキスト ファイルを ListBox にインポートしています

        OpenFileDialog openFileDialog1 = new OpenFileDialog();
        openFileDialog1.Filter = "Text Files|*.txt";
        openFileDialog1.Title = "Select a Text file";
        openFileDialog1.FileName = "";
        DialogResult result = openFileDialog1.ShowDialog();
        if (result == DialogResult.OK)
        {
            string file = openFileDialog1.FileName;

            string[] text = System.IO.File.ReadAllLines(file);
            foreach (string line in text)
            {
                listBox2.Items.Add(line);

            }
            listBox2.Items.Add("");
        }

10 行程度の小さなテキスト ファイルでは問題なく動作しますが、より大きなリスト (4 ~ 5 メガバイト) をインポートしようとすると、プログラムが応答せず、クラッシュします。

何か助けはありますか?

4

5 に答える 5

2

パフォーマンスを向上させるには、C# で BufferedStream クラスを使用します。
http://msdn.microsoft.com/en-us/library/system.io.bufferedstream.aspx

于 2012-11-15T20:22:09.597 に答える
1

これを使用することによって:

string[] text = System.IO.File.ReadAllLines(file);
listBox1.Items.AddRange(text);

これの代わりに:

string[] text = System.IO.File.ReadAllLines(file);
foreach (string line in text)
{
       listBox2.Items.Add(line);
}

すべてのアイテム挿入でlistBoxを無効にするわけではないため、実行を少なくとも10〜15倍高速化できます。私は数千行で測定しました。

ボトルネックはReadAllLines、テキストの行数が多すぎる場合にも発生する可能性があります。なぜこんなに多くの行を挿入するのかわかりませんが、ユーザーは必要な行を見つけることができますか?

[OK]を編集してから、BackgroundWorkerを使用することをお勧めします。コードは次のとおりです。

まず、BackGroundWorkerを初期化します。

 BackgroundWorker bgw;
        public Form1()
        {
            InitializeComponent();
            bgw = new BackgroundWorker();
            bgw.DoWork += new DoWorkEventHandler(bgw_DoWork);
            bgw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgw_RunWorkerCompleted);
        }

次に、メソッドでそれを呼び出します。

private void button1_Click(object sender, EventArgs e)
        {
            if (!bgw.IsBusy)
            {
                OpenFileDialog openFileDialog1 = new OpenFileDialog();
                openFileDialog1.Filter = "Text Files|*.txt";
                openFileDialog1.Title = "Select a Text file";
                openFileDialog1.FileName = "";
                DialogResult result = openFileDialog1.ShowDialog();
                if (result == DialogResult.OK)
                {
                    string file = openFileDialog1.FileName;
                    listView1.BeginUpdate();
                    bgw.RunWorkerAsync(file);
                }
            }
            else
                MessageBox.Show("File reading at the moment, try later!");
        }


        void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            listView1.EndUpdate();
        }
        void bgw_DoWork(object sender, DoWorkEventArgs e)
        {
            string fileName = (string)e.Argument;
            TextReader t = new StreamReader(fileName);
            string line = string.Empty;
            while ((line = t.ReadLine()) != null)
            {
                string nLine = line;
                this.Invoke((MethodInvoker)delegate { listBox1.Items.Add(nLine); });
            }
        }

読み取り時に各行が追加され、レスポンシブUIが作成され、読み込みが完了する前に行がlistBoxに影響を与えることはありません。

于 2012-11-15T20:30:26.233 に答える
0

メソッドが完了するのを待っておりReadAllLines、UI スレッドをブロックしているため、アプリケーションが応答しなくなります。UI のブロックを回避するために、別のスレッドでファイルを読み取ることができます。以下のコードがエラーなしで動作することを保証することはできませんが、問題に対処する方法についてのアイデアが得られるはずです。

まず、アイテムを に追加するメソッドが必要ですListBox

private void AddListBoxItem(string item)
{
    if(!InvokeRequired)
    {
        listBox2.Items.Add(item);
    }
    else
    {
        var callback = new Action<string>(AddListBoxItem);
        Invoke(callback, new object[]{item});
    }
}

上記のメソッドは、UI スレッドで実行されているかどうかを確認し、実行されている場合は、アイテムをlistBox2.Itemsコレクションに追加するだけです。そうでない場合は、それ自体からデリゲートを作成し、UI スレッドでそのデリゲートを呼び出します。

次に、ファイルを読み取るコードを別のスレッドに移動し、AddListBoxItemメソッドを呼び出す必要があります。読みやすくするために、それを別のメソッドに入れましょう。

private void AddFileContentsToList(string fileName)
{
    using(var reader = new System.IO.StreamReader(fileName))
    {
        while(!reader.EndOfStream)
        {
            var line = reader.ReadLine();
            AddListBoxItem(line);
        }
    }
}

そして、別のスレッドでメソッドを呼び出します。

OpenFileDialog openFileDialog1 = new OpenFileDialog();
openFileDialog1.Filter = "Text Files|*.txt";
openFileDialog1.Title = "Select a Text file";
openFileDialog1.FileName = "";
DialogResult result = openFileDialog1.ShowDialog();
if (result == DialogResult.OK)
{
    var thread = new Thread(AddFileContentsToList);
    thread.Start();
}

お役に立てれば!

于 2012-11-15T20:43:54.663 に答える
0

ストリームを使用してデータを保存できます。

class Test
{

public static void Main()
{
    string path = @"c:\temp\MyTest.txt";

    //Create the file. 
    using (FileStream fs = File.Create(path))
    {
        AddText(fs, "This is some text");
        AddText(fs, "This is some more text,");
        AddText(fs, "\r\nand this is on a new line");
        AddText(fs, "\r\n\r\nThe following is a subset of characters:\r\n");

        for (int i=1;i < 120;i++)
        {
            AddText(fs, Convert.ToChar(i).ToString());

        }
    }

    //Open the stream and read it back. 
    using (FileStream fs = File.OpenRead(path))
    {
        byte[] b = new byte[1024];
        UTF8Encoding temp = new UTF8Encoding(true);
        while (fs.Read(b,0,b.Length) > 0)
        {
            Console.WriteLine(temp.GetString(b));
        }
    }
}

private static void AddText(FileStream fs, string value)
{
    byte[] info = new UTF8Encoding(true).GetBytes(value);
    fs.Write(info, 0, info.Length);
}

}

次に、イベントハンドラ

 privateasyncvoid Button_Click(object sender, RoutedEventArgs e)
    {
        UnicodeEncoding uniencoding = new UnicodeEncoding();
        string filename = @"c:\Users\exampleuser\Documents\userinputlog.txt";

        byte[] result = uniencoding.GetBytes(UserInput.Text);

        using (FileStream SourceStream = File.Open(filename, FileMode.OpenOrCreate))
        {
            SourceStream.Seek(0, SeekOrigin.End);
            await SourceStream.WriteAsync(result, 0, result.Length);
        }
    }
于 2012-11-15T20:22:47.163 に答える
0

単にその仕事を完了していない可能性があり、さらに待つ必要があります. この解決策を試してください:

http://www.bytechaser.com/en/articles/f3a3niqyb7/display-large-lists-in-listview-control-quickly.aspx

于 2012-11-15T20:26:01.413 に答える