I need to extract data from a text file in ASP .NET.
Example Data:
; comment
data = astringvalue
; comment
; string values
person = bob
animal = rabbit
; boolean values (yes / no)
isValid = yes
isAnimal = no
I will be creating a GUI control for each line that is not a comment. What is the best way to extract each line and determine if it is a string or a Boolean value. Performance is a must as the file can be quite large.
Edit: At some point i will have need to update the values with the updated ones from the web page.
private void ShowConfig()
{
string configLine = String.Empty;
using (TextReader tr = File.OpenText(@"textfile"))
{
do
{
configLine = tr.ReadLine();
if (!String.IsNullOrEmpty(configLine) && !configLine.Contains(Convert.ToChar(";")))
{
CreateControl(configLine);
}
} while (configLine != null);
}
private void CreateControl(string configline)
{
string lineHeader = string.Empty;
string lineValue = String.Empty;
for (int i = 0; i < configline.Length; i++)
{
if (configline[i] == Convert.ToChar("="))
{
lineHeader = configline.Remove(i).TrimEnd();
lineValue = configline.Remove(0, ++i).TrimStart();
if (GetValueType(lineValue) is CheckBox)
{
this.Panel1.Controls.Add(CreateCheckBox(lineValue, lineHeader));
}
else
{
this.Panel1.Controls.Add(CreateLabel(lineHeader));
this.Panel1.Controls.Add(CreateTextBox(lineValue, lineHeader));
}
this.Panel1.Controls.Add(CreateNewLine());
break;
}
}
}
private Control GetValueType(string Value)
{
switch (Value)
{
case "yes":
case "no":
return new CheckBox();
default:
return new TextBox();
}
}
In the future i will need to check for more value types than开发者_运维知识库 string and boolean.
How about something like this? However, I think that working any kind of serious type-recognition into this schema is likely to be error prone. Why not use a better serialization in the first place? Something that captures type info in the serialized data?
var data=@" ; comment
data = value
; comment
; string values
person = Bob
animal = Rabbit
; boolean values (yes / no)
isValid = yes
isAnimal = no";
var parsed = data
.Split(new[]{"\r\n","\r","\n"}, StringSplitOptions.RemoveEmptyEntries)
.Select(line => line.Trim())
.Where(line => !line.StartsWith(";"))
.Select(line => line.Split('=').Select(item => item.Trim()))
.Where(kv => kv.Count() == 2)
.Select(kv => new{key = kv.First(), value = kv.Last()})
.Select(kv =>
new{kv.key, kv.value, isBool = Regex.IsMatch(kv.value,"yes|no")});
Taking @Rubens' comments on-board, if the data source is too large to load in at once, you could stream the data with the addition of a helper method:
static IEnumerable<string> Lines(string filename)
{
using (var sr = new StreamReader(filename))
{
while (!sr.EndOfStream)
{
yield return sr.ReadLine();
}
}
}
then:
Lines(@"c:\path\to\data")
.Select(line => line.Trim())
.Where(line => !line.StartsWith(";"))
.Select(line => line.Split('=').Select(item => item.Trim()))
.Where(kv => kv.Count() == 2)
.Select(kv => new{key = kv.First(), value = kv.Last()})
.Select(kv =>
new{kv.key, kv.value, isBool = Regex.IsMatch(kv.value,"yes|no")});
StreamReader sr = null;
while(!sr.EndOfStream)
{
string line = sr.ReadLine();
if (string.IsNullOrEmpty(line) || line.StartsWith(";")) continue;
string[] tokens = line.Split("= ".ToCharArray(),
StringSplitOptions.RemoveEmptyEntries);
if(tokens.Length == 2)
{
if("Yes".Equals(tokens[1], StringComparison.CurrentCultureIgnoreCase) ||
"No" .Equals(tokens[1], StringComparison.CurrentCultureIgnoreCase))
{
// boolean
}
else
{
// non boolean
}
}
}
精彩评论