winforms 查找richtextbox中的所有换行符

jobtbby3  于 2022-12-23  发布在  其他
关注(0)|答案(2)|浏览(175)

我正在开发一个自定义的texteditor控件,遇到了这个问题。
我需要一个函数来获取文本中每一个换行符"\n"的字符索引。我已经有两种方法来实现这一点:

private List<int> GetNewLineLocations()
    {
        var list = new List<int>();
        int ix = 0;
        foreach (var c in this.Text)
        {
            if (c == '\n') list.Add(ix);
            ix++;
        }
        Debug.WriteLine(ix);
        return list;
    }

以及:

private List<int> GetNewLineLocations()
    {
        var list = new List<int>();
        int ix = -1;

        for (int i = 0; i < this.Lines.Length; i++)
        {
            ix += Lines[i].Length;
            ix += 1;
            list.Add(ix);
        }

        return list;
    }

第一种解决方案确实有效,但速度会减慢,因为在richtextbox中输入的文本数量更多,大约有40000个字符,但可以分散到许多行中,比如20000行。
第二个似乎更快,因为它循环更少,做或多或少相同的,但在1000行显着放缓,无论他们包含多少文本。
当然,代码需要快速运行,并且不使用大量资源,这就是为什么我认为第二种解决方案会更好。

    • 我的问题是**

1.哪种解决方案更好?为什么?
1.为什么第二种解决方案要慢得多?
1.有更好的解决办法吗?

myzjeezk

myzjeezk1#

我尝试了你的例子和Felix的例子,以及我自己的一个解决方案,使用了一个富文本框和40k行。结果是这是最快的,而且我没有看到任何减慢。你能尝试将行数组作为参数传递给我们吗?

public static List<int> GetNewLineLocations(this string[] lines)
        {
            var list = new List<int>();
            int ix = -1;

            for (int i = 0; i < lines.Length; i++)
            {
                ix += lines[i].Length+1;
                list.Add(ix);
            }

            return list;
        }
vddsk6oq

vddsk6oq2#

处理字符串时,Regular Expressions非常好用,但是它们不是最快的,如果你需要更快的处理,你应该在较低的层次上并行处理,并且确保使用long作为index,因为int最多只能处理2^31个字符,long最多只能处理2^63个字符。
我同意@Nyerguds在评论中说的话:
问题在于,获取富文本框中文本的标准函数实际上是一个处理函数,它必须过滤掉RTF标记,获取文本的实际函数才是瓶颈,而不是它后面的函数。
所以你的数据应该保存在代码中的某个地方,而不是用户界面中。迟早当处理长文本时,无论如何都会引起麻烦,比如滚动时的口吃或进一步的瓶颈。而且我只会表示无论如何都可以在控件中显示的行。所以你应该过度考虑你的应用程序设计。Check your Front/Backend seperation.将数据存储在后端将允许您直接访问数据,而无需依赖于Textbox方法或其他用户界面。
下面是如何使用.net framework的Parallel Class轻松处理数据的示例:

using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Threading.Tasks;

    namespace ConsoleApp1
    {
        internal class Program
        {
            public static byte[] _globalDataStore { get; set; }
            private static void Main(string[] args)
            {
                DoStuff();
                ShowDone();
            }

            private static void ShowDone()
            {
                Console.WriteLine("done...");
                Console.ReadKey();
            }

            private static void DoStuff()
            {
                var tempData = GetData();
                StoreData(ref tempData);
                tempData = null; //free some ram
                var dataIdentifier = (byte)'\n';
                GetAndPromptDataPositions(_globalDataStore, dataIdentifier);
            }

            private static void GetAndPromptDataPositions<T>(T[] data, T dataIdentifier)
            {
                var dataPositionList = GetDataPositions<T>(data, dataIdentifier);
                PromptDataPostions(dataPositionList);
            }

            private static void PromptDataPostions(IEnumerable<long> positionList)
            {
                foreach (var position in positionList)
                {
                    Console.WriteLine($"Position '{position}'");
                }
            }
            private static string GetData()
            {
                return "aasdlj\naksdlkajsdlkasldj\nasld\njkalskdjasldjlasd";
            }

            private static void StoreData(ref string tempData)
            {
                _globalDataStore = Encoding.ASCII.GetBytes(tempData);
            }

            private static List<long> GetDataPositions<T>(T[] data, T dataToFind)
            {
                lock (data) //prevent data from being changed while processing, important when have other threaded could write data 
                {
                    var postitonList = new List<long>();
                    Parallel.For(0, data.LongLength, (position) =>
                    {
                        if (data[position].Equals(dataToFind))
                        {
                            lock (postitonList) //lock list because of multithreaded access to prevent data corruption
                            {
                                postitonList.Add(position);
                            }
                        }
                    });
                    return postitonList;
                }
            }
        }
    }

相关问题