Как преобразовать строку в RTF в С#?
Вопрос
Как преобразовать строку "Européen" в строку в формате RTF "Europ\e9en"?
[TestMethod]
public void Convert_A_Word_To_Rtf()
{
// Arrange
string word = "Européen";
string expected = "Europ\'e9en";
string actual = string.Empty;
// Act
// actual = ... // How?
// Assert
Assert.AreEqual(expected, actual);
}
Что я нашел до сих пор
RichTextBox
RichTextBox может использоваться для определенных целей. Пример:
RichTextBox richTextBox = new RichTextBox();
richTextBox.Text = "Européen";
string rtfFormattedString = richTextBox.Rtf;
Но тогда rtfFormattedString оказывается полностью документом, отформатированным в формате RTF, а не только строкой "Europ\e9en".
Stackoverflow
Google
Я также нашел в Интернете множество других ресурсов, но ничто не решило мою проблему.
Ответ
Брэд Кристи ответ
Придется добавить Trim()
, чтобы удалить предыдущее пространство в result
. Кроме того, решение Brad Christie похоже работает.
Теперь я буду работать с этим решением, даже если у меня плохое чувство кишки, поскольку мы должны подстроить SubString и исправить из RichTextBox, чтобы получить строку в формате RTF.
Тестовый пример:
[TestMethod]
public void Test_To_Verify_Brad_Christies_Stackoverflow_Answer()
{
Assert.AreEqual(@"Europ\'e9en", "Européen".ConvertToRtf());
Assert.AreEqual(@"d\'e9finitif", "définitif".ConvertToRtf());
Assert.AreEqual(@"\'e0", "à".ConvertToRtf());
Assert.AreEqual(@"H\'e4user", "Häuser".ConvertToRtf());
Assert.AreEqual(@"T\'fcren", "Türen".ConvertToRtf());
Assert.AreEqual(@"B\'f6den", "Böden".ConvertToRtf());
}
Логика как метод расширения:
public static class StringExtensions
{
public static string ConvertToRtf(this string value)
{
RichTextBox richTextBox = new RichTextBox();
richTextBox.Text = value;
int offset = richTextBox.Rtf.IndexOf(@"\f0\fs17") + 8; // offset = 118;
int len = richTextBox.Rtf.LastIndexOf(@"\par") - offset;
string result = richTextBox.Rtf.Substring(offset, len).Trim();
return result;
}
}
Ответы
Ответ 1
Не имеет ли RichTextBox
один и тот же заголовок/нижний колонтитул? Вы могли бы просто прочитать контент, основанный на отключенном местоположении, и продолжить использовать его для разбора. (Я думаю, пожалуйста, поправьте меня, если я ошибаюсь)
Доступны библиотеки, но мне никогда не удавалось с ними лично (хотя всегда просто находил другой метод, прежде чем полностью исчерпывать возможности). Кроме того, большинство из лучших обычно включают номинальную плату.
ИЗМЕНИТЬ
Вид взлома, но вам нужно пройти через то, что вам нужно пройти (надеюсь):
RichTextBox rich = new RichTextBox();
Console.Write(rich.Rtf);
String[] words = { "Européen", "Apple", "Carrot", "Touché", "Résumé", "A Européen eating an apple while writing his Résumé, Touché!" };
foreach (String word in words)
{
rich.Text = word;
Int32 offset = rich.Rtf.IndexOf(@"\f0\fs17") + 8;
Int32 len = rich.Rtf.LastIndexOf(@"\par") - offset;
Console.WriteLine("{0,-15} : {1}", word, rich.Rtf.Substring(offset, len).Trim());
}
РЕДАКТИРОВАТЬ 2
разбивка кода управления кодом RTF выглядит следующим образом:
- Заголовок
-
\f0
- Используйте шрифт 0-index (первый шрифт в списке, который обычно является Microsoft Sans Serif (отмечен в шрифте таблица в заголовке: {\fonttbl{\f0\fnil\fcharset0 Microsoft Sans Serif;}}
))
-
\fs17
- Форматирование шрифта, укажите размер 17 (17 в полутонах)
- Footer
-
\par
указывает, что это конец абзаца.
Надеюсь, это прояснит некоторые вещи.; -)
Ответ 2
Вот как я пошел:
private string ConvertString2RTF(string input)
{
//first take care of special RTF chars
StringBuilder backslashed = new StringBuilder(input);
backslashed.Replace(@"\", @"\\");
backslashed.Replace(@"{", @"\{");
backslashed.Replace(@"}", @"\}");
//then convert the string char by char
StringBuilder sb = new StringBuilder();
foreach (char character in backslashed.ToString())
{
if (character <= 0x7f)
sb.Append(character);
else
sb.Append("\\u" + Convert.ToUInt32(character) + "?");
}
return sb.ToString();
}
Я думаю, используя RichTextBox
:
1) overkill
2) Мне не нравится RichTextBox
после нескольких дней попыток заставить его работать с RTF-документом, созданным в Word.
Ответ 3
Ниже приведен уродливый пример преобразования строки в строку RTF:
class Program
{
static RichTextBox generalRTF = new RichTextBox();
static void Main()
{
string foo = @"Européen";
string output = ToRtf(foo);
Trace.WriteLine(output);
}
private static string ToRtf(string foo)
{
string bar = string.Format("[email protected]@!!{0}[email protected]@!!", foo);
generalRTF.Text = bar;
int pos1 = generalRTF.Rtf.IndexOf("[email protected]@!!");
int pos2 = generalRTF.Rtf.LastIndexOf("[email protected]@!!");
if (pos1 != -1 && pos2 != -1 && pos2 > pos1 + "[email protected]@!!".Length)
{
pos1 += "[email protected]@!!".Length;
return generalRTF.Rtf.Substring(pos1, pos2 - pos1);
}
throw new Exception("Not sure how this happened...");
}
}
Ответ 4
Я знаю, что прошло какое-то время, надеюсь, что это поможет.
Этот код работает для меня после того, как я пробовал каждый код конвертации, на который я мог положиться:
titleText и contentText - это простой текст, заполненный обычным TextBox
var rtb = new RichTextBox();
rtb.AppendText(titleText)
rtb.AppendText(Environment.NewLine);
rtb.AppendText(contentText)
rtb.Refresh();
rtb.rtf теперь содержит текст rtf.
Следующий код сохранит текст rtf и позволит вам открыть файл, отредактировать его и снова загрузить обратно в RichTextBox:
rtb.SaveFile(path, RichTextBoxStreamType.RichText);
Ответ 5
Я нашел хорошее решение, которое на самом деле использует RichTextBox для преобразования:
private static string FormatAsRTF(string DirtyText)
{
System.Windows.Forms.RichTextBox rtf = new System.Windows.Forms.RichTextBox();
rtf.Text = DirtyText;
return rtf.Rtf;
}
http://www.baltimoreconsulting.com/blog/development/easily-convert-a-string-to-rtf-in-net/
Ответ 6
Не самый элегантный, но довольно оптимальный и быстрый метод:
public static string PlainTextToRtf(string plainText)
{
if (string.IsNullOrEmpty(plainText))
return "";
string escapedPlainText = plainText.Replace(@"\", @"\\").Replace("{", @"\{").Replace("}", @"\}");
escapedPlainText = EncodeCharacters(escapedPlainText);
string rtf = @"{\rtf1\ansi\ansicpg1250\deff0{\fonttbl\f0\fswiss Helvetica;}\f0\pard ";
rtf += escapedPlainText.Replace(Environment.NewLine, "\\par\r\n ") + ;
rtf += " }";
return rtf;
}
.
Кодировать символы (польские):
private static string EncodeCharacters(string text)
{
if (string.IsNullOrEmpty(text))
return "";
return text
.Replace("ą", @"\'b9")
.Replace("ć", @"\'e6")
.Replace("ę", @"\'ea")
.Replace("ł", @"\'b3")
.Replace("ń", @"\'f1")
.Replace("ó", @"\'f3")
.Replace("ś", @"\'9c")
.Replace("ź", @"\'9f")
.Replace("ż", @"\'bf")
.Replace("Ą", @"\'a5")
.Replace("Ć", @"\'c6")
.Replace("Ę", @"\'ca")
.Replace("Ł", @"\'a3")
.Replace("Ń", @"\'d1")
.Replace("Ó", @"\'d3")
.Replace("Ś", @"\'8c")
.Replace("Ź", @"\'8f")
.Replace("Ż", @"\'af");
}