Output all command line parameters - c#

I am working on a console application, that receives a pretty long list of parameters. For debugging purpose I need to print the parameters passed to a an output file. Right now, I am using the following code to concat command line parameters.
static void Main(string[] args)
{
string Params = string.Empty;
foreach(string arg in args)
{
Params += arg + ",";
}
}
Is there any better way to accomplish this?

What about
Params = string.Join(",", args);
Your foreach approach is not very performant. Since a string is immutable, that means for each iteration of the loop, the string will get thrown away for garbage collection, and a new string will be generated. In the string.Join case, only one string will be generated.
Inside the loop, to get around the same performance, you will have to use a StringBuilder, but in this case it's really no reason not to use string.Join since the code will be much more readable.

You could use this piece of code
String.Join(", ", Environment.GetCommandLineArgs())

You can use String.Join(",",args)

All of the answers here combining the arguments with a single comma will work, but I found that approach lacking somewhat because there's not a clear indicator of "quoted arguments" and those that might contain a comma.
Using the example: Foo.exe an example "is \"fine\", too" okay
The simple join suggestions will yield: an, example, is "fine", too, okay. Not bad, but not very clear and somewhat misleading.
Here's what I threw together that works well enough for me. I'm sure it could be improved further.
String.Join(", ", (from a in args select '"' + a.Replace("\"", #"\""") + '"'));
It returns the string: "an", "example", "is \"fine\", too", "okay". I think this does a better job indicating the actual parameters.

String params = String.Join(",", args);

You should use:
string.Join(",", args);
Strictly speaking the Join function creates a StringBuilder with capacity strings.Length * 16 (this 16 is a fixed number). If you have different args maximum size and if performance is crucial to you, use a StringBuilder with a specific capacity.

Related

C#: How to show a newline within a MessageBox

I often display messages using MessageBox.Show("This is my message");.
Sometimes I need a newline within a longer text.
Usually I use a variant which put one string per line:
MessageBox.Show("Line1" + Environment.NewLine + "Line2" + Environment.NewLine + "Line3");
But I don't like the "overhead". So I found the following solution:
MessageBox.Show(string.Format("Line1{0}Line2{0}Line3", Environment.NewLine));
Is there a better solution with less overhead?
You have pretty much found both ways to do it. A third one would be with string interpolation (to avoid the "extra" string.Format call.
$"Line1 {Environment.NewLine} Line2 {Environment.NewLine} Line3"
Fiddler example: https://dotnetfiddle.net/16Wy57
The string.Format way is pretty much the example at the official format docs
I prefer interpolation as it avoids the extra function in my code, but really it all comes down to preference.
There really is no "overhead" in any of the options, as the operation is trivial and at the end of the day, you concatenate strings.
If you want a growable solution with less overhead, here's a solution that is clean and scalable:
using System;
var messageLines = new string[]
{
"Some line here",
"More lines",
"Could be loaded from a database",
"With each row as a string"
};
MessageBox.Show(string.Join(Environment.NewLine, messageLines));
Verbatim strings, just make sure you don't have identations on the string.
string v =
#"Hello,
! Today is
, it's
now.";
Console.WriteLine(v);
Output:
Hello,
! Today is
, it's
now.
Demo: https://dotnetfiddle.net/WvjGfC
MessageBox.Show("First Line\nSecond Line\nThird Line");
\n inserts a new line in a string which works for MessageBox.
Be careful with this within files. There you find \r\n, \n\r, \r, \n - it depends on the operating system or file format.
Luke Parker's example can be slicked up a bit if you make your own MessageBox class (sadly it can't be done as an extension method because there isn't an available instance of MessageBox):
namespace System.Windows.Forms
{
public static class MessageBoxLines
{
public static void Show(string[] lines)
{
MessageBox.Show(string.Join(Environment.NewLine, lines));
}
}
}
You'd use it like:
MessageBoxLines.Show(new[] { "Line1", "Line2"} );
You'd add more overloads or optional parameters for the other forms (those that take a caption, specify the buttons etc
This could be tidied further if you use a params array:
public static void Show(params string[] lines)
{
MessageBox.Show(string.Join(Environment.NewLine, lines));
}
Which you'd use like:
MessageBoxLines.Show("Line1", "Line2" );
But using params would possibly interfere with the standard pattern for the other overloads (buttons etc) so you'd have to get more cute working that one out, either by rearranging the order so params is last or by putting all the args into a params object and digging them out / casting them back to what they should be (which clowns intellisense a bit)

Split string to array when some elements are empty

I need to process a large amount of csv data in real time as it is spat out by a TCP port. Here is an example as displayed by Putty:
MSG,3,1920,742,4009C5,14205994,2017/01/29,20:14:27.065,2017/01/29,20:14:27.972,,8000,,,51.26582,-0.33783,,,0,0,0,0
MSG,4,1920,742,4009C5,14205994,2017/01/29,20:14:27.065,2017/01/29,20:14:27.972,,,212.9,242.0,,,0,,,,,
MSG,1,1920,742,4009C5,14205994,2017/01/29,20:14:27.065,2017/01/29,20:14:27.972,BAW469,,,,,,,,,,,
MSG,3,1920,742,4009C5,14205994,2017/01/29,20:14:27.284,2017/01/29,20:14:27.972,,8000,,,51.26559,-0.33835,,,0,0,0,0
MSG,4,1920,742,4009C5,14205994,2017/01/29,20:14:27.284,2017/01/29,20:14:27.972,,,212.9,242.0,,,0,,,,,
I need to put each line of data in string (line) into an array (linedata[]) so that I can read and process certain elements, but linedata = line.Split(','); seems to ignore the many empty elements, with the result that linedata[20], for example, may or may not exist, and if it doesn't I get an error if I try to read it. Even if element 20 in the line contains a value it won't necessarily be the 20th element in the array. And that's no good.
I can work out how to parse line character by character into linedata[], inserting an empty string where appropriate, but surely there must be a better way ? Have I missed something obvious ?
Many Thanks. Perhaps I'd better add that I'm quite new to C#, my past experience is all with Delphi 7. I really miss stringlists.
Edited: sorry, this is now resolved with the help of MSDN's documentation. This code works: lineData = line.Split(separators, StringSplitOptions.None); after setting "string[] separators = { "," };". My big mistake was to follow examples found on tutorial sites which didn't give any clues that the .split method had any options.
https://msdn.microsoft.com/en-us/library/system.stringsplitoptions(v=vs.110).aspx
That link has an example section, look at example 1b specifically. There is an extra parameter to Split called StringSplitOptions which does this.
For Example:
string[] linedata = line.Split(charSeparators, StringSplitOptions.None);
foreach (string line in linedata)
{
Console.Write("<{0}>", line);
}
Console.Write("\n\n");
The way to find this sort of information is to start with the Reference Documentation for the function, and hope it has an option or a link to a similar function.
If you want to also start validating types, handling variants in the format etc... you could move up to a CSV library. If you do not need that functionality, this is the easiest way and efficient for small files.
Some of the overloads for String.Split() take a StringSplitOptions argument, and if you use the RemoveEmptyEntries option, it will...remove the empty entries. So you can specify the None option:
linedata = line.Split(new [] { ',' }, StringSplitOptions.None);
Or better yet, use the overload that doesn't take a StringSplitOptions, which treats it as None by default:
linedata = line.Split(',');
The code in your question indicates that you are doing this, but your description of the problem suggests that you are not.
However, you're probably better off using an actual CSV parser, which would handle things like unescaping and so on.
The StringReader class provides methods for reading lines, characters, or blocks of characters from a string. Hope this could be the clue
string str = #"MSG,3,1920,742,4009C5,14205994,2017/01/29,20:14:27.065,2017/01/29,20:14:27.972,,8000,,,51.26582,-0.33783,,,0,0,0,0
MSG,4,1920,742,4009C5,14205994,2017/01/29,20:14:27.065,2017/01/29,20:14:27.972,,,212.9,242.0,,,0,,,,,
MSG,1,1920,742,4009C5,14205994,2017/01/29,20:14:27.065,2017/01/29,20:14:27.972,BAW469,,,,,,,,,,,
MSG,3,1920,742,4009C5,14205994,2017/01/29,20:14:27.284,2017/01/29,20:14:27.972,,8000,,,51.26559,-0.33835,,,0,0,0,0
MSG,4,1920,742,4009C5,14205994,2017/01/29,20:14:27.284,2017/01/29,20:14:27.972,,,212.9,242.0,,,0,,,,,";
using (StringReader reader = new StringReader(str))
do
{
string[] linedata = reader.ReadLine().Split(',');
} while (reader.Read() != -1);
While you should look into the various ways the String class can help you here, sometimes the quick and dirty "MAKE it fit" option is called for. In this case, that'd be to roll through the strings in advance and ensure you have at least one character between the commas.
public static string FixIt(string s)
{
return s.Replace(",,", ", ,");
}
You should be able to:
var lineData = FixIt(line).Split(',');
Edit: In response to the question below, I'm not sure what you meant, but if you mean doing it without creating a helper method, you can do so easily. The code will be harder to read and troubleshoot if you do it in one line though. My personal rule is, if you have to do it a LOT, it should probably be a method. If you only had to do it once, this is particularly clean. I'd actually do it this way and just wrap it in a method that does all the work for you.
var lineData = line.Replace(",,", ", ,").Split(',');
As a method, it'd be:
public static string[] GiveMeAnArray(string s)
{
return s.Replace(",,", ", ,").Split(',');
}

How do I do multiple replaces on a string at the same time?

string rawConnString = Properties.Settings.Default.ConnectionString;
I want to do this with "rawConnString":
rawConnString.Replace("<<DATA_SOURCE>>", server);
rawConnString.Replace("<<INITIAL_CATALOG>>", "tempdb");
Then set the final string to variable finalConnString.
How would I go about doing this?
This is ASP .NET 4.0/C# btw.
string finalString = Properties.Settings.Default.ConnectionString.Replace("<<DATA_SOURCE>>", server).Replace("<<INITIAL_CATALOG>>", "tempdb");
will do it all in one line of code. But it's uglier IMO because you'll have to scroll. The code in your question seems a LOT cleaner and more readable to me.
And doing it in one line of code won't help your performance at all. It should all compile down to the same MSIL either way. I'd leave it as you had it.
Not sure if this is what you're after, but you can chain them:
var finalConnString = rawConnString.Replace("<<DATA_SOURCE>>", server)
.Replace("<<INITIAL_CATALOG>>", "tempdb");
If you're looking to do it with a single method call, I don't think there's anything native to .NET. You can always create an extension method though. Here's a performance-conscious ReplaceMany implementation (signature .ReplaceMany(string[] oldValues, string[] newValues)).
This is frankly trivial; you have 90% of the code you need:
string rawConnString = Properties.Settings.Default.ConnectionString;
string finalConnString = rawConnString
.Replace("<<DATA_SOURCE>>", server)
.Replace("<<INITIAL_CATALOG>>", "tempdb");
To avoid using two back-to-back calls of Replace, you can use regular expressions. However, this is far less readable than the original:
string connString = Regex.Replace(
rawConnString
, "(<<DATA_SOURCE>>)|(<<INITIAL_CATALOG>>)"
, m => m.Groups[1].Success ? server : "tempdb"
);
Link to ideone.
you mean something like this
string tempString=rawConnString.Replace("<<DATA_SOURCE>>", server);
sting finalstring=tempString.Replace("<<INITIAL_CATALOG>>", "tempdb");
First, String.replace does not change the original string: it creates a new string. So you have to assign the return value to something. So the logically simplest thing to do is:
finalstring=rawConnString.Replace("<<DATA_SOURCE>>", server);
finalstring=finalstring.Replace("<<INITIAL_CATALOG>>", "tempdb");
Note that for the second replace, you want to start with the results of the first replace, not the original string.
As String.replace returns a string, and String.replace takes a string, you might find it easier to run them together:
finalstring=rawConnString.Replace("<<DATA_SOURCE>>", server).Replace("<<INITIAL_CATALOG>>", "tempdb");

how to get a String with String.Format to execute?

I have a little chunk of code (see below) that is returning the string:
string.Format("{0}----{1}",3,"test 2");
so how do I get this to actually "Execute"? To run and do the format/replacement of {0} and {1}?
My Code snippet:
StringBuilder sb = new StringBuilder();
sb.Append("{0}----{1}\",");
sb.AppendFormat(ReturnParamValue(siDTO, "siDTO.SuggestionItemID,siDTO.Title"));
string sbStr = "=string.Format(\""+sb.ToString()+");";
yes, ReturnParamValue gives the actually value of the DTO.
Anyways, I've taken a look at the following (but it doesn't say how to execute it:
How to get String.Format not to parse {0}
Maybe, I just should put my code snippet in a method. But, what then?
Why are you including String.Format in the string itself?
If you're looking for a generic "let me evaluate this arbitrary expression I've built up in a string" then there isn't a simple answer.
If, instead, you're looking at how to provide the parameters to the string from a function call, then you've got yourself all twisted up and working too hard.
Try something like this, based on your original code:
string result
= string.Format(
"{0}----{1}",
ReturnParamValue(siDTO, "siDTO.SuggestionItemID,siDTO.Title"));
Though, this won't entirely work since your original code seems to be only providing a single value, and you have two values in your format string - the {0} will be replaced with the value from your function, and {1} left unchanged.
What output are you expecting?
Does your ReturnParamValue() function try to return both the label and the value in a single string? If it does, and if they're comma separated, then you could try this:
var value = ReturnParamValue(siDTO, "siDTO.SuggestionItemID,siDTO.Title"));
var pieces = string.Split(',');
string result
= string.Format( "{0}----{1}", pieces[0], pieces[1]);
Though this is seriously working too hard if ReturnParamValue() is a method you control.
Update Fri 6 August
Check out the declaration for string.Format() as shown on MSDN:
public static string Format(
string format,
params Object[] args
)
Unlike the special casing you might have seen in C for printf(), there's nothing special or unusual about the way string.Format() handles multiple parameters. The key is the params keyword, which asks the compiler to provide a little "syntactic sugar" where it combines the parameters into an array for you.
Key here is that the wrapping doesn't happen if you're already passing a single object[] - so if you wanted to, you could do something like this:
object[] parameters
= ReturnParamValues(siDTO, "siDTO.SuggestionItemID,siDTO.Title");
string result
= string.Format("{0}----{1}----{2}", parameters);
Though, if I saw something like this in any codebase I maintained, I'd be treating it as a code-smell and looking for a better way to solve the problem.
Just because it's possible doesn't mean it's advisable. YMMV, of course.
I don't think you can execute it. Java is not really a interpreted language.
You may make use of scripting languages (which can even embed in your Java app as I know, start from JDK6) for such purpose, like Groovy
You could use RegEx to parse the three parameters out of the string, and then pass them to a real, actual string.Format method :-)
It looks like what you want is something like this:
string sbStr = string.Format("{0}----{1}", siDTO.SuggestionItemID, siDTO.Title);
Maybe i didn't understand your question completely, but it sounds like you need to format a format-string. If that's true you could maybe try something like this:
int width = 5;
string format = String.Format("{{0,{0}}}----{{1,{0}}}", width);
string result = String.Format(format, "ab", "cd");
So the trick is simply to escape the { or } by using a double {{ or }}.

List of strings to one string

Lets say you have a:
List<string> los = new List<string>();
In this crazy functional world we live in these days which one of these would be best for creating one string by concatenating these:
String.Join(String.Empty, los.ToArray());
StringBuilder builder = new StringBuilder();
los.ForEach(s => builder.Append(s));
string disp = los.Aggregate<string>((a, b) => a + b);
or Plain old StringBuilder foreach
OR is there a better way?
I would go with option A:
String.Join(String.Empty, los.ToArray());
My reasoning is because the Join method was written for that purpose. In fact if you look at Reflector, you'll see that unsafe code was used to really optimize it. The other two also WORK, but I think the Join function was written for this purpose, and I would guess, the most efficient. I could be wrong though...
As per #Nuri YILMAZ without .ToArray(), but this is .NET 4+:
String.Join(String.Empty, los);
string.Concat(los.ToArray());
If you just want to concatenate the strings then use string.Concat() instead of string.Join().
If you use .net 4.0 you can use a sorter way:
String.Join<string>(String.Empty, los);
String.Join() is implemented quite fast, and as you already have a collection of the strings in question, is probably the best choice. Above all, it shouts "I'm joining a list of strings!" Always nice.
los.Aggregate((current, next) => current + "," + next);
My vote is string.Join
No need for lambda evaluations and temporary functions to be created, fewer function calls, less stack pushing and popping.

Categories

Resources