在将由C#读取的.txt文件中包含控制字符
本文关键字:文件 包含 控制字符 txt 读取 | 更新日期: 2023-09-27 17:59:19
我正在处理一个项目,该项目使用一个普通的ASCI.txt文件作为键/值配置文件。ConfigFile.txt的当前格式类似于
FirstName=Elmer | LastName=Fudd | UserId=EFudd |密码=fubar |日期=2016年7月29日
这很容易读入程序,并使用KeyValuePairs创建字典,代码类似于:
using (FileStream fs = new FileStream("ConfigFile.txt", FileMode.Open))
{
using (StreamReader sr = new StreamReader(fs))
{
string fileText = sr.ReadToEnd();
// Tokenize the entire file string into separate key=value strings.
string[] tokens = fileText.Split('|');
// Iterate through all of the key=value strings, tokenize each one into a key=Value
// pair and add the key and value as separate strings into the dictionary.
foreach (string token in tokens)
{
string[] keyValuePair = token.Split('=');
configDict.Add(keyValuePair[0], keyValuePair[1]);
}
}
}
它首先使用"|"作为分隔符将每个键/值拆分为一个单独的字符串。
FirstName=Elmer
LastName=Fudd
UserId=EFudd
密码=foobar
日期=2016年7月29日
然后,对于每个键/值字符串,它在"="分隔符上分离键和值,创建KeyValuePair,并将其插入字典中,以便稍后在程序中查找。
到目前为止还不错。指示用户不要使用任何分隔符创建密码。然而,在将密码包含在文件中之前,我现在必须对其进行加密,并且加密例程可以生成从0x20到0x7F的任何可打印字符。因此,一个加密的密码最终可能包含其中一个或两个分隔符。我最终可能会发现"foobar"(或其他任何东西)被加密引擎加密为P#|=g%。这会打乱拆分函数正常工作的能力。
因此,我想更改在Notepad.txt文件中键入的分隔符以控制字符,这样我就可以使用0x1E(记录分隔符)而不是"|"分隔符,并将"="符号替换为0x1F(单位分隔符)。
我可以直接用C#进行转义和编码,没有任何问题,但我如何修改原始的.txt磁盘文件,使其能够正确地以单个(不可打印)字符的形式读取分隔符?
因此,与其使用这样的纯文本,不如使用适当的序列化格式,例如JSON。
有一些工具可以为你做艰苦的工作
内置的System.Web.Script.Serialization
命名空间有一些工具可以使用,但我更喜欢使用Json.Net。如果你有Visual Studio,你可以用nuGet安装它(如果你需要更多帮助,请在评论中告诉我)。
但一旦你把它添加到你的项目中,你就可以做一些类似于的事情
using System.Collections.Generic;
using System.IO;
using Newtonsoft.Json;
namespace ConsoleApplication1
{
public class Program
{
static void Main(string[] args)
{
var dict = new Dictionary<string, string>();
dict.Add("FirstName", "Elmer");
dict.Add("LastName", "Fudd");
dict.Add("Password", @"'a'ansld'sb'b8d95nj");
var json = JsonConvert.SerializeObject(dict);
File.WriteAllText("ConfigFile.txt, json);
var txt = File.ReadAllText("ConfigFile.txt");
var newDict = JsonConvert.DeserializeObject<Dictionary<string, string>>(txt);
}
}
}
和ConfigFile.txt看起来像这个
{"FirstName":"Elmer","LastName":"Fudd","Password":"''a''ansld''sb''b8d95nj"}
如果你想让它更易于阅读,可以使用
var json = JsonConvert.SerializeObject(dict, Formatting.Indented);
你会得到
{
"FirstName": "Elmer",
"LastName": "Fudd",
"Password": "''a''ansld''sb''b8d95nj"
}
您可以将整数转换为字符,所以只需执行以下操作。。。
string[] tokens = fileText.Split((char)0x1e);
// ...
string[] keyValuePair = token.Split((char)0x1f);
但将密码编码为base64会更容易、更干净。。。
string base64 = Convert.ToBase64String(passwordHash);
byte[] passwordHash = Convert.FromBase64String(base64);
注意:散列/加密数据可能会包含这些字符,所以我不会只是将散列转储到文本文件中。
以下类使用正则表达式提取字符串段,并支持不可打印字符的密码:0x00。。0xFF该类包括配置段的属性
您可以在.NEt Fiddle 上运行演示示例
using System;
using System.Text.RegularExpressions;
class ConfigParser
{
public string Text { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string UserId { get; set; }
public string Password { get; set; }
public string Date { get; set; }
public ConfigParser(string text)
{
Text =text;
Parse(text);
}
private static string pattern = @"
^FirstName=(?<firstname>'w+) '|
LastName=(?<lastname>'w+) '|
UserId=(?<userid>'w+) '|
Password=(?<pasword>.+)
Date=(?<date>.+)
$
";
private Regex regex = new Regex(pattern,
RegexOptions.Singleline
| RegexOptions.ExplicitCapture
| RegexOptions.CultureInvariant
| RegexOptions.IgnorePatternWhitespace
| RegexOptions.Compiled
);
private void Parse(string text)
{
Console.WriteLine("text: {0}",text);
Match m = regex.Match(text);
FirstName = m.Groups["firstname"].ToString();
LastName = m.Groups["lastname"].ToString();
UserId = m.Groups["userid"].ToString();
Password = m.Groups["pasword"].ToString();
Date = m.Groups["date"].ToString();
}
}
如何使用:
var text ="your text here";
var c = new ConfigParser(text );
you can access the properties of the class: FirstName, LastName,....
Console.WriteLine("firstname: {0}", c.FirstName);
Console.WriteLine("lastname: {0}", c.LastName);
Console.WriteLine("UserId: {0}", c.UserId);
Console.WriteLine("Password: {0}", c.Password);
Console.WriteLine("date {0}", c.Date);
样本输出:密码包括不可打印的字符|分隔符和符号
text: FirstName=Elmer|LastName=Fudd|UserId=EFudd|Password=fg%|uy|◄¶|hj↑khg|Date=7/29/2016
firstname: Elmer
lastname: Fudd
UserId: EFudd
Password: fg%|uy|◄¶|hj↑khg
date: 7/29/2016
最简单的答案:
使用ALT数字键盘数值技巧将特殊字符插入字符串。记录组ALT-31(▼)定义键/值对和项目组ALT-30的末尾(▲)以从值中分隔键。将字符串另存为UTF-8。
分隔符的代码是
private static char tokenDelimiter = ('▲');
private static char keyValuePairDelimiter = ('▼');
使用相同的ALT数字键盘技巧输入上下三角形。包括禁止编辑或删除黑色三角形的说明,并解释其含义。
它让我回到了以前的DOS时代。实现起来很简单,只需5分钟,而且不需要对现有的代码库进行实质性更改,只需更改两个分隔符即可。