Environment.NewLine和TextWriter.NewLine属性的用途是什么

时间:2013-08-04 09:57:16

标签: c# io newline

我有一个奇怪的情况,我不理解与我发送到文件的换行符'\n'有关。根据{{​​1}}和NewLine的{​​{1}}属性,似乎不会对换行符进行处理。此代码演示了:

TextWriter

当我运行它时,控制台输出是

  

2
  2

当我以十六进制模式查看我的文件时,我得到:

  <00> 00000000h:31 EF 83 B1 0A 32 EE 83 A1 0A 33 ED 83 91 0A;   1.2.3탓。

显然,API会显示两个字符,当您查看文件时,只有一个字符。现在,当我查看TextWriter中Write方法的描述时,它表明Write方法不会将0A替换为NewLine属性。好吧,如果Write方法没有考虑到这一点,那么只有两个NewLine属性的用途是什么?这些东西是为了什么?

4 个答案:

答案 0 :(得分:4)

程序员有很长的历史同意在将文本写入文件时应如何编码文本。 ASCII和Unicode在一定程度上帮助了巴别塔的水平。但是什么字符表示一行的结尾从未达成一致。

  • Windows使用回车符+换行控制代码。 C#代码中的"\r\n"
  • Unix版本只使用C#代码中的单个换行控制代码'\n'
  • Apple过去只使用C#代码中的一个回车控制代码'\r'

.NET需要兼容所有这些不兼容的选择。因此它添加了Environment.NewLine属性,它具有操作系统的默认行结束顺序。请注意如何在具有Mono或Silverlight的Unix和Apple机器上运行.NET代码。

抽象TextWriter类需要知道在写入文本文件时要使用的序列。所以它有一个NewLine属性,它的默认值与Environment.NewLine相同。您几乎总是使用它,但如果您需要创建一个由另一个操作系统上的程序读取的文本文件,您可能想要更改它。

您在程序中犯的错误是硬编码行终止符。你在字符串中使用了'\ n'。这完全绕过了.NET属性,您只能在文本文件中看到单行换行控制代码。 0x0A是换行符。您的控制台输出显示“2”,因为它只显示NewLine属性的字符串长度。对于“\ r \ n”,Windows上为2。

使用.NET属性的最简单方法是使用WriteLine()而不是Write():

  sw.WriteLine("1\uf0f1");
  sw.WriteLine("2\ue0e1");
  sw.WriteLine("3\ud0d1"); 

这使得您的代码也可以很好地读取,它在运行时并不慢。如果你想保留单行,那么你可以使用复合格式:

  sw.Write("1\uf0f1{0}2\ue0e1{0}3\ud0d1{0}", Environment.NewLine);

答案 1 :(得分:1)

如果选择通过将\ n发送给streamwriter来生成'linebreaks',那么框架就无法干扰它。如果您希望框架遵守NewLine属性,请使用writer的WriteLine方法并设置Writer的Ne​​wLine属性。

像这样调整你的代码:

sw.NewLine = Environment.NewLine; // StreamWriter uses \r\n by default

sw.WriteLine("1\uf0f1")
sw.WriteLine("2\ue0e1");
sw.WriteLine("3\ud0d1");

或者有一个自定义StreamWriter覆盖Write方法:

public class MyStreamWriter:StreamWriter
{
    public MyStreamWriter(Stream s):base(s)
    {
    }

    public override void Write(string s)
    {
        base.Write(s.Replace("\n",Environment.NewLine));
    }   
}

或者,如果您只想要处理一行:

sw.Write("1\uf0f1\n2\ue0e1\n3\ud0d1\n".Replace("\n", Environment.NewLine));

答案 2 :(得分:0)

如果隐式使用,如在调用WriteLine方法中或在Write(String.Concat(“Hello”,Environment.NewLine)中显式使用,则会获得为您的环境定义的行尾字符。如果您不要使用它并使用说'\ n'或甚至'$',然后你说无论我在什么环境,行将像我说的那样结束。如果你想比较行为,写一点代码并在windows和linux(mono)下运行它

答案 3 :(得分:0)

所有换行符都是字符串中的\ n转换为单字符ASCII换行符(0x0A)(不是Windows换行符0D0A)并输出到写入器中的流为0x0A,除非程序员采取一些明确的步骤将字符串中的这些转换为格式0D0A。

TextWriter.NewLine属性仅由WriteLine等方法使用,并控制作为调用的一部分附加的隐式换行符的格式。

Environment.NewLineTextWriter.NewLine之间的区别在于Environment.NewLine是只读的,只是程序员要查询的。 (例如,这与Java不同,您可以使用System.setProperty("line.separator", x);

更改“系统级”换行格式默认值

在C#中,您可以使用TextWriter.NewLine进行书写时修改隐式换行符的格式,Environment.NewLine初始化为TextReader.NewLine。使用读取行的TextReader方法时,没有sw.Write("1\uf0f1\n2\ue0e1\n3\ud0d1\n".Replace("\n", Environment.NewLine)); 属性。读者的隐式换行行为是在任何0x0A,0x0D或0D0A

处中断

正如勒内所指出的,原始问题可以通过写下来解决:

{{1}}