C# StringBuilder:检查是否以换行符结尾

9

我有一个StringBuilder用于累积代码。在某些情况下,代码块之间会有2个空行,我想把它们变成1个空行。
如何检查当前代码是否已经以空行结尾?(我不想使用 ToString() 方法,因为会影响性能。)


你要么在添加行/块时检查它们 - 要么将所有“双换行符”替换为一个,然后修剪末尾。 - Dave Bish
1
可以使用Replace函数将两个Environment.NewLine的出现替换为一个Environment.NewLine(在构建结束时)。另一种可能性是使用ToString(length-1,1)来获取最后一个字符。 - Eyal H
这是我最终所做的。它被发布为答案,但因为有人提到它也会删除代码中间的双重换行符而被删除。对我来说真的无关紧要,所以如果这个解决方案被发布为答案,我会标记它。 - Noich
7个回答

7

您可以通过索引访问StringBuilder中的任何字符,就像您处理String一样。

var sb = new StringBuilder();
sb.Append("Hello world!\n");
Console.WriteLine(sb[sb.Length - 1] == '\n'); // True

我在谈论巨大的代码块。 我尝试检查结尾字符,但变得混乱了。 - Noich
为什么变得混乱了?如果你编写一个接受 StringBuilder 的方法,那么你可以创建一个整洁的小子程序。分而治之。请注意,这适用于 Linux 和 Windows,但不适用于 Mac OSX 之前的 Mac 行尾,其以 \r 结尾(但这很容易编程,是史前时期的事情)。 - Maarten Bodewes

2

我得到了一个“有趣”的答案:

var sb = new StringBuilder();
sb.AppendLine("test");
sb.AppendLine("test2");

Console.WriteLine(sb.ToString().TrimEnd('\n').Length != sb.ToString().Length); //true

目前你的回答不够清晰,请编辑并添加更多细节,以帮助其他人理解它如何回答问题。你可以在帮助中心找到有关如何编写好答案的更多信息。 - Community

1

您可以使用正则表达式来规范化换行符:

var test = @"hello

moop

hello";

var regex = new Regex(@"(?:\r\n|[\r\n])+");

var newLinesNormalized = regex.Replace(test, Environment.NewLine);

输出:

hello
moop
hello

2
这与 StringBuilder 有什么关系? - Clément

1

单行检查。使用字符串类型,而不是StringBuilder,但您应该了解基本思路。

if (theString.Substring(theString.Length - Environment.NewLine.Length, Environment.NewLine.Length).Contains(Environment.NewLine))
{
     //theString does end with a NewLine
}
else
{
     //theString does NOT end with a NewLine
}

当然,这仅适用于平台默认的行尾符,可能有点自以为是。它似乎也没有使用StringBuilder - Maarten Bodewes
@MaartenBodewes 平台检测不是必需的,我在开头明确表示它不使用 StringBuilder。重新阅读原始问题后,我不确定它是否解决了他的问题 - 他想检查整个字符串末尾是否有额外的换行符,还是想分析字符串中的每个“行”并删除双重换行符... - Dave Thompson
当然,问题是由特定用户编写的,但它们应适用于其他用户。如果这仅适用于平台编码,则至少在答案中说明,否则每个复制您的代码的人都可能遇到问题。问题明确指出最好不要使用字符串 - 但除此之外,如果可以使用字符串,那么问题对其他人来说将不那么有用; 这是一个更容易解决的问题(正则表达式等)。感谢您再次查看。 - Maarten Bodewes

0

这是完整的示例。

class string_builder
{
    string previousvalue = null;
    StringBuilder sB;
    public string_builder()
    {
        sB = new StringBuilder();
    }
    public void AppendToStringBuilder(string new_val)
    {
        if (previousvalue.EndsWith("\n") &&  !String.IsNullOrEmpty(previousvalue) )
        {
            sB.Append(new_val);
        }
        else
        {
            sB.AppendLine(new_val);
        }

        previousvalue = new_val;
    }

}
class Program
{

    public static void Main(string[] args)
    {
        string_builder sb = new string_builder();            
        sb.AppendToStringBuilder("this is line1\n");
        sb.AppendToStringBuilder("this is line2");
        sb.AppendToStringBuilder("\nthis is line3\n");

    }            
}

这将需要对我的代码进行巨大的更改 - 我希望尽量减少更改。不过感谢提供代码示例。 - Noich
这只是一个代码示例,没有回答标题中的问题。 - Maarten Bodewes

-1

既然我不在乎代码中间的两行空白,最简单的方法就是使用

myCode.Replace(string.Format("{0}{0}", Environment.NewLine),Environment.NewLine);

这个选项不需要对使用代码累加器的类进行任何更改。


如果myCode没有使用Environment.NewLine作为行分隔符,那么这种方法是行不通的。此外,这种方法并不比ToString更有效率。 - Clément
即使这对您的特定情况似乎有效,但这并不是您提出的问题的答案。 - Maarten Bodewes

-1
如果有人像我一样来到这里,以下是一种通用方法,可以检查 StringBuilder 的结尾是否为任意字符串,而不必在其上使用 ToString
public static bool EndsWith(this StringBuilder haystack, string needle)
{
    var needleLength = needle.Length - 1;
    var haystackLength = haystack.Length - 1;
    if (haystackLength < needleLength)
    {
        return false;
    }
    for (int i = 0; i < needleLength; i++)
    {
        if (haystack[haystackLength - i] != needle[needleLength - i])
        {
            return false;
        }
    }
    return true;
}

可能存在多种行结尾,而您的搜索只接受一个字符串。 - Maarten Bodewes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接