2013-10-25 3 views
0

Я хотел бы проанализировать текстовый файл с несколькими десятками записей. Прямо сейчас, у меня есть упрощенный вниз решение, которое считывает построчно и сравнивает с жестко закодированными строками:C# Текстовый текстовый файл - поле класса доступа по индексу

while ((line = reader.ReadLine()) != null) //returns null if end of stream 
{ 
    cmpStr = "MODE"; 
    try 
    { 
     if (line.Equals(cmpStr))       
      GlobalData.mode = Convert.ToInt32(line.Remove(0, cmpStr.Length)); 
    } 
    catch { } 

    cmpStr = "TIME_YEAR"; 
    try 
    { 
     if (line.Equals(cmpStr))       
      GlobalData.time_year = Convert.ToInt32(line.Remove(0, cmpStr.Length)); 
    } 
    catch { } 


    // ... repeat to parse the remaining lines 
} 

GlobalData является статическим классом и выглядит следующим образом:

public static class GlobalData 
{ 

    public static int mode;     
    public static int time_year; 
    public static int time_month; 
    public static int time_day; 
    public static int time_hour; 
    public static int time_minute; 
    // other entries omitted 

    public static string[] GlobalKeywords = new string[37] 
    { 
     "MODE", 
     "TIME_YEAR", 
     "TIME_MONTH", 
     "TIME_DAY", 
     "TIME_HOUR", 
     "TIME_MINUTE", 
     // other entries omitted  
    }; 
} 

Если бы это было можно получить доступ к своим статическим полям по индексу, я бы:

int i = 0; 
while ((line = reader.ReadLine()) != null) 
{ 
    cmpStr = GlobalData.GlobalKeywords[i]; // when i == 0: cmpStr = "MODE" 

    if (line.Equals(cmpStr)) 
     GlobalData[i] = Convert.ToInt32(line.Remove(0, cmpStr.Length)); 
     // GlobalData[0] would be GlobalData.mode, and so on (but doesn't work) 

    i++; 
} 
catch { } 

Так что, даже если я могу настроить цикл для сравнения массива строк ключевых слов, Как назначить определенное поле моего статического класса?

уш Крис

+0

Я не уверены, как GlobalData [i] будет GlobalData.mode. – srsyogesh

+0

Можете ли вы показать пример того, как отформатирован ваш входной файл? – Steve

+0

Вы правы, этого не было. Это файл .txt, где каждая запись находится в одной строке, а строки разделены CR + LF (Windows Linefeed). Например, файл может выглядеть так: MODE 5 TIME_YEAR 2013 TIME_MONTH 10 и т. Д. – user2286339

ответ

1

Я не уверен, что ваши деловые ограничения, так что трудно предложить дурак доказательство решение, хотя в нескольких точках:

cmpStr = "MODE"; 
try 
{ 
    if (line.Equals(cmpStr))       
     GlobalData.mode = Convert.ToInt32(line.Remove(0, cmpStr.Length)); 
} 

Это не будет работать как вы (вероятно, ожидаете) - если line.Equals("MODE"), то line.Remove(0, "MODE".Length) - пустая строка. То, что вы, вероятно, хотите, - line.StartsWith(cmpStr) или line.Contains(cmpStr).

GlobalData статический класс

