Мне нужен метод замены без учета регистра, который работает с классом StringBuilder - PullRequest
2 голосов
/ 30 июля 2010

Мне нужен код для нечувствительного к регистру метода Replace для класса StringBuilder.Код должен работать с существующим StringBuilder.Реализация метода расширения была бы хороша.

Вот как я планирую использовать метод:

    [TestMethod]
    public void StringBuilder_Replace_TTD() {

        StringBuilder oRequestText = new StringBuilder(File.ReadAllText("Customer.xml"));

        Customer oCustomer = new Customer(null);

        foreach (FieldIndex iField in Enum.GetValues(typeof(FieldIndex))) {

            oRequestText.Replace("{" iField.ToString() + "}", oCustomer[iField]);

        }

        Debug.WriteLine(oRequestText.ToString());
    }

Ответы [ 4 ]

3 голосов
/ 30 июля 2010

StringBuilder не поддерживает использование IComparer при поиске / замене текста (фактически, вообще нет поддержки поиска). Вы могли бы попробовать развернуть посимвольную версию, но это будет сложно и может все еще работать плохо.

Исходя из вашего варианта использования, я бы предложил использовать строку, а не StringBuilder, и использовать string.IndexOf(), чтобы найти позиции во входной строке, где вы собираетесь выполнять замену, что поддерживает поиск без учета регистра. Как только вы нашли все области замены, создайте StringBuilder, а затем скопируйте каждую область, заменив найденный текст требуемыми значениями замены.

РЕДАКТИРОВАТЬ: Предположительно, вы собираетесь использовать замену на StringBuilder, чтобы избежать выделения дополнительных строк и понизить производительность. Однако замена текста в буфере StringBuilder на самом деле может быть более дорогой, особенно если строки замены имеют другую длину, чем исходная строка, которую они заменяют. Каждая замена требует, чтобы символы были смещены вперед или назад в зависимости от того, короче или длиннее замещающий текст. Выполнение перемещений блока памяти, как это будет дорого.

2 голосов
/ 30 июля 2010

От: http://blogs.msdn.com/b/btine/archive/2005/03/22/400667.aspx

string Replace( string expr, string find, string repl, bool bIgnoreCase )  
{
// Get input string length
       int exprLen = expr.Length;
       int findLen = find.Length;

       // Check inputs    
       if( 0 == exprLen || 0 == findLen || findLen > exprLen )    
              return expr;

       // Use the original method if the case is required    
       if( !bIgnoreCase )
              return expr.Replace( find, repl );

       StringBuilder sbRet = new StringBuilder( exprLen );

       int pos = 0;              
       while( pos + findLen <= exprLen )    
       {    
              if( 0 == string.Compare( expr, pos, find, 0, findLen, bIgnoreCase ) )    
              {    
                     // Add the replaced string    
                     sbRet.Append( repl );    
                     pos += findLen;    
                     continue;    
              }

              // Advance one character    
              sbRet.Append( expr, pos++, 1 );    
       }

       // Append remaining characters    
       sbRet.Append( expr, pos, exprLen-pos );

       // Return string    
       return sbRet.ToString();    
}
0 голосов
/ 30 декабря 2014

Я бы использовал метод замены RegEx, но это означает преобразование из StribgBuilder в строку

oRequestText = new StringBuilder(Regex.Replace(oRequestText.ToString(), "{" iField.ToString() + "}", oCustomer[iField], RegexOptions.IgnoreCase)));
0 голосов
/ 30 июля 2010

В вашем примере вы хотите сделать (в псевдокоде):

StringBuilder oRequestText = ...;
For all fields do replace on oRequestText;
Debug.WriteLine(oRequestText.ToString());

Поскольку после этого вы фактически не используете StringBuilder, функциональной разницы с

нет
StringBuilder oRequestText = ...;
string strRequest = oRequestText.ToString();
For all fields do replace on strRequest;
Debug.WriteLine(strRequest);

Обычные функции замены для строк должны легко поддерживать то, что вы хотите сделать.

Я предполагаю, что в вашей реальной ситуации вы действительно хотите снова использовать StringBuilder. Но, вероятно, все еще проще всего сделать .ToString (), заменить строку, а затем перезагрузить StringBuilder со строкой.

...