Search string according to specific format - c#

I'm having problem searching text with certain format. my file looks as below.
britney ak4564gc1 18
scott ak3333hc2 28
jenny ad4564gc3 32
amy ak4564gc4 29
I would like to search for worknumber with certain format which is dynamic. here is my code. the format must have specific length with * as change variable.
for (int line = 0; line <= Countline(OriFile)-1; line++)
{
var desiredText = File.ReadAllLines(OriFile).ElementAt(line);
string s = desiredText.ToString();
string b = s.Substring(WONUmStart, WONumLength);
//format changeable(I changed it to make it easier to understand)
if(b.Contains(a.TextBox.ToString())) //textbox value "ak****gc*"
{
if (WoNum != b)
{
WoNum = b;
StreamWriter sw = new StreamWriter(reportfile, true);
sw.WriteLine(Path.GetFileName(OriFile) +
" " +
WoNum +
" " +
Path.GetFileName(MergeFile));
sw.Flush();
sw.Close();
}
}
}
can anybody guide me?

I suggest using regular expressions with Linq, e.g.
string pattern = #"\bak.{3}gc.{1}\b";
var result = File
.ReadLines(OriFile)
.Select(line => Regex.Match(line, pattern)) // if we expect at most one match per line
.Where(match => match.Success)
.Select(match => match.Value);
...
File.WriteAllLines(reportfile, result.
Select(line => string.Format("{0} {1} {2}",
Path.GetFileName(OriFile), line, Path.GetFileName(MergeFile))));

Related

How to combine two texts?

I have a Single line text box and Multiline text box, and want to include a word into the Single line text box with the words in Multiline text box per line
Like this :
Single line text: "Hello"(I have to use variables)<br>
Multiline words:
<br>
1998<br>
1999<br>
2000
Expected results:
Hello1998
Hello1999
Hello2000
Pls Help me
I use the below code, but it is not working just with the Single line text box and I have to manipulate by both text boxes:
string left = string.Format(add.Text , Environment.NewLine);
string right = string.Format(textBox1.Text, Environment.NewLine);
string[] leftSplit = left.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
string[] rightSplit = right.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
string output = "";
if (leftSplit.Length == rightSplit.Length)
{
for (int i = 0; i < leftSplit.Length; i++)
{
output += leftSplit[i] + ":" + rightSplit[i] + Environment.NewLine;
}
}
result.Text = output;
Could you please advise me on the right approach?
If you have single line only one word, then no need split it into an array.
Lets consider it as a string left = "Hello";
and textbox1 contains multiline words i.e.
string right = string.Format(textBox1.Text, Environment.NewLine); // right variable contains 1998 \n 1999 \n 2000
Then you can try below approach
var concatString = right.Split(new[] { Environment.NewLine }, StringSplitOptions.None).Select(x => left + x);
string result = string.Join(Environment.NewLine , concatString);
.Net Fiddle
Output :
Hello1998
Hello1999
Hello2000
TextBox.GetLineText(int) will help you:
var singlelineText = singlelineTextBox.Text;
var composedLines = new List<string>();
for (var i = 0; i < multilineineTextBox.LineCount; i++)
{
composedLines.Add(singlelineText + multilineineTextBox.GetLineText(i));
}
result.Text = string.Join(EnvironmentNewline, composedLines);

How to write just an # before some rows in a text file?

I have a text file who are like this :
Rows
...
product.people
product.people_good
product.people_bad
product.boy
#product.me
...
Rows
I want to put # before product. and the file to be :
Rows
...
#product.people
#product.people_good
#product.people_bad
#product.boy
#product.me
...
Rows
For this I use next code :
string installerfilename = pathTemp + fileArr1;
string installertext = File.ReadAllText(installerfilename);
var linInst = File.ReadLines(pathTemp + fileArr1).ToArray();
foreach (var txt in linInst)
{
if (txt.Contains("#product="))
{
installertext = installertext.Replace("#product=", "product=");
}
else if (txt.Contains("product.") && (!txt.StartsWith("#")))
{
installertext = installertext.Replace(txt, "#" + txt);
}
File.WriteAllText(installerfilename, installertext);
}
But this code do the next thing:
Rows
...
#product.people
##product.people_good
##product.people_bad
#product.boy
#product.me
...
Rows
Someone can explain me way ? And how I can write just one # before that rows?
Currently you're reading the same text file twice - ones as individual lines and once as a whole thing. You're then rewriting a file as many times as you have lines. This is all broken. I suspect you simply want:
// Note name changes to satisfy .NET conventions
// Note: If pathTemp is a directory, you should use Path.Combine
string installerFileName = pathTemp + fileArr1;
var installerLines = File.ReadLines(installerFileName)
.Select(line => line.StartsWith("product=") ? "#" + line : line)
.ToList();
File.WriteAllLines(installerFileName, installerLines);
If you were writing to a different file than the one you were reading from, you wouldn't need the ToList call.
You can split by product, and then concatenate it to a new string :
// string installerFileText = File.ReadAllText(installerFileName);
string installerFileText = #"
Rows
...
product.people
product.people_good
product.people_bad
product.boy
...
Rows";
string[] lines = installerFileText.Split(new string[] { "product." }, StringSplitOptions.None);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < lines.Length; i++)
sb.Append(((i > 0 && i < lines.Length) ? "#product." : "") + lines[i]);
// File.WriteAllText(installerFileName, sb.ToString());
Console.WriteLine(sb.ToString());
Console.ReadKey();
Output:
Rows
...
#product.people
#product.people_good
#product.people_bad
#product.boy
...
Rows";
else if (txt.Contains("product.") && (!txt.StartsWith("#")))
{
installertext = installertext.Replace(txt, "#" + txt);
}
Why don't your replace the "!txt.StartsWith("#")" by a "!txt.Contains("#")" ?
Think that would do the trick !

Differentiating between different values with a Line.Contains()

Something I was curious about, I'm coding a utility for a old game that I play and this allows for custom NPC's. Long story short, I'm coding a reader for these custom NPC files. I've gotten most of the reading down with a line.contains() method (all code will be shown later) but there's a problem. The file can contain either just "height" or "gfxheight" which both do different things. Using line.contains("width") will make it output both width and gfxwidth twice. I don't really know any good way to explain it so here's the file:
width=32
height=32
gfxwidth=64
gfxheight=32
nofireball=1
noiceball=1
noyoshi=1
grabside=0
The Console output when I read it in and do what I need to split the lines and such:
And here's the code I use for height and gfxheight (of course there are others but these are the only problems I have when reading):
if (line.Contains("height"))
{
var split = line.Split(new char[] { '=' }, 2);
decimal dc;
//var val = int.Parse(split.ToString());
Console.WriteLine(split[0].ToString() + " is equal to " + split[1].ToString());
npcHeight.Value = Decimal.Parse(split[1].ToString());
npcHeight.Enabled = true;
npcHCb.Checked = true;
}
if (line.Contains("gfxheight"))
{
var split = line.Split(new char[] { '=' }, 2);
//var val = int.Parse(split.ToString());
Console.WriteLine(split[0].ToString() + " is equal to " + split[1].ToString());
}
Of course there's also the code for width and gfxwidth and the other various codes but I'm not going to bother posting those because I can apply what I get for the height to those.
So what would I have to do to differentiate between them? Suggestions?
Thanks in advanced,
Mike
Read the file into a string array, then parse it into a dictionary.
var file = File.ReadAllLines(yourFile);
var config = (from line in file
let s = line.Split('=')
select new { Key = s[0], Value = s[1] })
.ToDictionary(x => x.Key, x => x.Value);
Now you can access anything you want by referencing the key:
var gfxHeight = config["gfxheight"]; // gfxHeight is a string containing "32"
If you know the value after the = is always a number, you could parse it:
var config = (from line in file
let s = line.Split('=')
select new { Key = s[0], Value = int.Parse(s[1]) })
.ToDictionary(x => x.Key, x => x.Value);
var gfxHeight = config["gfxheight"]; // gfxHeight is an int containing 32
Instead of trying to figure out what each line is before splitting it, try splitting it first. This parsing approach leverages the format of the file and has a much-reduced dependency on its data:
foreach (var line in lines) {
var data = line.Split('=', 2);
if (data.Length != 2) {
continue;
}
var attrib = data[0];
var value = data[1];
Console.WriteLine(attrib + " is equal to " + value);
switch (attrib) {
case "height":
// ...
break;
case "gfxheight":
// ...
break;
}
}
I figured out a solution actually! Be warned: I haven't refreshed the page yet to see any proposed answers.
if (line.Contains("width"))
{
if (line.Contains("gfx"))
{
var split = line.Split(new char[] { '=' }, 2);
//var val = int.Parse(split.ToString());
Console.WriteLine(split[0].ToString() + " is equal to " + split[1].ToString());
npcWidth.Value = Decimal.Parse(split[1].ToString());
npcWidth.Enabled = true;
npcWCb.Checked = true;
}
else
{
var split = line.Split(new char[] { '=' }, 2);
Console.WriteLine(split[0].ToString() + " is equal to " + split[1].ToString());
pNpcWidth.Value = Decimal.Parse(split[1].ToString());
pNpcWidth.Enabled = true;
pNpcWidthCb.Checked = true;
}
}
Basically that ^
What it does is checks if the line is width with that line.Contains method. And if it does, it then checks to see if it contains gfx in it (as in gfxheight, gfxwidth, etc) and if it does, then that's the gfxheight or gfxwidth value. If not, it's the regular height/width.

Need to count incidents found multiple times within a text file

I'm really trying to count the number of times a regex is found within a text but there are many regex to be found within a text file.
the problem is that my code only counts the first time, the subsequent IF that contains the other regexes will not count, Everything works but the counting of on each line that error occurred :(
could you please shed some light?
int counter = 1;
string liner;
string pattern = #"access-group\s+\w+\s+out\s+interface\s+\w+";
Boolean foundMatch;
int totalOUTgroups = Lines(ofd.FileName)
.Select(line => Regex.Matches(line, pattern).Count)
.Sum();
if (totalOUTgroups > 0)
{
richTextBox2.SelectionFont = new Font("Courier New", 8);
richTextBox2.AppendText(">>> ACls installed by using access-group using the keyword OUT are NOT supported: " + "\u2028");
richTextBox2.AppendText(">>> Total of incidences found: " + totalOUTgroups.ToString() + "\u2028");
System.IO.StreamReader file = new System.IO.StreamReader(ofd.FileName);
while ((liner = file.ReadLine()) != null)
{
foundMatch = performMatch(pattern, liner);
if (foundMatch)
{
richTextBox2.AppendText("Line: " + counter + " " + liner + "\r\n");
}
counter++;
}
}
//Will end 1
// 2 Mark echo-reply ICMP
int counter2 = 1;
string liner2;
string pattern2 = #"/^(?=.*\baccess-list\b)(?=.*\beq echo-reply\b).*$/gm";
Boolean foundMatch2;
int totalIntACLInt = Lines(ofd.FileName)
.Select(line => Regex.Matches(line, pattern2).Count)
.Sum();
if (totalIntACLInt > 0)
{
richTextBox2.SelectionFont = new Font("Courier New", 8);
richTextBox2.AppendText(" " + "\u2028");
richTextBox2.AppendText(">>> Echo-reply is not necessary: " + "\u2028");
richTextBox2.AppendText(">>> Total of incidences found: " + totalIntACLInt.ToString() + "\u2028");
System.IO.StreamReader file = new System.IO.StreamReader(ofd.FileName);
while ((liner2 = file.ReadLine()) != null)
{
foundMatch2 = performMatch(pattern2, liner2);
if (foundMatch2)
{
richTextBox2.AppendText("Line:" + counter2 + " " + liner2 + "\r\n");
}
counter2++;
}
}
If I understand your question, then the problem you're having is most likely tied to your implementation of performMatch(). Post the code for performMatch() if you want help debugging that.
As #Justin lurman pointed out, try printing out each line and line number while only iterating through the file once. If Regex.Matches(line, pattern) is already working for you, then just make use of that.
For example:
int counter = 1;
string pattern = #"access-group\s+\w+\s+out\s+interface\s+\w+";
var totalMatches = 0;
var output = new StringBuilder();
foreach(var line in Lines(ofd.FileName))
{
var matches = Regex.Matches(line, pattern).Count;
if (matches > 0)
{
totalMatches += matches;
output.AppendLine(string.Format("Line: {0} {1}", counter, line));
}
counter++;
}
if(toatlMatches > 0)
{
richTextBox2.SelectionFont = new Font("Courier New", 8);
richTextBox2.AppendText(">>> ACls installed by using access-group using the keyword OUT are NOT supported: " + "\u2028");
richTextBox2.AppendText(">>> Total of incidences found: " + totalMatches.ToString() + "\u2028");
richTextBox2.AppendText(output.ToString());
}
As a warning I haven't compiled or tested the code above, so use it as a guideline. You can certainly improve upon the code further. To start you could refactor your repeated code into methods.
Update
OK, I still don't know that I'm clear on what exactly your problem is, but I wrote out some code that should achieve what it is that I think you're trying to accomplish. While writing my code I noticed some things about the code you posted that may be causing issues for you.
Your second regex /^(?=.*\baccess-list\b)(?=.*\beq echo-reply\b).*$/gm doesn't look like a valid .NET regex, it looks like a JavaScript regex literal
You're appending text to a RichTextBox control, which has a max length property you may be exceeding. I doubt you're writing out that much text, but it's possible.
When this property is set to 0, the maximum length of the text that can be entered in the control is 64 KB of characters
- source
Here is the relevant snippet from the console app I wrote that reads a text file, line by line, and applies a collection of regexes to each line. If a match is found it stores the pertinent information about each match and then prints out its finding once all lines have been examined.
class CommonError
{
public Regex Pattern { get; private set; }
public string Message { get; private set; }
public List<KeyValuePair<int, IEnumerable<string>>> Details { get; private set; }
public CommonError(Regex pattern, string message)
{
Pattern = pattern;
Message = message;
Details = new List<KeyValuePair<int, IEnumerable<string>>>();
}
}
class Program
{
static void Main(string[] args)
{
//take a file read it once and while reading each line check if that line matches any of a slew of regexes.
//if it does match a regex then add the line number and the matching text into a collection of matches for that regex.
//at the end output all the matches by regex and the totals for each pattern. Along with printing each match also print the line it was found on.
var errorsToFind = new List<CommonError>()
{
new CommonError(new Regex(#"access-group\s+\w+\s+out\s+interface\s+\w+"), "ACls installed by using access-group using the keyword OUT are NOT supported"),
new CommonError(new Regex(#"^(?=.*\baccess-list\b)(?=.*\beq echo-reply\b).*$"), "Echo-reply is not necessary")
};
var errorsFound = FindCommonErrorsInFile(".\\test-file.txt", errorsToFind);
foreach (var error in errorsFound)
{
Console.WriteLine(error.Message);
Console.WriteLine("total incidences found: " + error.Details.Count);
error.Details.ForEach(d => Console.WriteLine(string.Format("Line {0} {1}", d.Key, string.Join(",", d.Value))));
}
}
static IEnumerable<CommonError> FindCommonErrorsInFile(string pathToFile, IEnumerable<CommonError> errorsToFind)
{
var lineNumber = 1;
foreach (var line in File.ReadLines(pathToFile))
{
foreach (var error in errorsToFind)
{
var matches = error.Pattern.Matches(line);
if(matches.Count == 0) continue;
var rawMatches = matches.Cast<Match>().Select(m => m.Value);
error.Details.Add(new KeyValuePair<int, IEnumerable<string>>(lineNumber, rawMatches));
}
lineNumber++;
}
return errorsToFind.Where(e => e.Details.Count > 0);
}
}
If you're still having issues give this code a try--this time I actually compiled it and tested it. Hope this helps.

Read a .txt file line by line, recognising specific characters

Basicaly i want to read a .txt file line by line.
As i read each line i wish to recognise any space characters between the doubles, for example
"12.1 34.478 67.9" as like something like X Y Z co-ordinates.
Once spaces are recognised, i can treat each double value independently, and can do specific calcuations to each.
currently im using this to read lines
string line = reader.ReadLine();
MessageBox.Show("Line Read: " + line + "");
I tried a array based approach like below, but the output was never successful.
char[] block = new char[3];
reader.ReadBlock(block, 0, 3);
Console.WriteLine(block);
MessageBox.Show("" + block + "");
Basic Finished working Code thanks to #Bartosz looks like
string line = reader.ReadLine();
var split = line.Split(' ');
var x = double.Parse(split[0]);
var y = double.Parse(split[1]);
var z = double.Parse(split[2]);
MessageBox.Show("X:" + x + " Y:" + y + " Z:" + z + "");
When you obtain your line, you could:
var split = line.Split(' ');
Then you can obtain each double:
var x = double.Parse(split[0]);
var y = double.Parse(split[0]);
var z = double.Parse(split[0]);
(or TryParse depending on your error handling needs, you should also check if your split is indeed of length 3).
Note: bewre of the locale settings on your OS, if your file use .as float pointing seperator, it mai fail on machine where , is set.
What about something like this?
var filename = "c:\\test.txt";
var allLines = File.ReadAllLines(filename);
var myList = new List<IEnumerable<double>>();
foreach (var line in allLines)
{
var currentLine = line.Split(' ').Select(i => double.Parse(i));
myList.Add(currentLine);
}
A little bit refactored :
var myList = File.ReadAllLines("c:\\test.txt")
.Select(line => line.Split(' ')
.Select(double.Parse))
.ToList();
http://msdn.microsoft.com/en-us/library/db5x7c0d.aspx
using System;
using System.IO;
class Test
{
public static void Main()
{
try
{
using (StreamReader sr = new StreamReader("TestFile.txt"))
{
String line = sr.ReadToEnd();
Console.WriteLine(line);
}
}
catch (Exception e)
{
Console.WriteLine("The file could not be read:");
Console.WriteLine(e.Message);
}
}
}
then split using var stringlist = string.Split('')
and double.Parse every string in stringlist

Categories