Это не кажется хороший подход для того, что вы делаете. Возможно, вам захочется прочитать статические классы и когда их использовать (MSDN - хорошая отправная точка, хотя, очевидно, она не может охватить все: http://msdn.microsoft.com/en-us/library/79b3xss3%28v=vs.80%29.aspx).

Кроме того, вы, вероятно, можете просто заменить весь ИНТ поле со словарем (хотя пожалуйста переосмыслением статического подхода, как описаны выше):

public static Dictionary<String, int> Items = new Dictionary<String, int>(); 

Тогда ваш код синтаксического анализа может выглядеть следующим образом:

while ((line = reader.ReadLine()) != null) //returns null if end of stream 
{ 
    var matchingString 
     = GlobalData.GlobalKeywords.FirstOrDefault(s => line.StartsWith(s)); 
    if (matchingString != null) 
     GlobalData[matchingString] 
      = Convert.ToInt32(line.Remove(0, matchingString.Length)); 
} 

После этого вы сможете получить эти данные, используя, например, GlobalData.Items["MODE"].

Один последних бит: вы можете рассмотреть вопрос о введении постоянных значений в вашем глобальном классе данных, например .:

public const String MODE = "MODE"; 

Затем вы можете использовать GlobalData.Items[GlobalData.MODE] и избежать опечаток: написание GlobalData.Items[GlobalData.MODe] вызовет ошибку компиляции.

1

Заменить это:

public static int mode;     
public static int time_year; 
public static int time_month; 
public static int time_day; 
public static int time_hour; 
public static int time_minute; 

С этим:

public static Dictionary<string, int> my_values = new Dictionary<string, int>(); 

Затем замените:

GlobalData[i] = Convert.ToInt32(line.Remove(0, cmpStr.Length)); 

с:

GlobalData.my_values[cmpStr] = Convert.ToInt32(line.Remove(0, cmpStr.Length)); 

Это должно делать то, что вы хотите, хотя я не понимаю, как вы ожидаете, что работаете Convert.ToInt32. То, как вы вызываете Remove, создаст пустую строку (которая может конвертировать в 0, я не помню), и даже если это не так, строка не содержит числа, потому что вы успешно сравнили ее с строкой типа " РЕЖИМ".

1

Простой (и не совсем чистый) подход состоит в том, чтобы добавить indexer в свой глобальный класс данных и решить, какое поле установить на основе индекса. Но вам нужно расширять индексатор каждый раз, когда вы добавляете поле (в основном вы перемещаете if/switch из цикла while в индекс).
Вы также можете использовать отражение, если вы можете сопоставить ключевое слово с именем поля. Это не очень удобно, но не нужно расширять, пока вы можете сопоставить ключевое слово с новым именем поля.
Другой подход - создать словарь>. В этом словаре вы регистрируете ключевые слова, например. (Псевдо-код): Класс переменной Уровень:

private keywordsDict = new Dictionary<string, Action<int>>(); 

В конструкторе:

keywordsDict.Add("MODE", delegate(value) GlobalData.mode = value); 

В то время как петли:

var action = keywordsDict[line]; 
action(value); 

В последнем подходе, вам нужно всего лишь расширьте словарь, но не алгоритм как таковой, если у вас есть новое ключевое слово/поле.

1

Элегантный способ решить вашу проблему - подготовить другое действие для каждой из приемлемых строк. Вы используете Dictionary(Of String, <Action>), где Action является общим типом делегата, который получает строку ввода и знает, как ее обрабатывать соответственно ключевому слову, присутствующему в начале строки.

// The common signature for every methods stored in the value part of the dictionary 
public delegate void ParseLine(string line); 

// Global dictionary where you store the strings as keyword 
// and the ParseLine as the delegate to execute 
Dictionary<String, ParseLine> m_Actions = new Dictionary<String, ParseLine>() ; 

void Main() 
{ 
    // Initialize the dictionary with the delegate corresponding to the strings keys 
    m_Actions.Add("MODE", new ParseLine(Task1)); 
    m_Actions.Add("TIME_YEAR", new ParseLine(Task2)); 
    m_Actions.Add("TIME_MONTH", new ParseLine(Task3)); 
    m_Actions.Add("TIME_DAY", new ParseLine(Task4)); 
    ..... 

    while ((line = reader.ReadLine()) != null) 
    { 
     // Search the space that divide the keyword from the value on the same line 
     string command = line.Substring(0, line.IndexOf(' ')).Trim(); 
     // a bit of error checking here is required 
     if(m_Actions.ContainsKey(command)) 
      m_Actions[command](line); 

    } 
} 

void Task1(string line) 
{ 
    // this will handle the MODE line 
    GlobalData.Mode = Convert.ToInt32(line.Substring(line.IndexOf(' ')+1).Trim()); 

} 
void Task2(string line) 
{ 
    GlobalData.time_year = Convert.ToInt32(line.Substring(line.IndexOf(' ')+1).Trim()); 
} 
void Task3(string line) 
{ 
    ..... 
} 
void Task4(string line) 
{ 
    ..... 
} 
0

Может быть, я могу рассказать вам, как его достичь (GlobalData [i]) в C#, подумал, что это не тот ответ, который вы ищете.

class GlobalData 
    { 
     private string[] array = new string[10]; 
     public GlobalData() 
     { 
      //now initialize array 
      array[0] = "SomeThingA"; 
      array[1] = "SomeThingB";//continue initialization. 
     } 
     public string this[int index] 
     { 
      get {return array[index];} 
     } 
    } 

Теперь клиенты могут использовать GlobalData как,

GlobalData gd = new GlobalData(); 
    gd[1] = "SomeOtherThing" ; //set the value. 
    string value = gd[1];//get the value 

Но это не может быть сделано, делая класс статическим, как вы видите, она работает с «это»

Смежные вопросы