How to make an organized text document - c#

I am currently working on a D&D program for my friends and I. It is pretty much finished except for the fact that it is going to be extremely hard for my friends to add all their stats into the program. I am currently storing all the information for the persons character in a .txt document and calling it to my program as seen below.
labelCharisma.Text = line[0];
labelStrength.Text = line[1];
but the my problem being there is no format for my friends to follow. they would have to look in the code of my program, and find out what label or textbox correlates to which line on the text document. Is there any way for me to put a some sort of indicator in the .txt document before the value to show them what they need to put where in the .txt document?
IE
(Line 0 is for Charisma): 16
(line 0 is for strength): 14
but when calling the line leave everything out but the value.
I realize this would be much easier to use a database, but at this time I want to keep it simple by using .txt document.
Or is there a way to reference an .xlsx?

An easy format for settings is the good old *.INI format. It looks like this:
[Section1]
Setting1 = value 1
Setting2 = value 2
[Another section]
Setting3 = value 3
Charisma = high
Strength = 2
While other formats like XML or JSON are more versatile and allow to build complex hierarchical structures, INI-files are easy to understand by everyone, even by non-programmers.
You can write a class for the access of these settings like this
public class IniSettings
{
private string _filename;
public IniSettings(string filename)
{
_filename = filename;
}
[DllImport("kernel32")]
private static extern long WritePrivateProfileString(string section, string key,
string val, string filePath);
[DllImport("kernel32")]
private static extern int GetPrivateProfileString(string section, string key,
string def, StringBuilder retVal, int size, string filePath);
public string this[string section, string key]
{
get
{
StringBuilder sb = new StringBuilder(1024);
GetPrivateProfileString(section, key, String.Empty, sb, 1024, _filename);
return sb.ToString();
}
set
{
WritePrivateProfileString(section, key, value, _filename);
}
}
}
Use it like this:
var settings = new IniSettings(myIniFile);
string charisma = settings["Another section", "Charisma"];

Depending on the technology you're using, you would probably want to use XML or JSON.
Both of these are structured text files, and have great support in navigating, accessing and extending its content.
If you're using Microsoft tech, I'd suggest using XML, and if it's a website type application I'd suggest looking at JSON. Personally I like XML more as I think it's cleaner and easier to maintain.
an example of how your structure will look in xml will be something like this...
<character>
<name>Wizard King</name>
<strength>3</strength>
<intelligence>9</intelligence>
etc.
hope it helps.

Related

Adding new strings to string array in a class constructor

I'm doing an assignment about working with structured / semi-structured / unstructured data and I'm doing a word count of Shakespeare plays (to see how language changes over time) by importing txt files of each play and an xml index file which stores key information about each play like the year it was written, character list etc.. Then I will remove character names, settings, punctuation and common words (and, but, or, if etc...) from the txt file ready for the word count - all in a console script run in C#. I'm writing a class for which each play's data will be stored and it currently looks like this:
class PlayImport
{
public string Title;
public DateTime Year;
public string location;
public string[] Cast;
public Counter[] WordCount;
public PlayImport(string location, int Num)
{
XmlDocument Reader = new XmlDocument();
Reader.Load(location);
this.Title = Convert.ToString(Reader.DocumentElement.ChildNodes[Num].Attributes["Title"].Value);
this.Year = Convert.ToDateTime(Reader.DocumentElement.ChildNodes[Num].Attributes["Year"].Value);
this.location = Convert.ToString(Reader.DocumentElement.ChildNodes[Num].Attributes["Location"].Value);
foreach (XmlNode xmlNode in Reader.DocumentElement.ChildNodes[Num].ChildNodes[0].ChildNodes)
this.Cast += Convert.ToString(xmlNode.Attributes["Name"].Value);
}
}
However, the final line (Cast +=) gives off an error cannot convert string to string[]. How can I get around this so that the character list gets bundled together into the Cast string array?
public string[] Cast;
The line above is a declaration of an array and this array hasn't been initialized anywhere. So you cannot add anything here until you inform the compiler that you want to initialize it with the space to store a certain number of strings.
....
this.Cast += Convert.ToString(xmlNode.Attributes["Name"].Value);
This line instead tries to execute a += operation on the previous array.
This is not possible because there is no operator defined for an array that is capable to do that operation, thus you get the error
A very simple and better approach is to declare your Cast field as a List<string>
public List<string> Cast = new List<string>();
then inside the foreach you just Add a new string to the existing string collection
foreach (XmlNode xmlNode in Reader.DocumentElement.ChildNodes[Num].ChildNodes[0].ChildNodes)
this.Cast.Add(Convert.ToString(xmlNode.Attributes["Name"].Value));
The advantage of using a List instead of an array is basically in the fact that you don't need to know in advance how many strings you want to store in the array, instead the list dinamically expand its internal storage to accomodate for new entries.

