如何将文件读入保存CR / LF的字符串?

时间:2012-11-22 21:53:11

标签: c# string file newline carriage-return

如果我问“如何将文件读入字符串”这个问题答案是显而易见的。但是 - 这里是保留CR / LF的

问题是,File.ReadAllText剥离了这些字符。 StreamReader.ReadToEnd我刚刚将LF转换为CR,导致我在很明显的代码中遇到错误而进行了长时间的调查; - )

因此,简而言之,如果我的文件包含foo\n\r\nbar,我想获得foo\n\r\nbar(即完全相同的内容),而不是foo barfoobarfoo\n\n\nbar。在.Net空间中是否有一些可以使用的方式?

结果应该始终是单个字符串,包含整个文件。

6 个答案:

答案 0 :(得分:8)

你确定那些方法是剥夺你的角色的罪魁祸首吗?

我试着写一个快速测试; StreamReader.ReadToEnd会保留所有换行符。

string str = "foo\n\r\nbar";
using (Stream ms = new MemoryStream(Encoding.ASCII.GetBytes(str)))
using (StreamReader sr = new StreamReader(ms, Encoding.UTF8))
{
    string str2 = sr.ReadToEnd();
    Console.WriteLine(string.Join(",", str2.Select(c => ((int)c))));
}

// Output: 102,111,111,10,13,10,98,97,114
//           f   o   o \n \r \n  b  a   r

在写入和读取临时文件时,可以获得相同的结果:

string str = "foo\n\r\nbar";
string temp = Path.GetTempFileName();
File.WriteAllText(temp, str);
string str2 = File.ReadAllText(temp);
Console.WriteLine(string.Join(",", str2.Select(c => ((int)c))));

您的换行似乎在其他地方丢失了。

答案 1 :(得分:4)

这段代码将保留LR和CR

string r = File.ReadAllText(@".\TestData\TR120119.TRX", Encoding.ASCII);

答案 2 :(得分:2)

  

结果应该始终是单个字符串,包含整个文件。

需要两次跳跃。首先是File.ReadAllBytes()来获取文件中的所有字节。哪个不尝试翻译任何内容,您将获得文件中的原始数据,以便按原样保留怪人行结尾。

但那是字节,你问了一个字符串。所以第二跳是应用Encoding.GetString()将字节转换为字符串。您要做的一件事就是选择正确的Encoding类,该类与编写该文件的程序使用的编码相匹配。如果文件包含\n\r\n序列,并且您没有记录有关该文件的任何其他信息,那么该文件非常混乱,您最好的选择是使用Encoding.Default。必要时调整。

答案 3 :(得分:0)

您可以使用File.ReadAllLines读取文件的内容,这将返回一行数组。然后使用String.Join使用分隔符将这些行合并在一起。

string[] lines = File.ReadAllLines(@"C:\Users\User\file.txt");
string allLines = String.Join("\r\n", lines);

请注意,这将失去实际行终止符的精度。例如,如果行仅以\n\r结尾,则生成的字符串allLines将替换为\r\n行终止符。

当然还有其他方法可以在不失去真正的EOL终结符的情况下实现这一点,但是ReadAllLines很方便,因为它可以自己检测多种类型的文本编码,并且它也只占用很少的代码行

答案 4 :(得分:0)

ReadAllText不会返回回车。

  

此方法打开一个文件,读取文件的每一行,然后将每一行添加为字符串的元素。然后它关闭文件。一行被定义为一系列字符,后跟一个回车符(' \ r'),一个换行符(' \ n'),或一个回车后面紧跟一行饲料。 结果字符串不包含终止回车符和/或换行符

来自MSDN - https://msdn.microsoft.com/en-us/library/ms143368(v=vs.110).aspx

答案 5 :(得分:0)

这与接受的答案类似,但希望更多地说明问题。 sr.ReadToEnd()将读取所需的字节:

string myFilePath = @"C:\temp\somefile.txt";
string myEvents = String.Empty;

FileStream fs = new FileStream(myFilePath, FileMode.Open);
StreamReader sr = new StreamReader(fs);
myEvents = sr.ReadToEnd();
sr.Close();
fs.Close();

您甚至可以在级联using语句中执行这些操作。但我想描述一下你写入该文件的方式将如何确定如何从myEvents字符串中读取内容,并且可能确实是问题所在。我写信给我的文件:

using System.Reflection;
using System.IO;

private static void RecordEvents(string someEvent)
{
    string folderLoc = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
    if (!folderLoc.EndsWith(@"\")) folderLoc += @"\";
    folderLoc = folderLoc.Replace(@"\\", @"\"); // replace double-slashes with single slashes
    string myFilePath = folderLoc + "myEventFile.txt";

    if (!File.Exists(myFilePath))
        File.Create(myFilePath).Close(); // must .Close() since will conflict with opening FileStream, below

    FileStream fs = new FileStream(myFilePath, FileMode.Append);
    StreamWriter sr = new StreamWriter(fs);
    sr.Write(someEvent + Environment.NewLine);
    sr.Close();
    fs.Close();
}

然后我可以使用上面的代码来获取内容的字符串。因为我正在进一步寻找单个字符串,所以我把这段代码放在那个代码之后,在那里:

if (myEvents != String.Empty) // we have something
{
    // (char)2660 is ♠  -- I could have chosen any delimiter I did not
    // expect to find in my text
    myEvents = myEvents.Replace(Environment.NewLine, ((char)2660).ToString());
    string[] eventArray = myEvents.Split((char)2660);
    foreach (string s in eventArray)
    {
        if (!String.IsNullOrEmpty(s))
            // do whatever with the individual strings from your file
    }
}

这很好用。所以我知道myEvents必须保留Environment.NewLine个字符,因为我能够用(char)2660替换它,并使用该字符对该字符串执行.Split()来划分它进入各个细分市场。