【问题标题】:Saving/Loading RichTextBox Content with other data using C#使用 C# 将 RichTextBox 内容与其他数据一起保存/加载
【发布时间】:2009-03-27 05:32:34
【问题描述】:

我目前正试图弄清楚如何将 RichTextbox 中的内容保存到流中(当前使用 FileStream),并与一堆其他数据一起执行此操作。然后我当然希望能够从这个文件中加载。 我目前正在尝试使用以下内容。

FileStream stream = new FileStream(); //this is actually correctly defined.
ASCIIEncoding encoding = new ASCIIEncoding();

//write Title
byte[] array = encoding.GetBytes(Title);
stream.WriteByte(Convert.ToByte(array.Length));
stream.Write(array, 0, array.Length);

//save textRange
textRange.Save(stream, System.Windows.DataFormats.Rtf);

//write Subtitle
byte[] array = encoding.GetBytes(Subtitle);
stream.WriteByte(Convert.ToByte(array.Length));
stream.Write(array, 0, array.Length);
//ect...and something very similar for Loading a file.

这基本上就是我想要做的。我实际上保存了 2 个 TextRanges 和更多的属性。所以我的问题是 TextRange.Load() 读取到文件的末尾......考虑到我有 2 个需要保存/加载的 TextRanges,我无法使用它。 所以在这里我试图想出另一种方法来保存/加载 RichTextBox 的内容和其他数据。我不必使用流。我对任何可行的解决方案都持开放态度。提前致谢!

~杰森

【问题讨论】:

    标签: c# load richtextbox save


    【解决方案1】:

    您可以加载/保存到 MemoryStream 以解决读取到文件末尾的问题。它可能看起来像这样:

    • 将文件加载到内存中
    • 将该文件中作为富文本框内容的部分加载到 MemoryStream 中
    • 从该 MemoryStream 加载 Richtextbox 内容

    或者您想知道如何创建和解析文件以包含标题、内容和任何其他字段的不同部分?

    【讨论】:

    • 我怎么知道 RichTextBox 的内容有多长?在写入 RichTextBox 的内容后,我是否会立即在文件中写入一些标志字节。那么我可以告诉内容何时真正结束并使用标志之前的字节 [] 作为 MemoryStream?这是我最好的猜测。
    • 你不需要标志。由于您将各种文本范围保存为 RTF,因此所有 RTF 文档都以“{\rtf”开头并以“}”结尾。 (请参阅 RTF 规范 1.9.1。)当然,这意味着解析您的流,但无论如何您都会这样做,以根据上面的代码找到您的标题、副标题等。
    • 我搞定了。我没有解析它来寻找 '{\rtf' 和 '}' 但是我会在不久的将来研究它,因为它可能是比我目前正在做的更好/更安全的方法。谢谢你们的帮助。对此,我真的非常感激! :D
    【解决方案2】:

    我想我应该发布我当前的解决方案。它似乎工作得很好。感谢 Chris 和 Ants 提供有关如何执行此操作的提示。

    /// <summary>
        /// Reads a TextRange (DataFormats.Rtf) from the stream.
        /// </summary>
        /// <param name="stream">The stream to be read from.</param>
        /// <returns>The TextRange (DataFormats.Rtf) that was read from the stream.</returns>
        public static TextRange ReadTextRange(FileStream stream)
        {
            long startPos = stream.Position;
            int length = -1;
            int count = 0;
            int previousByte = 0;
            int currentByte = 0;
            //set previousByte to give the current one something to compare to
            previousByte = stream.ReadByte();
            //parse the file counting the { and } to find the end of the rtf portion of the file.
            while (count > 0 || length < 1)
            {
                length++;
                stream.Position = startPos + length;
                currentByte = stream.ReadByte();
                if (previousByte != 92) // not '\' so check to see if '{' or '}' is currentByte
                {
                    if (currentByte == 123) // '{' increase count
                        count++;
                    else if (currentByte == 125) // '}' decrease count
                        count--;
                }
                previousByte = currentByte;
            }
            //save finish position to move to later
            long finishPos = stream.Position;
            //reset stream position to start at beginning of rtf
            stream.Position = startPos;
            //read the rtf portion of the file into a byte[]
            byte[] content = new byte[length];
            stream.Read(content, 0, length);
            //put the byte[] into a memory stream
            MemoryStream memStream = new MemoryStream(content);
            FlowDocument doc = new FlowDocument();
            TextRange range = new TextRange(doc.ContentStart, doc.ContentEnd);
            //have the TextRange read from the memorystream
            range.Load(memStream, System.Windows.DataFormats.Rtf);
            memStream.Close();
            //set the position to after the rtf portion of the file
            stream.Position = finishPos;
            return range;
        }
    

    此 ReadTextRange 方法位于我为帮助从 FileStream 读取而定义的 StreamHelper 类中。所以这一切都是为了像这样加载一个保存到 FileStream 的 TextRange...

    //save query (TextRange)
            Query.Save(stream, System.Windows.DataFormats.Rtf);
    

    我希望有人在遇到类似问题时发现这很有用! :D

    编辑:

    我使用了分析器,发现这段代码效率不高,所以我对这段代码进行了一些更改,以提高效率。

    1. 不要使用 TextRange,而是使用包含 MemoryStream memStream 内容的 byte[]。这会减少 range.Load 消耗大量 CPU。

    2. 我取出了stream.Position = startPos + length这一行,因为我意识到它在第一次运行后没有用,而且还占用了相当多的CPU。我放置了stream.Position--;在 previousByte = stream.ReadByte();

    3. 行之后

    我还意识到我是一个糟糕的编码员,并且没有通过在我的数据类中包含 TextRange、UI 元素来遵循 MVC。现在它有一个字节[],这要好得多。

    再次编辑:

    在使用 byte[] 而不是 TextRange 几分钟后,我意识到我有 byte[] 的大小,所以我不需要解析它。因此,我保存写入字节 [] 大小,然后写入字节 []。这使其速度非常快,几乎可以立即读取一个非常大的文件。

    【讨论】:

    • 谢谢 Jasson - StackOverflowering 的典范 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多