2011-01-25 19 views
12

DomandaCome convertire una stringa in RTF in C#?

Come faccio a convertire la stringa "Européen" alla stringa di formato 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); 
} 

Quello che ho trovato finora

RichTextBox

RichTextBox può essere utilizzato per certe cose. Esempio:

RichTextBox richTextBox = new RichTextBox(); 
richTextBox.Text = "Européen"; 
string rtfFormattedString = richTextBox.Rtf; 

Ma poi rtfFormattedString risulta essere l'intero documento in formato RTF, non solo la stringa "Europ \ 'e9en".

StackOverflow

Google

Ho anche trovato un sacco di altre risorse sul web, ma nulla ha risolto il mio problema.

risposta

Brad Christie's answer

dovuto aggiungere Trim() per rimuovere lo spazio precedente in result. Oltre a questo, la soluzione di Brad Christie sembra funzionare.

Per ora corro con questa soluzione anche se ho un pessimo sentimento perché dobbiamo SubString e Trim il diavolo da RichTextBox per ottenere una stringa in formato RTF.

Test case:

[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()); 
} 

Logica come un metodo di estensione:

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; 
    } 
} 
+0

possibile duplicato di [output RTF caratteri speciali Unicode] (http: // STA ckoverflow.com/questions/1310694/output-rtf-special-characters-to-unicode) –

+0

@Abe Miessler: avevo visto questa domanda e ho aggiunto il link alla mia domanda sopra. Tuttavia, non vedo come questo risolva il mio problema (probabilmente lo fa, ma non lo capisco). Potresti forse fornire uno snippet di codice che rende obsoleto il precedente metodo di test? – Lernkurve

+0

Controlla di nuovo la mia risposta, ho inviato una soluzione (hacky) alla tua domanda. La mia speranza è che tu stia solo traducendo alcune cose minori/più semplici. –

risposta

6

non RichTextBox ha sempre la stessa intestazione/piè di pagina? Potresti semplicemente leggere il contenuto in base al luogo impostato e continuare a usarlo per analizzare. (Penso, per favore correggimi se ho torto)

Ci sono librerie disponibili, ma non ho mai avuto fortuna con loro personalmente (anche se ho sempre trovato un altro metodo prima di esaurire completamente le possibilità). Inoltre, la maggior parte dei migliori di solito include una tassa nominale.


EDIT
una specie di hack, ma questo dovrebbe ottenere attraverso ciò che è necessario per ottenere attraverso (spero):

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()); 
} 

EDIT 2

breakdown of the codes RTF control code sono i seguenti:

  • Header
    • \f0 - Utilizzare il tipo di carattere 0-index (primo font nella lista, che in genere è Microsoft Sans Serif (indicato nella tabella di carattere nell'intestazione: {\fonttbl{\f0\fnil\fcharset0 Microsoft Sans Serif;}}))
    • \fs17 - Font formattazione, specificare la dimensione è 17 (17 essendo in mezzi punti)
  • piè
    • \par è specificando t è la fine di un paragrafo.

Speriamo che cancella alcune cose. ;-)

+0

Il metodo fallirà se la lunghezza dell'intestazione cambierà mai. Il mio metodo fallirà se l'intestazione include sempre la stringa "!! @@ !!" (ma non fallirà se la stringa di input contiene "!! @@ !!"). – Brian

+0

@Brian: le mie intestazioni cambiano. la differenza tra l'emissione di "Apple" e "Européen" rende il cambio di intestazione. –

+0

@Brad Christie: Voglio dire se "\ fo \ fs17" cambia mai. Ammetto che è improbabile. Immagino di avere solo un'avversione a seconda dei dettagli di implementazione. – Brian

1

Di seguito è un brutto esempio di conversione di una stringa in una stringa 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..."); 
    } 
} 
+0

Grazie per aver dedicato del tempo per pubblicare il codice. Dovrò dargli un'occhiata. I punti esclamativi sembrano spaventosi ... – Lernkurve

+2

@Lernkurve: "!! @@ !!" è un delimitatore arbitrario e appartiene davvero a un 'const String'. – Brian

+0

Grazie per la spiegazione. Avrei dovuto vederlo anch'io. :-) – Lernkurve

-1

Non il più elegante, ma proprio ottimale e veloce metodo:

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; 
} 

. Metodo

caratteri Encode (quelli polacchi):

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"); 
} 
+0

Con la tua soluzione, come fai a sapere di aver coperto tutti i possibili caratteri speciali? Se un personaggio non è nella lista di sostituzione della tua EncodeCharacters, allora si rivelerà sbagliato, giusto? – Lernkurve

3

Ecco come sono andato:

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(); 
} 

Credo che utilizzando un RichTextBox è:
1) eccessivo
2) I don Mi piace RichTextBox dopo aver trascorso giorni a provare a farlo funzionare con un documento RTF creato in Word.

1

So che è stato un po ', spero che questo aiuta ..

Questo codice sta lavorando per me dopo aver provato ogni codice di conversione ho potuto mettere le mani su:

TitleText e contentText sono semplice testo compilato in un controllo TextBox regolare

var rtb = new RichTextBox(); 
rtb.AppendText(titleText) 
rtb.AppendText(Environment.NewLine); 
rtb.AppendText(contentText) 

rtb.Refresh(); 

rtb.rtf detiene ora il testo RTF.

Il seguente codice salvare il testo RTF e permetterà di aprire il file, modificarlo e di caricarlo di nuovo in un RichTextBox di nuovo:

rtb.SaveFile(path, RichTextBoxStreamType.RichText); 
Problemi correlati