C# string pairing method (external file)

I’m writing a windows service C# service.
Within it I need a piece of functionality that can take a value (string) and look to an external file to try and match it and return the matching value, also a string.
So for example, the file might have:
Stringone – anothertwo
So if Stringone was passed the return value would be anothertwo
I need to it to be quite quick and importantly I must be able to make changes without having the recompile, so putting it into the resource file is not really an option.
Going to be less than 100 entries. So DB seems overkill.
Does anyone have some suggestions of what might be the best way to accomplish this?
Thanks.
Why dont you try XML or JSON? Create Serializable class.
Like
public class Entries
{
[JsonMember]
public string key{get;set;}
[JsonMember]
public string value{get;set;}
}
and use its collection to read.
Since it's a very small amount of entries, I think the easiest thing would be to create a dictionary<string, string>, serialize to json (since it's simple), and in the start method of the service just deserialize it.
Then, when your service gets a request, all you have to do is something like this:
public string GetTranslation(string source)
{
string returnValue = "";
_Dictionary.TryGetValue(source, out returnValue);
return returnValue; // if TryGetValue fails, you simply return an empty string
}
Or, you can return the source if there is no translation:
public string GetTranslation(string source)
{
string returnValue = "";
return _Dictionary.TryGetValue(source, out returnValue) ? source, returnValue;
}
Either way it's going to be super quick.

How to get the full string element of a dicom item with fo-dicom?

I'm trying to get a string of a radiation therapy plan in a dicom file with fo-dicom. Doesn't seem to be that hard for you, but I'm stucking because I cannot find the right command.
I was filtering the plan e.g. for the Leaf/Jaw Positions. The string value shown in VS debugging mode is "-35//35" and I find it in my DICOM Editor too. But the output only gives me the value -35. My code is like
var Leaf = file.Dataset.Get<Dicom.DicomSequence>(Dicom.DicomTag.BeamSequence).Items[0].
Get<Dicom.DicomSequence>(Dicom.DicomTag.ControlPointSequence).Items[0].
Get<Dicom.DicomSequence>(Dicom.DicomTag.BeamLimitingDevicePositionSequence).Items[0].
Get<string>(Dicom.DicomTag.LeafJawPositions);
So with this I only get the mentioned first value. By changing the last Get<string>() to Get<Dicom.DicomElement>() or something else in debugging overwatch I can see the whole string again, but can't print it.
As I looked up here C# Split A String By Another String or Easiest way to split a string on newlines in .NET? I tried it with editing my code to
string Leaf = file.Dataset.Get<Dicom.DicomSequence>(Dicom.DicomTag.BeamSequence).Items[0].
Get<Dicom.DicomSequence>(Dicom.DicomTag.ControlPointSequence).Items[0].
Get<Dicom.DicomSequence>(Dicom.DicomTag.BeamLimitingDevicePositionSequence).Items[0].
Get<Dicom.DicomElement>(Dicom.DicomTag.LeafJawPositions);
But string isn't able to accept Dicom.DicomElement as a string and with Get<string>() in the last line I only get the cut string again.
Hoping you can help to find where I did something wrong and how to get the full string of this item.
From https://github.com/fo-dicom/fo-dicom/issues/491 they are fixing the issue with a new API, but assuming you are using an older release,
string Leaf = String.Join(#"\",
...
Get<string[]>(Dicom.DicomTag.LeafJawPositions));
should return what you expect.
PS I use a string extension method for Join:
public static string Join(this IEnumerable<string> strings, string sep) => String.Join(sep, strings.ToArray());
public static string Join(this IEnumerable<string> strings, char sep) => String.Join(sep.ToString(), strings.ToArray());

