Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/322.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Environment.NewLine和TextWriter.NewLine属性的用途是什么_C#_Io_Newline - Fatal编程技术网

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

C# Environment.NewLine和TextWriter.NewLine属性的用途是什么,c#,io,newline,C#,Io,Newline,我有一个奇怪的情况,我不理解与我要发送到文件的新行“\n”有关的情况。根据TextWriter和Environment的换行符属性,似乎不会对换行符进行处理。此代码演示: String baseDir = Environment.GetEnvironmentVariable("USERPROFILE") + '\\'; String fileName = baseDir + "deleteme5.txt"; FileInfo fi = new FileInfo(fileName); fi.Del

我有一个奇怪的情况,我不理解与我要发送到文件的新行“\n”有关的情况。根据TextWriter和Environment的换行符属性,似乎不会对换行符进行处理。此代码演示:

String baseDir = Environment.GetEnvironmentVariable("USERPROFILE") + '\\';
String fileName = baseDir + "deleteme5.txt";
FileInfo fi = new FileInfo(fileName);
fi.Delete();
FileStream fw = new FileStream(fileName, FileMode.CreateNew, FileAccess.Write);
StreamWriter sw = new StreamWriter(fw);
Console.WriteLine(Environment.NewLine.Length);
Console.WriteLine(sw.NewLine.Length);
sw.Write("1\uf0f1\n2\ue0e1\n3\ud0d1\n");
sw.Flush();
sw.Close();
当我运行此命令时,控制台输出为

二, 二,

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

00000000小时:31 EF 83 B1 0A 32 EE 83 A1 0A 33 ED 83 91 0A; 1ïƒ.2îƒ.3ƒ”


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

如果选择通过发送给streamwriter来生成“换行符”,则框架将无法与之干涉。如果希望框架支持换行符属性,请使用writer的WriteLine方法并设置writer的换行符属性

对代码进行如下调整:

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

sw.WriteLine("1\uf0f1")
sw.WriteLine("2\ue0e1");
sw.WriteLine("3\ud0d1");
或具有覆盖写入方法的自定义StreamWriter:

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

如果在调用WriteLine方法时隐式使用,或在WriteString.Concatherlo、Environment.NewLine中显式使用,则会得到为环境定义的行尾字符。如果您不使用它,并使用“\n”甚至“$”,那么您的意思是,无论我在什么环境中,行都会像我所说的那样结束。如果您想比较行为,请编写一段代码并在windows和linux mono下运行。程序员长期以来一直不同意在将文本写入文件时如何对其进行编码。ASCII和Unicode在一定程度上帮助了巴别塔的升级。但是,什么字符表示一行的结尾从未达成一致

Windows使用回车+换行控制代码\r\n在C代码中。 Unix版本只使用一行提要控制代码,C代码中的“\n”。 苹果历史上只使用一个回车控制代码,C代码中的“\r”。 NET需要与所有这些不兼容的选择兼容。因此,它添加了Environment.NewLine属性,它具有操作系统的默认行结束顺序。请注意如何使用Mono或Silverlight在Unix和Apple计算机上运行.NET代码

抽象TextWriter类需要知道使用什么序列,因为它编写文本文件。因此它有一个换行符属性,其默认值与Environment.NewLine相同。您几乎总是使用它,但是如果您需要创建一个文本文件供另一个操作系统上的程序读取,您可能需要更改它

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

使用.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);

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

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

Environment.NewLine和TextWriter.NewLine之间的区别在于Environment.NewLine是只读的,只能由程序员查询。这与Java不同,例如,在Java中,您可以使用system.setPropertyline.separator,x更改系统范围的换行格式默认值

在C中,您可以在使用TextWriter.newline(初始化为Environment.newline)编写时修改隐式换行符的格式。使用读取行的TextReader方法时,没有TextReader.NewLine属性。读取器的隐式换行行为是在任何0x0A、0x0D或0D0A处中断

正如rene所指出的,最初的问题可以通过书面形式解决:

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

有没有更好的方法可以做到这一点,而不需要进行三次而不是一次方法调用的开销?据我所知,WriteLine将考虑TextWriter.NewLine属性。我仍然有一个问题:Environment.NewLine.的目的是什么?为了帮助别人消除误解,请阅读
对上面的注释进行注释:WriteLineX只调用WriteX,然后调用WriteLine,然后再简单地追加TextWriter.NewLine。换句话说,TextWriter.NewLine只确定TextWriter在每个WriteLineX调用末尾追加的内容。没别的了。它写的东西和你发的一模一样。啊!你是说Environment.NewLine主要供程序员使用,TextWriter.NewLine主要供运行时使用?这是有道理的。我不知道为什么我有这两个属性。我不知道TextWriter有自己的属性,但我怀疑它默认为Environment的。当一个特定文件来自或用于不同的环境时,设置它,然后您的其余代码就不可知了。您的知识令人惊讶地无与伦比。我真诚地希望这不是一个意外: