How to replace > 1 tokens on a string? - c#
I have a list of tokens
[#date]
[#time]
[#fileName]
... etc
That are dispersed all over a large file. I can parse the file and replace them with Regex.Replace easily when there's only one token on a line. However the problem arises when there's two tokens on one line
example:
[#date] [#time]
What I thought about doing is using String.Split with " " as the delimiter, and then iterate through the result checking if there are tokens.
But I see two problems with this approach, the file is rather large and this would definitely impact performance. The second problem is that the file that will be outputted is a SQL file and I'd like to retain the white space just for looks.
Is there a more elegant solution to this problem? Or is it just another case of premature optimization?
One thing you can do is that instead of replacing patterns line by line, replace them in the whole file:
string fileContent = File.ReadAllText(path);
fileContent = Regex.Replace(fileContent, pattern1, replacement1);
...
fileContent = Regex.Replace(fileContent, patternN, replacementN);
One simple way to do this is to store tokens and their values separately and then to iterate over them replacing your query with values for that tokens. Example is given below:
var tokensWithValues = new Dictionary<string, object>()
{
{"[#date]", DateTime.Now},
{"[#time]", DateTime.Now.Ticks},
{"[#fileName]", "myFile.xml"},
};
var sqlQuery = File.ReadAllText("mysql.sql");
foreach (var tokenValue in tokensWithValues)
{
sqlQuery = sqlQuery.Replace(tokenValue.Key, tokenValue.Value.ToString());
}
try using the string.Replace(...) extension. That would allow you to Replace all instances of a string.
for example
string file = File.ReallAllText("myfile.txt");
file.Replace("[#date]", "replaced_value");
the above would replace all instances of "[#date]" with "replaced_value".
Edited as previous answer included custom extensions not available to OP. Thanks llya.
Related
Can someone please confirm the reason behind foreach loop giving error as "invalid token" and "splittedText" as does not exist in current context?
string[] splittedText = File.ReadAllLines(#"file.txt");//.Split(','); foreach (string data in splittedText) { } I want to read through a file in c# which returns array of string type. Then, I will be iterating over the array to fetch my desired data.
If you want to read a CSV file, you should use a CVS parser. Values in the CSV file are separated using command and in some cases, the value in the CSV file can also contain a comma. In that case, the column values are wrapped in double-quotes. And this solution will not handle that scenario. var splittedText = File.ReadAllText("E:\\Test.txt").Split(','); foreach (string data in splittedText) { Console.WriteLine(data.Trim()); }
Hint - Reading file line by line or Reading whole file content depends on your use case. May be below code snippet give some idea on how to split the content. Please try. var inputtext = File.ReadAllText(#"inpufile.txt"); inputtext.Replace("\n", "") .Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) .ToList().ForEach(t => { System.Console.WriteLine(t); //Other manupulations }); if you want to split based on multiple characters , pass a character array to the split(). new char[] { ',', ':' }; Thank you.
You need change File.ReadAllLines to File.ReadAllText(path) then you can split method.
Use everything before a specific character
So, I've been learning C# and I need to remove everything after the ":" character. I've used a StreamReader to read the text file, but then I can't use the Split function, then I tried it by using an int function to import it, but then again I can't use the Split function? What I want this to do is import a text file that's written like; name:lastname name2:lastname2 And so that it only shows name and name2. I've been searching this for a couple of days but I can't seem to figure it out! I don't know what I'm doing wrong and how to import the text file without using StreamReader or anything else. Edit: I'm trying to post something to a website that goes like; example.com/q=(name without ":") Edit 2: StreamReader list = new StreamReader(#"list.txt"); string reader = list.ReadToEnd(); string[] split = reader.Split(":".ToCharArray()); Console.WriteLine(split); gives output as; System.String[]
You've got a few issues here. First, use File.ReadLines() instead of a StreamReader, its much simpler and easier: IEnumerable<string> lines = File.ReadLines("path/to/file"); Next, your lines variable needs to be iterated so you can get to each line of the collection: foreach (string line in lines) { //TODO: write split logic here } Then you have to split each line on the ':' character: string[] split = line.Split(":"); Your split variable is an array of string (i.e string[]) which means you have to access a specific index of the array if you want to see its value. This is your second issue, if you pass split to Console.WriteLine() under the hood it just calls .ToString() on the object you have passed it, and with a string[] it won't automatically give you all the values, you have to write that yourself. So if your line variable was: "name:Steve", the split variable would have two indexes and look like this: //split[0] = "name" //split[1] = "Steve" I made a fiddle here that demonstrates.
I your file size small and your name:lastname in one line use: var lines = File.ReadAllLines("filaPath"); foreach (var line in lines) { var array = line.Split(':'); if (array.Length > 0) { var name = array[0]; } } if name:lastname isn't in new line tell me how it's seprated
How can i analise millions of strings that merge into each other?
I have millions of strings, around 8GB worth of HEX; each string is 3.2kb in length. Each of these strings contains multiple parts of data I need to extract. This is an example of one such string: GPGGA,104644.091,,,,,0,0,,,M,,M,,*43$GPVTG,0.00,T,,M,0.00,N,0.00,K,N*32Header Test.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ$GPGGA,104645.091,,,,,0,0,,,M,,M,,*42$GPVTG,0.00,T,,M,0.00,N,0.00,K,N*32Header Test.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ ÿÿ!ÿÿ"ÿÿ#ÿÿ$ÿÿ%ÿÿ&ÿÿ'ÿÿ(ÿÿ)ÿÿ*ÿÿ+ÿÿ,ÿÿ-ÿÿ.ÿÿ/ÿÿ0ÿÿ1ÿÿ$GPGGA,104646.091,,,,,0,0,,,M,,M,,*41$GPVTG,0.00,T,,M,0.00,N,0.00,K,N*32Header Test2ÿÿ3ÿÿ4ÿÿ5ÿÿ6ÿÿ7ÿÿ8ÿÿ9ÿÿ:ÿÿ;ÿÿ<ÿÿ=ÿÿ>ÿÿ?ÿÿ#ÿÿAÿÿBÿÿCÿÿDÿÿEÿÿFÿÿGÿÿHÿÿIÿÿJÿÿ$GPGGA,104647.091,,,,,0,0,,,M,,M,,*40$GPVTG,0.00,T,,M,0.00,N,0.00,K,N*32Header TestKÿÿLÿÿMÿÿNÿÿOÿÿPÿÿQÿÿRÿÿSÿÿTÿÿUÿÿVÿÿWÿÿXÿÿYÿÿZÿÿ[ÿÿ\ÿÿ]ÿÿ^ÿÿ_ÿÿ`ÿÿaÿÿbÿÿcÿÿ$GPGGA,104648.091,,,,,0,0,,,M,,M,,*4F$GPVTG,0.00,T,,M,0.00,N,0.00,K,N*32Header Testdÿÿeÿÿfÿÿgÿÿhÿÿiÿÿjÿÿkÿÿlÿÿmÿÿnÿÿoÿÿpÿÿqÿÿrÿÿsÿÿtÿÿuÿÿvÿÿwÿÿxÿÿyÿÿzÿÿ{ÿÿ|ÿÿ$GPGGA,104649.091,,,,,0,0,,,M,,M,,*4E$GPVTG,0.00,T,,M,0.00,N,0.00,K,N*32Header Test}ÿÿ~ÿÿ.ÿÿ€ÿÿ.ÿÿ‚ÿÿƒÿÿ„ÿÿ…ÿÿ†ÿÿ‡ÿÿˆÿÿ‰ÿÿŠÿÿ‹ÿÿŒÿÿ.ÿÿŽÿÿ.ÿÿ.ÿÿ‘ÿÿ’ÿÿ“ÿÿ”ÿÿ•ÿÿ$GPGGA,104650.091,,,,,0,0,,,M,,M,,*46$GPVTG,0.00,T,,M,0.00,N,0.00,K,N*32Head as you can see it is pretty much this repeated: GPGGA,104644.091,,,,,0,0,,,M,,M,,*43$GPVTG,0.00,T,,M,0.00,N,0.00,K,N*32Header Test.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ$GPGGA,104645.091,,,,,0,0,,,M,,M,,*42$GPVTG,0.00,T,,M,0.00,N,0.00,K,N*32Header Test.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ ÿÿ!ÿÿ"ÿÿ#ÿÿ$ÿÿ%ÿÿ&ÿÿ'ÿÿ(ÿÿ)ÿÿ*ÿÿ+ÿÿ,ÿÿ-ÿÿ.ÿÿ/ÿÿ0ÿÿ1ÿÿ I want to separate this string into two lists like this: _GPSList $GPGGA,104644.091,,,,,0,0,,,M,,M,,*43 $GPVTG,0.00,T,,M,0.00,N,0.00,K,N* $GPVTG,0.00,T,,M,0.00,N,0.00,K,N _WavList 32HeaderTest.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ 32HeaderTest.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ.ÿÿ ÿÿ!ÿÿ"ÿÿ#ÿÿ$ÿÿ%ÿÿ&ÿÿ'ÿÿ(ÿÿ)ÿÿ*ÿÿ+ÿÿ,ÿÿ-ÿÿ.ÿÿ/ÿÿ0ÿÿ1ÿÿ Issue 1: This repetition isn't containing within a single string, it overflows into the next string. so if some data crosses the end and start of two strings how to I deal with that? Issue 2: How do I analyse the string and extract only the parts I need?
The solution I'm providing is not a complete answer but more like an idea which might help you get what you want. Everything else which I present is an assumption on my behalf. //Assuming your data is stored in a file "yourdatafile" //Splitting all the text on "$" assuming this will separate GPSData string[] splittedstring = File.ReadAllText("yourdatafile").Split('$'); //I found an extra string lingering in the sample you provided //because I splitted on "$", so you gotta take that into account var GPSList = new List<string>(); var WAVList = new List<string>(); foreach (var str in splittedstring) { //So if the string contains "Header" we would want to separate it from GPS data if (str.Contains("Header")) { string temp = str.Remove(str.IndexOf("Header")); int indexOfAsterisk = temp.LastIndexOf("*"); string stringBeforeAsterisk = str.Substring(0, indexOfAsterisk + 1); string stringAfterAsterisk = str.Replace(stringBeforeAsterisk, ""); WAVList.Add(stringAfterAsterisk); GPSList.Add("$" + stringBeforeAsterisk); } else GPSList.Add("$" + str); } This provides the exact output as you need, only exception is with that extra string. Also some non-standard characters might look like black blocks.
How to handle quotation marks within CSV files?
To read a CSV file, I use the following statement: var query = from line in rawLines let data = line.Split(';') select new { col01 = data[0], col02 = data[1], col03 = data[2] }; The CSV file I want to read is malformed in the way, that an entry can have the separator ; itself as data when surrounded with qutation marks. Example: col01;col02;col03 data01;"data02;";data03 My read statement above does not work here, since it interprets the second row as four columns. Question: Is there an easy way to handle this malformed CSV correctly? Perhaps with another LINQ query?
Just use a CSV parser and STOP ROLLING YOUR OWN: using (var parser = new TextFieldParser("test.csv")) { parser.CommentTokens = new string[] { "#" }; parser.SetDelimiters(new string[] { ";" }); parser.HasFieldsEnclosedInQuotes = true; // Skip over header line. parser.ReadLine(); while (!parser.EndOfData) { string[] fields = parser.ReadFields(); Console.WriteLine("{0} {1} {2}", fields[0], fields[1], fields[2]); } } TextFieldParser is built in .NET. Just add reference to the Microsoft.VisualBasic assembly and you are good to go. A real CSV parser will happily handle this situation.
Parsing CSV files manually can always lead to issues like this. I would advise that you use a third party tool like CsvHelper to handle the parsing. Furthermore, it's not a good idea to explicitly parse commas, as your separator can be overridden in your computers environment options. Let me know if I can help further, Matt
Not very elegant but after using your method you can check if any colxx contains an unfinished quotation mark (single) you can join it with the next colxx.
cutting from string in C#
My strings look like that: aaa/b/cc/dd/ee . I want to cut first part without a / . How can i do it? I have many strings and they don't have the same length. I tried to use Substring(), but what about / ? I want to add 'aaa' to the first treeNode, 'b' to the second etc. I know how to add something to treeview, but i don't know how can i receive this parts.
Maybe the Split() method is what you're after? string value = "aaa/b/cc/dd/ee"; string[] collection = value.Split('/'); Identifies the substrings in this instance that are delimited by one or more characters specified in an array, then places the substrings into a String array. Based on your updates related to a TreeView (ASP.Net? WinForms?) you can do this: foreach(string text in collection) { TreeNode node = new TreeNode(text); myTreeView.Nodes.Add(node); }
Use Substring and IndexOf to find the location of the first / To get the first part: // from memory, need to test :) string output = String.Substring(inputString, 0, inputString.IndexOf("/")); To just cut the first part: // from memory, need to test :) string output = String.Substring(inputString, inputString.IndexOf("/"), inputString.Length - inputString.IndexOf("/");
You would probably want to do: string[] parts = "aaa/b/cc/dd/ee".Split(new char[] { '/' });
Sounds like this is a job for... Regular Expressions!
One way to do it is by using string.Split to split your string into an array, and then string.Join to make whatever parts of the array you want into a new string. For example: var parts = input.Split('/'); var processedInput = string.Join("/", parts.Skip(1)); This is a general approach. If you only need to do very specific processing, you can be more efficient with string.IndexOf, for example: var processedInput = input.Substring(input.IndexOf('/') + 1);