I have a long list of languages and their respective codes (http://pastebin.com/rn4JbTtP), which was generated by MP4Box.
I want to load this list into some sort of key-value store in C# (like a dictionary), so that the user will be able to select a language from a combo box and the program will return the respective language code.
Is there any way this can be done without reading the text file each time the program is run? If so, how?
UPDATE (as commented here): Sorry, I didn't explain myself clearly. I've got no problem with reading text files, it's just that the current format requires a lot of parsing before it can be fed into a Dictionary. What will be the best way to store these pairs so that it will require the least amount of parsing at runtime?
You will have to read the file anyway on the startup of your application.
One solution could be to create an xml file containing your languages like this:
<?xml version="1.0" encoding="utf-8" ?>
<Languages>
<Language Name="English" Code="en"/>
<Language Name="German" Code="de"/>
</Languages>
and you can also have a small class to hold the name and the code of the language like this:
class Language
{
public string Name { get; set; }
public string Code { get; set; }
}
and a reading method to read all languages:
private static List<Language> ReadLanguageFile()
{
List<Language> languages = new List<Language>();
string path = #"LanguagesFile.xml";
XDocument xdoc = XDocument.Load(path);
var lans = xdoc.Root.Elements("Language");
Language lan;
foreach (var item in lans)
{
lan = new Language();
lan.Name = item.Attribute("Name").Value;
lan.Code = item.Attribute("Code").Value;
languages.Add(lan);
}
return languages;
}
then you may bind your combo box data source to the language list like this:
cmb.DataSource = ReadLanguageFile();
cmb.DisplayMember="Name";
cmb.ValueMember="Code";
Now, if you don't want to create a file for languages you may create a class which keeps all your languages like this:
public sealed class Languages
{
public static List<Language> GetLanguages()
{
return new List<Language>
{
new Language{Code="en",Name="English"},
new Language{Code="de",Name="German"},
};
}
}
Is there any way this can be done without reading the text file each time the program is run?
Not really. The data needs to be loaded into memory somehow. As #lc commented, outside of hardcoding the dictionary into the application code, you will need to store it and read it.
You can store the data for reading in several ways, but it will need to be read into memory:
Save to a local text file
Serialize to a local file
Use an embedded database to store the data
Update:
Seeing as you want to load local data with minimum parsing, I suggest that once you have parsed the data into a dictionary, you serialize the dictionary to disk. When you deserialize from disk, you will have a populated instance of a dictionary.
Related
I have been reading posts trying to figure how to get this done. The title says it all. I am trying to take simple data from a text file and load in memory. Then let the user manipulate (add/delete) data in memory and have it added to an List<Automobile>. Then have it write what is in memory back to the same file by overwriting what is there. I have tried to use different parts of MemoryStream() and trying to use StreamReader(). I would get an error saying "Argument 1: cannot convert from 'string' to 'Exercise6_DealerVehicleInventory.Automobile'". When I would use MemoryStream, it would give me an error saying "Cannot implicitly convert type 'System.IO.StreamReader' to 'string'"
I am not that familiar with the .net framework and what all can be done with. What is the best way to go about doing what the Title of my post says? I have been reading for the past few days and not been able to figure this out. I am still very new to all that C# has to offer when writing applications.
PS: Where it says "Exercise6", this is not for school by any means. This is something that I was given and told to use online for help/answers if I had issues.
If there is another post that explains all of this, please point me to that post because I have not found a post/answer to what I am trying to get done.
C# makes this very easy for you.
string content = System.IO.File.ReadAllText("filename.txt");
// change content here
System.IO.File.WriteAllText("filename.txt", content);
To simplify things, you should add using System.IO; to the top of your file, and then you don't have to include System.IO in the body of the code.
I assume that:
Each line in the input file represents a single automobile.
You want to convert this list of strings to list of automobiles.
For simplicity, let's define the class Automobile as follows:
public class Automobile
{
public string Name;
//you can add more fields here.
}
Let's say that your input file "automobiles.txt" has the following lines:
auto1
auto2
auto3
Your program should be:
// read file content
string sFilePath = #"C:\Users\user\Desktop\automobiles.txt";
string[] aLines = File.ReadAllLines(sFilePath);
// initialize an empty list of automobiles
List<Automobile> lAutomobiles = new List<Automobile>();
// initialize a list of automobiles from file content
aLines.ToList().ForEach(line => lAutomobiles.Add(new Automobile { Name = line }));
// here, do whatever you want with the automobiles list
lAutomobiles.ForEach(auto => auto.Name += "_processed");
// write the processed data to the file
File.WriteAllLines(sFilePath, lAutomobiles.Select(auto => auto.Name));
After running this code, the lines in automobiles.txt are:
auto1_processed
auto2_processed
auto3_processed
The error says that you want to add a string value to a list of Autmobile type.so you should create a complete Autombile class that has all info about autombiles, then when add to the list you can write something like that:
List<Autombile> auto = new List<Autombile>();
auto.Add(new Autombile() { Name = "user's auto name", Model = "user's auto model" });
So I am developing an application that I want to be able to dynamically parse an xml file, grab attributes and populate a form that is created based on what elements are present in the xml file. Then the values can be edited, and written back to the xml file that was originally opened.
I've been able to parse, save values to a database , populate forms, and write back to the original xml file via hard coding, and I think I have an idea for the dynamic "database" structure (a dictionary where the key is a node's name, and the value is a dictionary if I wanna store a node's child node information, or a string if I'm in the furthest nested child node of an element).
I'm stuck on how to grab the information I need and how to store it in the "database" structure I've come up with. I've done research and have seen people use the "dynamic" object and linq. But everything I've seen seems to involve knowing the path names they've needed before run time. Any ideas on how I should be going about actually parsing the file and grabbing data, first off? I think if I can get that figured out, the rest should kind of fall into place.
Say I have this xml
<users>
<user1 age="43">John Doe</user1>
<user2 age="40">Jane Doe</user2>
</users>
An example database setup would look like Dictionary<users, Dictionary<user1, Dictionary<name,John Doe>
Where you could go Key("users").Key("user1").Key("name").Value to get John Doe or something like that.
Any other suggestions for my database setup would also be appreciated
It sounds like what you are looking for is XML serialization. Before you can do that though, you need to simplify your xml. Instead of numbering the <user> elements, you will want to use an attribute that has the value for the user id. For example you can use an id attribute.
<users>
<user id="1" age="43">John Doe</user>
<user id="2" age="40">Jane Doe</user>
</users>
Once you have done this, create a class that you can serialize to this xml.
using System.Xml.Serialization;
[XmlRoot(ElementName = "users")]
public class Users : List<User>
{
}
[XmlType(TypeName = "user")]
public class User
{
[XmlAttribute(AttributeName = "id")]
public int Id { get; set; }
[XmlAttribute(AttributeName = "age")]
public int Age { get; set; }
[XmlText]
public string Name { get; set; }
}
Then all you have to do to load from the file is deserialize.
XmlSerializer serializer = new XmlSerializer(typeof(Users));
Users users = (Users)serializer.Deserialize(File.OpenRead("XMLFile1.xml"));
You can use LINQ to query the Users collection for specific users.
var user1 = users.Where(u => u.Id == 1)
Modify the User objects or add more to the Users collection, then serialize to save changes back to the file.
XmlSerializer serializer = new XmlSerializer(typeof(Users));
serializer.Serialize(File.OpenWrite("XMLFile1.xml"), users);
You could parse xml using XmlDocument class. After parsing you have tree of nodes which you can traverse and show in UI. I don't understand why you want to save xml as distinct records of values in database, just save it as text. Anyway for saving xml you should translate its records back to xml.
I'm currently writing a function to save and read data to/from and XML document through
LINQ. Currently I can write the document just fine, but if I go to add data to an existing item, it simply adds a new item. My goal is to create an address book type system (yes I know there's 1000 out there, it's just a learning project for myself) and I've tried ini and basic text but it seems that XML is the best way to go short of using a local DB like sql. Currently I have:
XDocument doc = XDocument.Load(#"C:\TextXML.xml");
var data = new XElement("Entry",
new XElement("Name", textBox1.Text),
new XElement("Address", richTextBox2.Text),
new XElement("Comments", richTextBox1.Text));
doc.Element("Contacts").Add(data);
doc.Save(#"C:\TextXML.xml");
I searched SO and can't seem to find how to append/replace.
Now this saves everything properly, even when I add to the document, but if I want to update an entry I'm not sure how to without creating a new "Entry" nor am have I gotten the knack of removing one. (I'm somewhat new to C# still and self-taught so pardon anything obvious I've overlooked.)
My second issues revolves around loading the information into textboxes.
I'm able to load a list of Entry names into a listbox, but when I go to open the information from that entry I'm not sure how to properly get the nested info.
With the example above I'd need something similar to the following:
XDocument doc = XDocument.Load(#"C:\TextXML.xml");
boxName.Text = The name from the SelectedItem of the list box.
boxAddress.Text = The address child of the element named above etc.
Each method I've tried I wind up with a null reference exception, which tells me I'm not pointing to the right thing, but I'm not sure how to get to those things properly.
I've also tried creating a string and var of the SelectedItem from the list box to help with the naming, and using ToString methods, but still can't figure it out.
For replacing values, there are several functions you can use in XElement:
Value (property with a public setter)
SetValue()
SetElementValue()
SetAttributeValue()
ReplaceWith()
ReplaceNodes()
For example, if you wanted to replace the value in Name:
data.Element("Name").SetValue("NewValue");
or
data.Element("Name").Value = "NewValue";
For loading, once you have the XElement node you desire, then it's as simple as doing
xelement.Value
Or if it's an attribute:
xelement.Attribute("AttributeName").Value
Using your code as an example:
boxName.Text = doc.Element("Entry").Element("Name").Value;
Edit to address comment:
If I'm reading your comment right, you're wanting to extract the Name/Address/etc. data from all the nodes within the Contacts main node?
If so, then you would probably want something like this:
boxName.Text = string.Join(",", doc.Elements("Entry").Select(x => x.Element("Name").Value));
This will give you a single string that has all the names in all Entries separated by a comma. Just change "Name" to "Address" to do the same for addresses.
I'd suggest doing a search for Linq to XML for finding more information about how to use this parsing.
My current project is basically the conversion of an excel spreadsheet to a windows application. I came across a section of the worksheet using a table and vlookups. Assume the table looks like this (exactly like this only each quarter with an additional row added to the bottom):
I want to imitate the vlookups in C# and I can think of several different ways, however I am looking for what the "best" way is. By "best", I mean easiest to code and most maintainable, I don't mean speed, if it works in under 10 seconds its good enough. this is happening in a method that has the region name and Yr/Qrt passed in as strings. Using those, what data structures should I use to store the table data in and how can I do it in the least amount of code?
EDIT
I have now recieved the actual excel file that I will be extracting this data from. Any advice on how to get only the "yearQtr" fields and the HRTC fields with C# would be greatly appreciated
Edit
just discovered that them machine running this application will not have excel. So the file shown above will have to be changed into another format before it is read in to the application(this will be handled by manually saving the file from excel as csv or xml or whatever format. So I guess my question is how to get the above described data out of a csv or xml
You may do it this way:
public class MyClass
{
public List<string> columns;
}
Then in the form, you can do the look up like this:
List<MyClass> myValues;
public List<MyClass> LookUp(string value, int columnIndex)
{
return this.myValues.Where(
input => input.columns[columnIndex] == value
).ToList();
}
I am currently using this architecture solution to meet my data needs. I am creating a new table every time I need it (like I said in the question, speed doesn't matter). The table is only for a specific region per table. As you can tell, I haven't figured out the Excel data extraction part yet.
class Table
{
Dictionary<String, double> _regionTimeValues;
String _region;
public Table(String region)
{
_regionTimeValues = new Dictionary<string, double>();
_region = region;
suckInValues();
}
private void suckInValues()
{
//Go find the File, get the appropriate Values
//for each value found
}
internal double locateRelevantValue(string yearQuarter)
{
double locatedValue = 0.0;
_regionTimeValues.TryGetValue(yearQuarter,out locatedValue);
return locatedValue;
}
}
I want to read a xml file data and extract information from it to show in a form in a C#.Net vs2008 env.
I can't read this data into a list in Memory, but I want to have a .exe file from project that can run in another computer System. So I think, I can't use database for saving and retrieving data!
Please help me to solve my problem!
Use System.Xml.XmlReader to read the XML file. This is a forward only reader which only loads a bit of XML at a time.
Combine this with an iterator method which produces an IEnumerable, such as this example, where MyXmlData is a class representing what is held in the XML file and a class that your forms can work with:
public IEnumerable<MyXmlData> QueryFile(String xmlFile)
{
using (var reader = XmlReader.Create(xmlFile))
{
// These are the variables you want to read for each 'object' in the
// xml file.
var prop1 = String.Empty;
var prop2 = 0;
var prop3 = DateTime.Today;
while (reader.Read())
{
// Here you'll have to read an xml node at a time.
// As you read, assign appropriate values to the variables
// declared above.
if (/* Have we finished reading an item? */)
{
// Once you've completed reading xml representing a single
// MyXmlData object, return it using yield return.
yield return new MyXmlData(prop1, prop2, prop3);
}
}
}
}
The value returned from that method is a sequence of MyXmlData objects where each one will be created on demand as the file is read, one at a time. This will greatly reduce memory requirements for a large XML file.
You can then query your MyXmlData objects using Linq functions. For example, you can emulate paging by using the Take and Skip methods.
// Third page - 50 objects per page.
QueryFile(#"x.xml").Skip(100).Take(50);
Recently microsoft provide a synidcation class in WCF. you can use it for doing this task
You should look into VTD-XML, it is the most efficient xml parser in terms of memory usage without losing random access and xpath..
http://vtd-xml.sf.net