Salvando / Carregando conteúdo RichTextBox com outros dados usando C #
-
22-08-2019 - |
Pergunta
Atualmente, estou tentando descobrir como salvar o conteúdo de um RichTextbox em um fluxo (atualmente usando FileStream) e fazer isso ao lado de um monte de outros dados. Então é claro que eu quero ser capaz de carregar a partir deste arquivo. Eu estava atualmente tentando usar algo ao longo das seguintes linhas.
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.
Este é basicamente o que eu estou tentando fazer. Na verdade, estou salvando 2 TextRanges e um monte mais Imóveis. Portanto, meu problema é que TextRange.Load () lê até o fim do arquivo ... o que torna impossível para mim usar que, considerando eu tenho 2 TextRanges eu preciso para salvar / carga. Então aqui eu estou tentando chegar a uma outra maneira de ser capaz de salvar / carregar o conteúdo de um RichTextBox com outros dados. Eu não tenho que usar um Stream. Estou praticamente aberto a todas as soluções viáveis. Agradecemos antecipadamente!
~ Jasson
Solução
Você pode carregar / salvar em um MemoryStream para resolver o seu problema com a leitura até o final do arquivo. Ele poderia ficar assim:
- Coloque o arquivo na memória
- Coloque a seção do arquivo que é o conteúdo do richtextbox em um MemoryStream
- Coloque o conteúdo RichTextBox que MemoryStream
Ou você está querendo saber como você pode criar e analisar um arquivo para conter seções diferentes para o título eo conteúdo, e quaisquer outros campos?
Outras dicas
Eu percebi que eu deveria postar minha solução atual. Parece que funciona perfeitamente bem. Obrigado Chris e formigas às dicas sobre como ir sobre fazer isto.
/// <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;
}
Este método ReadTextRange está em uma classe StreamHelper I definido por ajudar a ler de um FileStream. Então, tudo isso é para carregar um TextRange que é salvo no FileStream assim ...
//save query (TextRange)
Query.Save(stream, System.Windows.DataFormats.Rtf);
Espero que alguém acha isso útil se / quando eles vêm para um problema semelhante! : D
EDIT:
Eu usei um profiler e descobriu que este código não foi muito eficiente, então eu mudou este código para ser muito mais eficiente em alguns aspectos.
-
Em vez de usar o TextRange e usar um byte [] que detém o conteúdo de MemoryStream memStream. Isto reduz a range.Load que consome muita CPU.
-
Eu tirei a linha stream.Position = startPos + comprimento porque eu percebi que era inútil após a primeira corrida e também tomou-se uma quantidade razoável de CPU. I colocado stream.Position--; após a linha previousByte = stream.ReadByte ();
Além disso, percebi que eu estava sendo um mau codificador e não estava seguindo MVC por ter TextRange, elemento UI, dentro da minha classe de dados. Agora ele tem um byte [], que é muito melhor.
EDIT novamente:
Depois de alguns minutos de ter o byte [] em vez do TextRange eu percebi que tinha o tamanho do byte [] para que eu não tinha necessidade de analisá-lo. Então, ao invés eu salvo escrever o tamanho byte [] e, em seguida, o byte []. Isto torna extremamente rápido e pode ler um arquivo muito grande quase instantaneamente.