Settings.settings save Pattern type - c#

I am trying to define Patterns on which an E-Mail is saved, in code i have been quite succesfull doing it like this:
string Pattern0 = SafeFileName(currMail.SenderName);
string Pattern1 = string.Join(" ", currMail.Subject.Split(' ').Take(3).ToArray());
string Pattern2 = (Convert.ToDateTime(currMail.CreationTime).ToString(" dd-MMM-yyyy HH-mm"));
and then i tried to save the Patterns on Properties.Setting, I Chose string, but that makes everything a string, as opposed to making them useful like they are above.
Does anybody know what it is that i could use, to save the Settings above in the Settings.settings file.
Thanks a lot in Advance

Related

How to add a second extension to a file name?

I want to create a data file, but before writing to the final file I want to drop it in a temporary location to avoid user confussion. As an example, I could begin with test.txt and want to have test.txt.tmp. The names could include a path, but the files may not necesarily exist (so this question is purely about string manipulation).
The closest I have been is to use Path.ChangeExtension:
string original = "test.txt";
string temp = Path.ChangeExtension(original, "tmp");
But that returns test.tmp instead. So my question is if there is a built-in method to achieve that "dual-extension" file name? I could always use brain-dead string concatenation, but I'm looking for a more safe and tested method.
Avoiding pitfalls is a great idea for things like Path.Combine, e.g. because you don't want to be bothered checking if there is no missing \ character.
But there are no pitfalls here.
If your original filename is as you expect it to be, then string concatenation will work.
If your original file name is not as you expect it to be, then the issue lies with whoever supplied you a faulty filename. "Shit goes in, shit comes out" is not really something your internal logic should worry about. An algorithm can only be as correct as the information that it receives.
String concatenation is perfectly acceptable here. There is no premade method here because there is no real pitfall to simply concatenating the strings.
Special shout out to AlessandroD'Andria's suggestion:
Path.ChangeExtension(original, Path.GetExtension(original) + ".tmp");
Technically, it employs Path logic and therefore fits with your criteria. I genuinely like the cleverness of following your expectations.
However, there is simply no merit to doing so. By its very nature an extension is defined as being "the last part of the filename".
Whether you do a direct string concatenation, or instead do this:
chop the string into two pieces (filename, extension)
append something to the last piece (extension + temp extension)
paste everything together again
The end result will always be the same. The chopping of the string is unnecessary work.
Why can't you append that string just like
if(!string.IsNullOrEmpty(Path.GetExtension(original)){
original+= ".tmp";
}
You should use temp file and rename the extension.
string path = Path.GetTempFileName();
// some logic on the file then rename the file and move it when you need it
string fileName = Path.GetFileName(path);
File.Move(path, path.Replace(fileName, "test.txt"));
If you would use temp file, you can use Path.GetTempFileName();
string tempFileName = Path.GetTempFileName();
Or in your case:
string original = "test.txt";
string temp = "test.txt" + ".tmp";

How to select something within an XML attribute?

I am currently attempting to replace a certain string in an xml document. I am doing this through Visual Studio using C#. The exact string I want to replace is Data Source = some-host to Data Source = local-host. The string is located under an attribute to my Strings. However, the attribute connectionString has many values under it.
<Strings>
<add name="Cimbrian.Data.ConnectionString" connectionString="Data Source=some-host;Integrated Security=false;pooling=true;Min Pool Size=5;Max Pool Size=400;Connection Timeout=5;"/>
I have managed to be able to select and replace the entire values for both name and connectionString however I want to be able to select JUST the Data Source = some-host to replace.
After loading the document my code currently looks like this,
XmlNode ConnectNode = Incident.SelectSingleNode("//Strings");
XmlNode add1 = ConnectNode.FirstChild;
add1.Attributes[1].Value = "THIS REPLACES ALL OF CONNECTION STRING";
But as the string value suggests, it is replacing far more than I want it to. Any help would be appreciated. Apologies if that is slightly hard to follow.
EDIT - I forgot to mention that if possible I want to do this without searching for the specific string Data Source = some-host due to the fact that the some-host part may change, and I still want to be able to edit the value without having to change my code.
This has really nothing to do with XML - the fact that the value of the attribute is itself a semi-colon-separated list is irrelevant as far as XML is concerned. You'd have the same problem if you had the connection string on its own.
You can use SqlConnectionStringBuilder to help though:
var builder = new SqlConnectionStringBuilder(currentConnectionString);
builder.DataSource = "some other host";
string newConnectionString = builder.ToString();
This means you don't need to rely on the current exact value of some-host (and spacing) which you will do if you just use string.Replace.
If you know exactly what you would be replacing you could use the replace method:
string string2 = string1.Replace("x", "y");
This would find all instances of x and replace them with y in string1
EDIT:
Your specific code would look something like this:
add1.Attributes[1].Value = add1.Attributes[1].Value.Replace("Data Source = some-host","Data Source = local-host");
EDIT 2:
Okay based on your comment I would then split the string on the semi-colon and then iterate to find the DataSource string and modify it and then concatenate everything back together

Data processing puzzle/headache

I have a CSV file I need to process which is a bit of a nightmare. Esentially it is the following
"Id","Name","Description"
"1","Test1","Test description text"
"2","Test2","<doc><style>body{font-family:"Calibri","sans-serif";}</style><p class="test_class"
name="test_name">Lots of word xdoc content here.</p></doc>"
"guid-xxxx-xxxx-xxxx-xxxx","Test3","Test description text 3"
I'm using the File Helpers library to process the CSV rather than reinvent the wheel. However, due to the description field containing unescaped Word xdoc xml which contains quotes it's getting rather confused when it comes to the start and end points of each record.
The following is an example mapping class.
[DelimitedRecord(","), IgnoreFirst(1), IgnoreEmptyLines()]
public class CSVDoc
{
#region Properties
[FieldQuoted('"', QuoteMode.AlwaysQuoted), FieldTrim(TrimMode.Both)]
public string Id;
[FieldQuoted('"', QuoteMode.AlwaysQuoted), FieldTrim(TrimMode.Both)]
public string Name;
[FieldQuoted('"', QuoteMode.AlwaysQuoted), FieldTrim(TrimMode.Both)]
public string Description;
[FieldQuoted('"', QuoteMode.AlwaysQuoted), FieldTrim(TrimMode.Both)]
}
I considered (despite my hate of regex for this kind of task) replacing all " with ' and then using ((?<=(^|',))'|'(?=($|,'))) pattern to replace all ' with " at the start and end of lines and where they are formatted ','. However, the dirty file contains some lines which end with a " and some css style attributes which are formatted ","
So now I'm left scratching my head trying to figure out how to do this and how it can be automated.
Any ideas?
You're going to have to re-invent the wheel, because that's not valid CSV or indeed a reasonable file at all - it doesn't have any sort of provably consistent escaping rules (e.g. we don't know if the plain-text columns are escaped correctly or not).
Your best bet is to ask the person producing this to fix the bug, it should be e.g.:
"2","Test2","<doc><style>body{font-family:""Calibri"",""sans-serif"";}</style><p class=""test_class""
name=""test_name"">Lots of word xdoc content here.</p></doc>"
Which your parser should handle fine, and which should not be hard for them to produce in a simple and efficient manner.
Failing that, you'll have to hand-code the parser to:
Read a line.
Check for unescaped " (any "that isn't followed by a " a , or whitespace.
If none found, parse as CSV.
If any found, parse as this horrible thing until you hit the line ending with "
It may be easier to look for < if that is consistently not used in the other lines. Or perhaps for <doc if it consistently identifies the correct rows.
If you don't mind doing some pre-processing before, you can change the first and second "," to "|" and then use FileHelper to parse the file normally (Assuming you don't have | in the last column where there are HTML tags)
The pre-processing could be something like (Simple pseudo code) :
var sb = new StringBuilder()
var regex = new Regex("\",\"");
foreach(string line in textFileLines)
{
sb.AppendLine(regex.Replace(line , "\"|\"", 2));
}
I worked on the CSV-1203 File Format standard a few months ago, so the first thing to realise is that you're not dealing with a CSV file - even though it's named "xyz.CSV".
As said by others here, it will be easier to write your own reader, they're not too difficult. I too have a hatred of everything regex, but the good news is you can code any solution without ever using it.
A couple of things: There's a really weird thing Excel does to CSV files that begin with the two capital letters ID (without quotes). It thinks your CSV is a corrupted SYLK file! Try it.
For details of this issue and a detailed CSV File Format specification, please refer to http://mastpoint.curzonnassau.com/csv-1203

