2016-07-29 4 views
0

Я работаю над проектом, который использует простой файл ASCII .txt в качестве файла конфигурации ключа/значения. Текущий формат для ConfigFile.txt что-то вродеВключая управляющие символы в TXT-файле, который должен быть прочитан C#

FirstName = Elmer | LastName = фадд | USERID = EFudd | Password = FuBar | Дата = 7/29/2016

Это легко считаны в программы и создать словарь с 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 = Элмер

LastName = фадд

UserId = EFudd

Password = Foobar

Дата = 7/29/2016

Затем для каждого ключа/значения string, он разделяет ключ и значение на разделителе '=', создает KeyValuePair и вставляет его в словарь для последующего поиска в программе.

Пока все хорошо. Пользователям предлагается не создавать пароли с разделителем. Однако теперь мне нужно зашифровать пароль, прежде чем включать его в файл, а процедура шифрования может выдавать любой печатный символ от 0x20 до 0x7F. Таким образом, зашифрованный пароль может заканчиваться одним или обоими разделителями. Я могу закончить «foobar» (или что-то еще), зашифрованное механизмом шифрования, в P # | = g%. Это испортило способность функции split работать правильно.

Итак, я хочу изменить разделители, введенные в файл Notepad .txt, для управления символами, чтобы вместо символа '|' delimiter, я использую 0x1E (разделитель записи) и заменяю знак '=' 0x1F (Unit Separator).

Я могу избежать и кодировать это прямо на C# без проблем, но как бы изменить исходный файл .txt-диска, чтобы он читал в разделителях как одиночные (непечатаемые) символы правильно?

+5

Почему пароли ясного текста? используйте хэш, а затем используйте base64 или hex для кодирования двоичного файла. –

+0

Что касается того, как читать файл, вы делаете это так же, как в настоящее время читаете файл. Если вы хотите сходить с ума, вы можете получить доступ к сырым файловым потокам, но это требует больше усилий, чем помощь в объяснении на SO. –

+0

Я унаследовал открытые pwds. Я написал утилиту для шифрования их на месте до того, как зашифрованный текст вводится вручную в файл конфигурации, поэтому на диске или в памяти нет открытого текста. Приложение использует одно и то же шифрование для их незашифрования непосредственно перед их использованием. – MiddleAgedMutantNinjaProgrammer

ответ

0

Самый простой ответ:

Вставьте специальные символы в строку, используя значение трюк ALT-цифровой блок. Запись группы ALT-31 (▼), чтобы разграничить конец пары «ключ/значение» и группу элементов ALT-30 (▲), чтобы отделить ключ от значения. Сохраните строку как UTF-8.

Код для разделителей

private static char tokenDelimiter = ('▲'); 
private static char keyValuePairDelimiter = ('▼'); 

используя тот же ALT-трик в цифровой блок положить в вверх и вниз треугольники. Включите инструкции, чтобы черные треугольники НИКОГДА не редактировались и не удалялись и не объясняли их значение.

Он возвращает меня в мои старые дни DOS. Простой и потребовалось 5 минут для реализации - и это не требует существенного изменения существующей базы кода - изменились только два символа разделителя.

+0

Спасибо всем, кто придумал множество методов для этого. Если бы это была новая программа, я бы поступил иначе. Но я работаю в отделе ИТ, который все еще поддерживает все, начиная с ASP.NET (pre -ASP.NET) 90-х с базой данных Access и даже с базовым мейнфреймом IBM 360/370 BAL (Basic Assembly Language). Когда я свободен выполнять свои собственные проекты, я регулярно использую методы, которые только разрабатываются в академических кругах. Я использовал REST/JSON, так как SOAP/XML вышел. Это приложение является kludge, но мне не разрешено изменять его, я не владею им. – MiddleAgedMutantNinjaProgrammer

0

Итак, вместо того, чтобы иметь простой текст, я бы использовал правильный формат сериализации, такой как 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" 
} 
+0

Это то, что вы кодируете после «пароля»: вот что заставляет меня делать это так. Я не могу контролировать, какие символы будут в зашифрованном пароле, и я не могу его отредактировать. Символы Escape нельзя использовать. Фактически, процедура шифрования будет переводить некоторые символы в обратную косую черту и должна быть способна перевести их обратно. Пароль должен быть именно тем, что вышло из машины шифрования, или оно не будет дешифровать правильно. U R выдает зашифрованный pwd с экранами - он не будет расшифровывать. У меня нет контроля над тем, какие символы появятся в зашифрованном pwd. – MiddleAgedMutantNinjaProgrammer

+0

@MiddleAgedMutantNinjaProgrammer Символы будут экранированы при сериализации, но будут нормальными при десериализации. Если вы не можете десериализовать приложение, то он полностью не подходит для хранения паролей. – Zong

+0

@MiddleAgedMutantNinjaProgrammer Вам не нужен какой-либо контроль над тем, какие символы будут в зашифрованном пароле. Просто полагайтесь на структуру сериализации, чтобы понять это для вас. –

0

Вы можете конвертировать целые числа в голец поэтому просто сделайте это ...

string[] tokens = fileText.Split((char)0x1e); 
// ... 
string[] keyValuePair = token.Split((char)0x1f); 

... но кодирующая ваши пароли в base64 будет проще и чище ...

string base64 = Convert.ToBase64String(passwordHash); 
byte[] passwordHash = Convert.FromBase64String(base64); 

... Примечание: возможно, что хэши/зашифрованные данные будут содержать эти символы, так что я Wouldn» t просто выгружать hases в текстовый файл.

0

Следующий класса извлечение строки сегментов с помощью регулярных выражений и поддержки пароля с непечатаемыми символами: 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