GetPrivateProfileString without Trim?

Being that this application has evolved over the years, there are still some INI files. I have a class that reads entries using GetPrivateProfileString.
At the top of the class we see this:
[DllImport("kernel32")]
private static extern int GetPrivateProfileString(string section,
string key, string def, StringBuilder retVal,
int size, string filePath);
And it looks like there is a public method that looks something like this:
public string IniReadValue(string Section, string Key)
{
// If string greater than 254 characters (255th spot is null-terminator),
// string will be truncated.
const int capacity = 255;
StringBuilder temp = new StringBuilder(capacity);
int i = GetPrivateProfileString(Section, Key, "", temp,
capacity, this.m_Path);
return temp.ToString();
}
I recently noticed that GetPrivateProfileString trims it's data. Therefore, if my INI file has an entry like this:
SomeData= Notice the three trailing spaces at front and back of this sentence.
It will retrieve it like (notice that it's trimmed to the left and right - ignore quotes):
"Notice the three trailing spaces at front and back of this sentence."
I don't want it to Trim. Is that out of my control? INI files aren't allowed to have spaces after the equal sign (e.g. SomeData=)?
As pointed out in the comments, that is how the API works. If you can live with that, you can at least save some DllImport work by using for example this library/wrapper (includes source, just one file):
IniReader
You can use quotation marks to express your content, when read the content into a string,
you can easily to parse the content you want.
like this:
key = " content "
and you can add some code in Function IniReadValue.
Or You can put/get the message use base64 string, like this:
some-key = your-content-in-base64-string
and many char issues would not be your problem.
But this way is not good for read.

C# - Converting string data to actual string representation

I have a device that sends out string data representing its settings, but the data is encoded in the string as its unicode(?) representation. For example, the device sends the string "00530079007300740065006D" which represents the string "System". Are there function built into C# that will convert the string data sent from the device to the actual string? If not, can someone advise me on how best to perform this conversion?
Totally jumping on #Will Dean's solution bandwagon here (so dont mark me as the answer).
If you're using Will's solution alot, I suggest wrapping it into a string extension:
public static class StringExtensions
{
public static string HexToString(this string input)
{
return new String(Enumerable.Range(0, input.Length/4)
.Select(idx => (char) int.Parse(input.Substring(idx*4,4),
NumberStyles.HexNumber)).ToArray());
}
}
This isn't a built-in function, but it is only one line of code:
string input = "00530079007300740065006D";
String output = new String(Enumerable.Range(0, input.Length/4)
.Select(idx => (char)int.Parse(input.Substring(idx * 4,4),
NumberStyles.HexNumber)).ToArray());
Here's another one, which is perhaps a little more high-minded in not doing the hacky char/int cast:
string out2 =
Encoding.BigEndianUnicode.GetString(Enumerable.Range(0, input.Length/2)
.Select(idx => byte.Parse(input.Substring(idx * 2, 2),
NumberStyles.HexNumber)).ToArray());
Yes, .NET has a built in way to move from a given encoding type to another type, say UTF8 -> ASCII or somesuch. The namespace you'll need is System.Text.Encoding.

Categories