what is the best way to parse out string from longer string?

i have a string that looks like this:
"/dir/location/test-load-ABCD.p"
and i need to parse out "ABCD" (where ABCD will be a different value every day)
The only things that i know that will always be consistent (to use for the logic for parsing) are:
There will always be be a ".p" after the value
There will always be a "test-load-" before the value.
The things i thought of was somehow grab everything past the last "/" and then remove the last 2 characters (to take case of the ".p" and then to do a
.Replace("test-load-", "")
but it felt kind of hacky so i wanted to see if people had any suggestions on a more elegant solution.
You can use a regex:
static readonly Regex parser = new Regex(#"/test-load-(.+)\.p");
string part = parser.Match(str).Groups[1].Value;
For added resilience, replace .+ with a character class containing only the characters that can appear in that part.
Bonus:
You probably next want
DateTime date = DateTime.ParseExact(part, "yyyy-MM-dd", CultureInfo.InvariantCulture);
Since this is a file name, use the file name parsing facility offered by the framework:
var fileName = System.IO.Path.GetFileNameWithoutExtension("/dir/location/test-load-ABCD.p");
string result = fileName.Replace("test-load-", "");
A “less hacky” solution than using Replace would be the use of regular expressions to capture the solution but I think this would be overkill in this case.
string input = "/dir/location/test-load-ABCD.p";
Regex.Match(input, #"test-load-([a-zA-Z]+)\.p$").Groups[1].Value

Declaring a looooong single line string in C#

Is there a decent way to declare a long single line string in C#, such that it isn't impossible to declare and/or view the string in an editor?
The options I'm aware of are:
1: Let it run. This is bad because because your string trails way off to the right of the screen, making a developer reading the message have to annoying scroll and read.
string s = "this is my really long string. this is my really long string. this is my really long string. this is my really long string. this is my really long string. this is my really long string. this is my really long string. this is my really long string. ";
2: #+newlines. This looks nice in code, but introduces newlines to the string. Furthermore, if you want it to look nice in code, not only do you get newlines, but you also get awkward spaces at the beginning of each line of the string.
string s = #"this is my really long string. this is my long string.
this line will be indented way too much in the UI.
This line looks silly in code. All of them suffer from newlines in the UI.";
3: "" + ... This works fine, but is super frustrating to type. If I need to add half a line's worth of text somewhere I have to update all kinds of +'s and move text all around.
string s = "this is my really long string. this is my long string. " +
"this will actually show up properly in the UI and looks " +
"pretty good in the editor, but is just a pain to type out " +
"and maintain";
4: string.format or string.concat. Basically the same as above, but without the plus signs. Has the same benefits and downsides.
Is there really no way to do this well?
There is a way. Put your very long string in resources. You can even put there long pieces of text because it's where the texts should be. Having them directly in code is a real bad practice.
If you really want this long string in the code, and you really don't want to type the end-quote-plus-begin-quote, then you can try something like this.
string longString = #"Some long string,
with multiple whitespace characters
(including newlines and carriage returns)
converted to a single space
by a regular expression replace.";
longString = Regex.Replace(longString, #"\s+", " ");
If using Visual Studio
Tools > Options > Text Editor > All Languages > Word Wrap
I'm sure any other text editor (including notepad) will be able to do this!
It depends on how the string is going to wind up being used. All the answers here are valid, but context is important. If long string "s" is going to be logged, it should be surrounded with a logging guard test, such as this Log4net example:
if (log.IsDebug) {
string s = "blah blah blah" +
// whatever concatenation you think looks the best can be used here,
// since it's guarded...
}
If the long string s is going to be displayed to a user, then Developer Art's answer is the best choice...those should be in resource file.
For other uses (generating SQL query strings, writing to files [but consider resources again for these], etc...), where you are concatenating more than just literals, consider StringBuilder as Wael Dalloul suggests, especially if your string might possibly wind up in a function that just may, at some date in the distant future, be called many many times in a time-critical application (All those invocations add up). I do this, for example, when building a SQL query where I have parameters that are variables.
Other than that, no, I don't know of anything that both looks pretty and is easy to type (though the word wrap suggestion is a nice idea, it may not translate well to diff tools, code print outs, or code review tools). Those are the breaks. (I personally use the plus-sign approach to make the line-wraps neat for our print outs and code reviews).
you can use StringBuilder like this:
StringBuilder str = new StringBuilder();
str.Append("this is my really long string. this is my long string. ");
str.Append("this is my really long string. this is my long string. ");
str.Append("this is my really long string. this is my long string. ");
str.Append("this is my really long string. this is my long string. ");
string s = str.ToString();
You can also use: Text files, resource file, Database and registry.
Does it have to be defined in the source file? Otherwise, define it in a resource or config file.
Personally I would read a string that big from a file perhaps an XML document.
You could use StringBuilder
For really long strings, I'd store it in XML (or a resource). For occasions where it makes sense to have it in the code, I use the multiline string concatenation with the + operator. The only place I can think of where I do this, though, is in my unit tests for code that reads and parses XML where I'm actually trying to avoid using an XML file for testing. Since it's a unit test I almost always want to have the string right there to refer to as well. In those cases I might segregate them all into a #region directive so I can show/hide it as needed.
I either just let it run, or use string.format and write the string in one line (the let it run method) but put each of the arguments in new line, which makes it either easier to read, or at least give the reader some idea what he can expect in the long string without reading it in detail.
Use the Project / Properties / Settings from the top menu of Visual Studio. Make the scope = "Application".
In the Value box you can enter very long strings and as a bonus line feeds are preserved. Then your code can refer to that string like this:
string sql = Properties.Settings.Default.xxxxxxxxxxxxx;

Categories