I need to create guids from their string equivalents from a text dump that I get from the Mailchimp 1.0 export api.
The guids are all strings that contain the backslash \ character, for example here is (truncated) one of them:
"\"9ffd2c3-6er456ds\""
When I pass the guid to the following methods, nothing works when I then attempt Guid.TryParse.
string[] values = sub.Split(',');
string rawguid = values[3];
var guid = rawguid.Replace("\\", "");
var tguid = rawguid.Trim();
var sguid = rawguid.Normalize().ToString();
How can I properly parse these guid strings into guids?
There are no backslashes in your guid - those are escaped doublequotes inside the string : the backslash is escaping the " inside it. Use .Replace("\"","") to remove them.
Beside that - you do not have a valid GUID - there are r and a s inside - guids consist of 32 digits using only 0-9a-fA-F.
Example using Guid.ParseExact:
using System;
public class Program
{
public static void Main()
{
var guid = Guid.ParseExact(
"\"ab9ffd2c3-6e456daaaaaaaaaaaaaaaaa\"" // guid with masked " inside
.Replace("-","") // remove all - for N
.Replace("\"",""), "N"); // remove all \" as well
Console.WriteLine( guid );
}
}
to get a parsed guid:
ab9ffd2c-36e4-56da-aaaa-aaaaaaaaaaaa
I need to demilitarise text by a single character, a comma. But I want to only use that comma as a delimiter if it is not encapsulated by quotation marks.
An example:
Method,value1,value2
Would contain three values: Method, value1 and value2
But:
Method,"value1,value2"
Would contain two values: Method and "value1,value2"
I'm not really sure how to go about this as when splitting a string I would use:
String.Split(',');
But that would demilitarise based on ALL commas. Is this possible without getting overly complicated and having to manually check every character of the string.
Thanks in advance
Copied from my comment: Use an available csv parser like VisualBasic.FileIO.TextFieldParser or this or this.
As requested, here is an example for the TextFieldParser:
var allLineFields = new List<string[]>();
string sampleText = "Method,\"value1,value2\"";
var reader = new System.IO.StringReader(sampleText);
using (var parser = new Microsoft.VisualBasic.FileIO.TextFieldParser(reader))
{
parser.Delimiters = new string[] { "," };
parser.HasFieldsEnclosedInQuotes = true; // <--- !!!
string[] fields;
while ((fields = parser.ReadFields()) != null)
{
allLineFields.Add(fields);
}
}
This list now contains a single string[] with two strings. I have used a StringReader because this sample uses a string, if the source is a file use a StreamReader(f.e. via File.OpenText).
You can try Regex.Split() to split the data up using the pattern
",|(\"[^\"]*\")"
This will split by commas and by characters within quotes.
Code Sample:
using System;
using System.Linq;
using System.Text.RegularExpressions;
public class Program
{
public static void Main()
{
string data = "Method,\"value1,value2\",Method2";
string[] pieces = Regex.Split(data, ",|(\"[^\"]*\")").Where(exp => !String.IsNullOrEmpty(exp)).ToArray();
foreach (string piece in pieces)
{
Console.WriteLine(piece);
}
}
}
Results:
Method
"value1,value2"
Method2
Demo
I'm in the process of needing to parse a file who's records are of the following format:
mr
Sean r.
Farrow
4 The Crescent
Eastleake
Loughborough
Leicestershire
LE12 6QH
01509 59213
07525945447
sean.farrow#seanfarrow.co.uk
Each record is delimited by a blank line to finish. The two phone numbers and email address are optional.
What is the best way of parsing this sort of record? I could write my own parser, but am hoping I don't have to!
FileHelpers expects each record to end with a new line, so you'd have to pre-parse the input before passing it the engine. That's straightforward to do though - something like:
var lines = File.ReadAllLines(pathToImportFile);
var sb = new StringBuilder();
var separator = ","; // use a comma as field delimiter
foreach (string line in lines)
{
if (String.IsNullOrEmpty(line))
sb.AppendLine(""); // convert empty lines into line feeds
else
sb.AppendFormat("\"{0}\"{1}", line, separator); // put quotes around the field to avoid problems with nested separators
}
var engine = new FileHelperEngine<MyClass>();
engine.ReadString(sb.ToString());
and your class would look something like
[DelimitedRecord(",")]
class MyClass
{
[FieldQuoted(QuoteMode.AlwaysQuoted)]
public string Title;
[FieldQuoted(QuoteMode.AlwaysQuoted)]
public string FullName;
[FieldQuoted(QuoteMode.AlwaysQuoted)]
public string Address1;
/// ... etc
}
Hi there I have a string return from url like that :
{ "Title": "Star Wars", "Year": "1977", "Rated":"3" }
How can I pick up such title, rating, Year without using Json library?
You can try to do it this way :
var str = #"{ ""Title"": ""Star Wars"", ""Year"": ""1977"", ""Rated"":""3"" }";
//remove "{" and "}" from string
var result = str.Trim('{', '}');
//separate each property-value pairs, and remove leading & trailing white spaces
var pairs = result.Split(',').Select(o => o.Trim()).ToArray();
foreach (var pair in pairs)
{
//separate key from it's value and remove leading & trailing white spaces
var keyValue = pair.Split(':').Select(o => o.Trim()).ToArray();
//print result
Console.WriteLine("{0} = {1}", keyValue[0], keyValue[1]);
}
UPDATE :
I agree with #pickypg comment, manually doing set of string manipulation operations isn't the ultimate way to handle JSON. This is better only on specific case: handling small JSON containing 'safe' string. If you're looking for general & robust approach, no one will argue with suggestion to use proven JSON library like JSON.NET. Also agree about using .Trim() instead of twice Replace(), hence updated my code a bit.
If you need to parse Json you should use a library to do it properly. Well, this solution can be a little overkill but you could do something like this:
Regex regex = new Regex("\"(?<field>.+?)\":\\s*\"(?<value>.*?)\"");
Match match = regex.Match("{ \"Title\": \"Star Wars\", \"Year\": \"1977\", \"Rated\":\"3\" }");
while (match.Success)
{
Console.WriteLine("Field: "+match.Groups["field"].Value+ ", Value: "+match.Groups["value"].Value);
match = match.NextMatch();
}
this is not valid json, you'd have to manually parse like split.
Parse error on line 4:
..."1977", "Rated"}
---------------------^
Expecting ':'
Try this
string[] words = s.Split(' ');
foreach (string word in words)
{
Console.WriteLine(word);
}
Class code added ignore above:
public class RootObject
{
public string Title { get; set; }
public string Year { get; set; }
public string Rated { get; set; }
}
using json2csharp
Is there an easy way in C# to read a properties file that has each property on a separate line followed by an equals sign and the value, such as the following:
ServerName=prod-srv1
Port=8888
CustomProperty=Any value
In Java, the Properties class handles this parsing easily:
Properties myProperties=new Properties();
FileInputStream fis = new FileInputStream (new File("CustomProps.properties"));
myProperties.load(fis);
System.out.println(myProperties.getProperty("ServerName"));
System.out.println(myProperties.getProperty("CustomProperty"));
I can easily load the file in C# and parse each line, but is there a built in way to easily get a property without having to parse out the key name and equals sign myself? The C# information I have found seems to always favor XML, but this is an existing file that I don't control and I would prefer to keep it in the existing format as it will require more time to get another team to change it to XML than parsing the existing file.
No there is no built-in support for this.
You have to make your own "INIFileReader".
Maybe something like this?
var data = new Dictionary<string, string>();
foreach (var row in File.ReadAllLines(PATH_TO_FILE))
data.Add(row.Split('=')[0], string.Join("=",row.Split('=').Skip(1).ToArray()));
Console.WriteLine(data["ServerName"]);
Edit: Updated to reflect Paul's comment.
Final class. Thanks #eXXL.
public class Properties
{
private Dictionary<String, String> list;
private String filename;
public Properties(String file)
{
reload(file);
}
public String get(String field, String defValue)
{
return (get(field) == null) ? (defValue) : (get(field));
}
public String get(String field)
{
return (list.ContainsKey(field))?(list[field]):(null);
}
public void set(String field, Object value)
{
if (!list.ContainsKey(field))
list.Add(field, value.ToString());
else
list[field] = value.ToString();
}
public void Save()
{
Save(this.filename);
}
public void Save(String filename)
{
this.filename = filename;
if (!System.IO.File.Exists(filename))
System.IO.File.Create(filename);
System.IO.StreamWriter file = new System.IO.StreamWriter(filename);
foreach(String prop in list.Keys.ToArray())
if (!String.IsNullOrWhiteSpace(list[prop]))
file.WriteLine(prop + "=" + list[prop]);
file.Close();
}
public void reload()
{
reload(this.filename);
}
public void reload(String filename)
{
this.filename = filename;
list = new Dictionary<String, String>();
if (System.IO.File.Exists(filename))
loadFromFile(filename);
else
System.IO.File.Create(filename);
}
private void loadFromFile(String file)
{
foreach (String line in System.IO.File.ReadAllLines(file))
{
if ((!String.IsNullOrEmpty(line)) &&
(!line.StartsWith(";")) &&
(!line.StartsWith("#")) &&
(!line.StartsWith("'")) &&
(line.Contains('=')))
{
int index = line.IndexOf('=');
String key = line.Substring(0, index).Trim();
String value = line.Substring(index + 1).Trim();
if ((value.StartsWith("\"") && value.EndsWith("\"")) ||
(value.StartsWith("'") && value.EndsWith("'")))
{
value = value.Substring(1, value.Length - 2);
}
try
{
//ignore dublicates
list.Add(key, value);
}
catch { }
}
}
}
}
Sample use:
//load
Properties config = new Properties(fileConfig);
//get value whith default value
com_port.Text = config.get("com_port", "1");
//set value
config.set("com_port", com_port.Text);
//save
config.Save()
Most Java ".properties" files can be split by assuming the "=" is the separator - but the format is significantly more complicated than that and allows for embedding spaces, equals, newlines and any Unicode characters in either the property name or value.
I needed to load some Java properties for a C# application so I have implemented JavaProperties.cs to correctly read and write ".properties" formatted files using the same approach as the Java version - you can find it at http://www.kajabity.com/index.php/2009/06/loading-java-properties-files-in-csharp/.
There, you will find a zip file containing the C# source for the class and some sample properties files I tested it with.
Enjoy!
Yet another answer (in January 2018) to the old question (in January 2009).
The specification of Java properties file is described in the JavaDoc of java.util.Properties.load(java.io.Reader). One problem is that the specification is a bit complicated than the first impression we may have. Another problem is that some answers here arbitrarily added extra specifications - for example, ; and ' are regarded as starters of comment lines but they should not be. Double/single quotations around property values are removed but they should not be.
The following are points to be considered.
There are two kinds of line, natural lines and logical lines.
A natural line is terminated by \n, \r, \r\n or the end of the stream.
A logical line may be spread out across several adjacent natural lines by escaping the line terminator sequence with a backslash character \.
Any white space at the start of the second and following natural lines in a logical line are discarded.
White spaces are space (, \u0020), tab (\t, \u0009) and form feed (\f, \u000C).
As stated explicitly in the specification, "it is not sufficient to only examine the character preceding a line terminator sequence to decide if the line terminator is escaped; there must be an odd number of contiguous backslashes for the line terminator to be escaped. Since the input is processed from left to right, a non-zero even number of 2n contiguous backslashes before a line terminator (or elsewhere) encodes n backslashes after escape processing."
= is used as the separator between a key and a value.
: is used as the separator between a key and a value, too.
The separator between a key and a value can be omitted.
A comment line has # or ! as its first non-white space characters, meaning leading white spaces before # or ! are allowed.
A comment line cannot be extended to next natural lines even its line terminator is preceded by \.
As stated explicitly in the specification, =, : and white spaces can be embedded in a key if they are escaped by backslashes.
Even line terminator characters can be included using \r and \n escape sequences.
If a value is omitted, an empty string is used as a value.
\uxxxx is used to represent a Unicode character.
A backslash character before a non-valid escape character is not treated as an error; it is silently dropped.
So, for example, if test.properties has the following content:
# A comment line that starts with '#'.
# This is a comment line having leading white spaces.
! A comment line that starts with '!'.
key1=value1
key2 : value2
key3 value3
key\
4=value\
4
\u006B\u0065\u00795=\u0076\u0061\u006c\u0075\u00655
\k\e\y\6=\v\a\lu\e\6
\:\ \= = \\colon\\space\\equal
it should be interpreted as the following key-value pairs.
+------+--------------------+
| KEY | VALUE |
+------+--------------------+
| key1 | value1 |
| key2 | value2 |
| key3 | value3 |
| key4 | value4 |
| key5 | value5 |
| key6 | value6 |
| : = | \colon\space\equal |
+------+--------------------+
PropertiesLoader class in Authlete.Authlete NuGet package can interpret the format of the specification. The example code below:
using System;
using System.IO;
using System.Collections.Generic;
using Authlete.Util;
namespace MyApp
{
class Program
{
public static void Main(string[] args)
{
string file = "test.properties";
IDictionary<string, string> properties;
using (TextReader reader = new StreamReader(file))
{
properties = PropertiesLoader.Load(reader);
}
foreach (var entry in properties)
{
Console.WriteLine($"{entry.Key} = {entry.Value}");
}
}
}
}
will generate this output:
key1 = value1
key2 = value2
key3 = value3
key4 = value4
key5 = value5
key6 = value6
: = = \colon\space\equal
An equivalent example in Java is as follows:
import java.util.*;
import java.io.*;
public class Program
{
public static void main(String[] args) throws IOException
{
String file = "test.properties";
Properties properties = new Properties();
try (Reader reader = new FileReader(file))
{
properties.load(reader);
}
for (Map.Entry<Object, Object> entry : properties.entrySet())
{
System.out.format("%s = %s\n", entry.getKey(), entry.getValue());
}
}
}
The source code, PropertiesLoader.cs, can be found in authlete-csharp. xUnit tests for PropertiesLoader are written in PropertiesLoaderTest.cs.
I've written a method that allows emty lines, outcommenting and quoting within the file.
Examples:
var1="value1"
var2='value2'
'var3=outcommented
;var4=outcommented, too
Here's the method:
public static IDictionary ReadDictionaryFile(string fileName)
{
Dictionary<string, string> dictionary = new Dictionary<string, string>();
foreach (string line in File.ReadAllLines(fileName))
{
if ((!string.IsNullOrEmpty(line)) &&
(!line.StartsWith(";")) &&
(!line.StartsWith("#")) &&
(!line.StartsWith("'")) &&
(line.Contains('=')))
{
int index = line.IndexOf('=');
string key = line.Substring(0, index).Trim();
string value = line.Substring(index + 1).Trim();
if ((value.StartsWith("\"") && value.EndsWith("\"")) ||
(value.StartsWith("'") && value.EndsWith("'")))
{
value = value.Substring(1, value.Length - 2);
}
dictionary.Add(key, value);
}
}
return dictionary;
}
Yeah there's no built in classes to do this that I'm aware of.
But that shouldn't really be an issue should it? It looks easy enough to parse just by storing the result of Stream.ReadToEnd() in a string, splitting based on new lines and then splitting each record on the = character. What you'd be left with is a bunch of key value pairs which you can easily toss into a dictionary.
Here's an example that might work for you:
public static Dictionary<string, string> GetProperties(string path)
{
string fileData = "";
using (StreamReader sr = new StreamReader(path))
{
fileData = sr.ReadToEnd().Replace("\r", "");
}
Dictionary<string, string> Properties = new Dictionary<string, string>();
string[] kvp;
string[] records = fileData.Split("\n".ToCharArray());
foreach (string record in records)
{
kvp = record.Split("=".ToCharArray());
Properties.Add(kvp[0], kvp[1]);
}
return Properties;
}
Here's an example of how to use it:
Dictionary<string,string> Properties = GetProperties("data.txt");
Console.WriteLine("Hello: " + Properties["Hello"]);
Console.ReadKey();
The real answer is no (at least not by itself). You can still write your own code to do it.
C# generally uses xml-based config files rather than the *.ini-style file like you said, so there's nothing built-in to handle this. However, google returns a number of promising results.
I don't know of any built-in way to do this. However, it would seem easy enough to do, since the only delimiters you have to worry about are the newline character and the equals sign.
It would be very easy to write a routine that will return a NameValueCollection, or an IDictionary given the contents of the file.
You can also use C# automatic property syntax with default values and a restrictive set. The advantage here is that you can then have any kind of data type in your properties "file" (now actually a class). The other advantage is that you can use C# property syntax to invoke the properties. However, you just need a couple of lines for each property (one in the property declaration and one in the constructor) to make this work.
using System;
namespace ReportTester {
class TestProperties
{
internal String ReportServerUrl { get; private set; }
internal TestProperties()
{
ReportServerUrl = "http://myhost/ReportServer/ReportExecution2005.asmx?wsdl";
}
}
}
There are several NuGet packages for this, but all are currently in pre-release version.
Capgemini.Cauldron.Core.JavaProperties 2.0.39-beta
Kajabity.Tools.Java 0.2.6638.28124
[Update]
As of June 2018, Capgemini.Cauldron.Core.JavaProperties is now in a stable version (version 2.1.0 and 3.0.20).
I realize that this isn't exactly what you're asking, but just in case:
When you want to load an actual Java properties file, you'll need to accomodate its encoding. The Java docs indicate that the encoding is ISO 8859-1, which contains some escape sequences that you might not correctly interpret. For instance look at this SO answer to see what's necessary to turn UTF-8 into ISO 8859-1 (and vice versa)
When we needed to do this, we found an open-source PropertyFile.cs and made a few changes to support the escape sequences. This class is a good one for read/write scenarios. You'll need the supporting PropertyFileIterator.cs class as well.
Even if you're not loading true Java properties, make sure that your prop file can express all the characters you need to save (UTF-8 at least)
No there is not : But I have created one easy class to help :
public class PropertiesUtility
{
private static Hashtable ht = new Hashtable();
public void loadProperties(string path)
{
string[] lines = System.IO.File.ReadAllLines(path);
bool readFlag = false;
foreach (string line in lines)
{
string text = Regex.Replace(line, #"\s+", "");
readFlag = checkSyntax(text);
if (readFlag)
{
string[] splitText = text.Split('=');
ht.Add(splitText[0].ToLower(), splitText[1]);
}
}
}
private bool checkSyntax(string line)
{
if (String.IsNullOrEmpty(line) || line[0].Equals('['))
{
return false;
}
if (line.Contains("=") && !String.IsNullOrEmpty(line.Split('=')[0]) && !String.IsNullOrEmpty(line.Split('=')[1]))
{
return true;
}
else
{
throw new Exception("Can not Parse Properties file please verify the syntax");
}
}
public string getProperty(string key)
{
if (ht.Contains(key))
{
return ht[key].ToString();
}
else
{
throw new Exception("Property:" + key + "Does not exist");
}
}
}
Hope this helps.