如何将文件读入保存CR / LF的字符串?
如果我问“如何将文件读成字符串”的问题,那么答案就很明显了。 然而 – 这里保留了CR / LF的捕获量。
问题是, File.ReadAllText
这些字符。 StreamReader.ReadToEnd
刚刚将LF转换为CR导致我进行了长时间的调查,我在相当明显的代码中有bug 😉
所以,简而言之,如果我有包含foo\n\r\nbar
我想得到foo\n\r\nbar
(即完全相同的内容),而不是foo bar
, foobar
或foo\n\n\nbar
。 .Net空间中是否有一些可以使用的方式?
结果应该始终是单个字符串,包含整个文件。
你确定那些方法是剥夺你的角色的罪魁祸首吗?
我试着写一个快速测试; 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 // foo \n \r \nbar
写入和读取临时文件时,可以获得相同的结果:
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))));
您的换行似乎在其他地方丢失了。
这段代码将保留LR和CR
string r = File.ReadAllText(@".\TestData\TR120119.TRX", Encoding.ASCII);
结果应该始终是单个字符串,包含整个文件。
它需要两个跃点。 第一个是File.ReadAllBytes()来获取文件中的所有字节 。 哪个不尝试翻译任何内容,您将获得文件中的原始数据,以便按原样保留怪异的行结尾。
但那是字节,你问了一个字符串。 所以第二跳是应用Encoding.GetString()将字节转换为字符串。 您要做的一件事就是选择正确的Encoding类,该类与编写该文件的程序使用的编码相匹配。 如果文件包含\n\r\n
序列,并且您没有记录有关该文件的任何其他信息,那么该文件非常混乱,您最好的选择是使用Encoding.Default。 根据需要调整。
您可以使用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
非常方便,因为它可以自己检测多种类型的文本编码,并且它也占用很少的代码行。
ReadAllText不返回回车符。
此方法打开一个文件,读取文件的每一行,然后将每一行添加为字符串的元素。 然后它关闭文件。 一行被定义为一系列字符,后跟一个回车符(’\ r’),一个换行符(’\ n’)或一个回车符后面紧跟一个换行符。 生成的字符串不包含终止回车符和/或换行符 。
来自MSDN – https://msdn.microsoft.com/en-us/library/ms143368(v=vs.110).aspx
这与接受的答案类似,但希望更多地说明问题。 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
级联using
语句来执行这些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()
将其划分为各个段。