Подтвердить что ты не робот

Как преобразовать строку в 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;
    }
}
4b9b3361

Ответ 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);

Ответ 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");
}