sɐu*_*qɐp 1 .net c# streamwriter text-files backspace
在C#中,是否可以将包含退格的字符串附加到文本文件中,并将所有退格视为"删除最后一个字符"操作?
例如我的文本文件:
这个文件有
两行
某种C#代码是这样的:
string str = "...\b\b\b\b\b\b\b\b\b\b\b\b\b one line."
myFile.Append(str);
Run Code Online (Sandbox Code Playgroud)
执行此代码后,文本文件如下所示:
这个文件有一行.
这些StreamWriter和File类似乎没什么帮助.
如果不在每个附加操作上读取和写入整个文件,我就无法轻易找到实现这一点的好方法,这可能会导致大文本文件出现严重的性能问题.我们的想法是使用这个新功能将日志语句集中写入文本文件.
我的第二个问题是如何处理windows风格的新行字符("\ r \n")?即一个退格键应删除整个单行换行符("\ r \n").
有关如何实现这一点的任何想法?
源代码将受到高度赞赏.
在"最一般的情况下"做"正确"是非常非常,非常困难..NET中没有直接的支持.让我们看看最先进的技术:
有一个FileStream类...它是读/写.可悲的是,它不知道编码,它以字节为单位工作.所以没有UTF-8,也没有原生的Unicode.你看到你美丽的昵称s?un????q?p?它显然需要一些编码:-)
StreamReader并且StreamWriter可以被"连接到"一个FileStream.不幸的是它们是独立的(一个是只读的,一种是只写),以及它们可悲预缓冲器,从而使FileStream.Position不对应于在当前"读"字符StreamReader.这使得阅读与StreamReader"修复" StreamWriter相当复杂.
即使我们有一个StreamReaderWriter,也会有点困难..NET适用于UTF-16 char,因此许多Unicode字符(例如,像笑脸一样的表情符号)由两个组成char......所以单个\b可能需要擦除一个或两个char(以及在UTF中的1到4个字节之间) 8),取决于它找到了什么.
请注意,更复杂的表情符号(如 家族)由多个单个表情符号组成(4个unicode代码点,对应11个.net char,对应于UTF-8中的25个字节),但我们将忽略此问题
最简单的解决方案是将整个文件加载到string(或类似)内存中,修改它,然后将其重新写入磁盘.即使在这里,要注意行尾,可能是两个字符(\r\n),而"逻辑上"它们是单个字符(如果你在记事本中的一行开头并按下一个退格键,它将会完全擦除\r\n).但正如你已经注意到这个解决方案是"慢":-)
其他解决方案,有很多限制.正如我在评论中写的那样,你可以做相反的事情:保存Position前写,写,如果你需要纠正改变Position后面,重写,SetLength()截断多余的文件,如果存在.这将问题限制为只能修改您在当前会话中编写的文本部分的情况,通常只能修改文件的"最后"部分.
public static long WriteAppend(this FileStream fs, string str, Encoding enc)
{
long pos = fs.Length;
fs.Position = pos;
byte[] bytes = enc.GetBytes(str);
fs.Write(bytes, 0, bytes.Length);
return pos;
}
public static long RewriteTruncate(this FileStream fs, long pos, string str, Encoding enc)
{
fs.Position = pos;
byte[] bytes = enc.GetBytes(str);
fs.Write(bytes, 0, bytes.Length);
fs.SetLength(pos + bytes.Length);
return pos;
}
Run Code Online (Sandbox Code Playgroud)
使用:
int secs = 5;
using (var fs = new FileStream("Hello.txt", FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite))
{
fs.WriteAppend("Beginning of the elaboration\r\n", Encoding.UTF8);
long pos1 = fs.WriteAppend("Step 1\r\n", Encoding.UTF8);
long pos2 = fs.WriteAppend($"Working 0\r\n", Encoding.UTF8);
for (int i = 1; i < 10; i++)
{
Thread.Sleep(secs * 1000);
fs.RewriteTruncate(pos2, $"Working {i}\r\n", Encoding.UTF8);
}
Thread.Sleep(secs * 1000);
fs.RewriteTruncate(pos1, $"Finished working\r\n", Encoding.UTF8);
}
Run Code Online (Sandbox Code Playgroud)
在Notepad ++中保持打开输出文件并每隔几秒刷新一次.
| 归档时间: |
|
| 查看次数: |
169 次 |
| 最近记录: |