我编写了一个屏蔽文本文件的c#应用程序。我有一个用UTF-8
编码的大文本文件。我想只呈现此文件的一部分。所有其他文本将被" *"掩盖。 character(替换我要隐藏的旧字符)。所以,让我们假设:
这是方法签名的样子:
public void Mask(MemoryStream inputData, int clearSectionStart, int clearSectionEnd)
{
}
请求的输出是屏蔽文件。我应该遍布蒙面部分(例如0-100和200-1000部分)并用" *"替换这些字符。
例如,如果文本文件内容为" Hello world"我想保留“世界”这个词。未屏蔽(6-11),预期输出为:
******世界
完全像目标1,但现在我们应该保持句子格式与原始格式一样。这意味着,我们将保留未屏蔽的部分并保持这些字符不被屏蔽:
对于这个输入:"你好,机器人。" +清除第7-10节(" bot") - >预期的产出将是:
*****,机器人。
我想知道如何解决这个问题。
第一个天真的选项是从文件中读取所有文本以进行流式处理并处理此字符串以隐藏其中的部分内容。这是原因,这是最慢的解决方案,并且在长文本文件的情况下还包括大量可用RAM。
另一种可能的解决方案是实现一个自定义流阅读器,它将读取源流(文本文件)并操纵内容以隐藏部分流。
您认为最好的方法是什么?任何建议\解决方案都会有所帮助。
答案 0 :(得分:1)
你可以一次读取一个字符并检查你想要的索引和获得所需文本部分所需的长度。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var maskedString = MaskFileContent(@"C:\PSQL_v10_Install.log", 100, 200);
Console.WriteLine(maskedString);
Console.ReadKey();
}
static string MaskFileContent(string filePath, int indexOfClearData, int lengOfClearData, string mask ="***")
{
int counter = 0;
StringBuilder result = new StringBuilder();
System.IO.StreamReader file =
new System.IO.StreamReader(filePath);
while (!file.EndOfStream)
{
var curChar = (char)file.Read();
if (counter >= indexOfClearData)
{
result.Append(curChar.ToString());
}
if(result.Length >= lengOfClearData)
break;
counter++;
}
file.Close();
result.Insert(0, mask);
result.Append(mask);
return result.ToString();
}
}
}
答案 1 :(得分:1)
您可以通过使用缓冲区以块的形式读取,屏蔽和写入数据,而无需将所有数据加载到内存中。
public class TextMasker
{
private readonly int _bufferSize;
private readonly string _outputDataPath;
private readonly byte _maskByte;
private readonly byte[] _unmaskableBytes;
public TextMasker()
{
_bufferSize = 4096;
_outputDataPath = "outputData.txt";
_maskByte = Encoding.UTF8.GetBytes("*")[0];
_unmaskableBytes = Encoding.UTF8.GetBytes(" ,.");
}
public void Mask(MemoryStream inputData, int unmaskedStart, int unmaskedStop)
{
var byteIndex = 0;
var buffer = new byte[_bufferSize];
using (var fileStream = File.OpenWrite(_outputDataPath))
{
int bytesBuffered;
while ((bytesBuffered = inputData.Read(buffer, 0, buffer.Length)) != 0)
{
for (var i = 0; i < bytesBuffered; i++, byteIndex++)
{
if ((byteIndex < unmaskedStart - 1 || byteIndex > unmaskedStop - 1)
&& !_unmaskableBytes.Contains(buffer[i]))
{
buffer[i] = _maskByte;
}
}
fileStream.Write(buffer, 0, bytesBuffered);
}
}
}
}