Both the below cases are not working. I want to extract from a text file a certain part that I can choose by specifying the start of the line and end.
case looks like this:
using (StreamReader reader = new StreamReader("C:/Users/david/Desktop/20180820.log",Encoding.Default))
{
Console.WriteLine("From:");
string a = (Console.ReadLine());
Console.WriteLine(" To:");
string b = (Console.ReadLine());
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
if (line.StartsWith(a) && (line.EndsWith(b)))
{
Console.WriteLine(line);
}
}
}
case with regex
string line;
while ((line = reader.ReadLine()) != null)
{
string regex12 = a.ToString() + b.ToString();
Match m = Regex.Match(line,regex12);
string s = Regex.Match(line, regex12).Groups[0].Value;
Console.WriteLine(s);
if (m.Success)
{
string n = m.Groups[0].Value;
Console.WriteLine(n);
}
}
If anyone can solve my problem, I will be very thankful.
Update Based on Comments
From the comments, it looks like you are attempting to parse a specifically formatted file, and would better benefit with a non-generic solution. Also, it looks like the text is split across multiple lines, rather than single line as you had shared in comments.
[00:09:08.870] text...
[00:09:08.886] text...
[00:09:08.886] text...
[00:09:10.448] text...
[00:09:10.464] text...
[00:09:10.526] text...
[00:09:11.886] text...
[00:09:11.901] text...
[00:09:11.980] text...
[00:09:12.026] text...
In this case, you could use the following.
var reader = File.OpenText(filePAth);
var startLineDetected = false;
var startWord = "00:09:08.870";
var endWord = "00:09:12.026";
var strBuilder = new StringBuilder();
while(!reader.EndOfStream)
{
var newLine = reader.ReadLine();
if(newLine.Contains($"[{startWord}") && !startLineDetected)
{
startLineDetected = true;
}
if(newLine.Contains($"[{endWord}") && startLineDetected)
{
strBuilder.AppendLine(newLine);
break;
}
if(startLineDetected)
{
strBuilder.AppendLine(newLine);
}
}
var resultData = strBuilder.ToString();
Original Answer based on OP
You could do the following.
var reader = File.OpenText(filePAth);
var startLineDetected = false;
var startWord = // startWord;
var endWord = // endWord;
var strBuilder = new StringBuilder();
while(!reader.EndOfStream)
{
var newLine = reader.ReadLine();
if(newLine.Contains(startWord) && !startLineDetected)
{
startLineDetected = true;
newLine = newLine.Substring(newLine.IndexOf(startWord));
}
if(newLine.Contains(endWord) && startLineDetected)
{
newLine = newLine.Substring(0,newLine.IndexOf(endWord) + endWord.Length);
strBuilder.Append(newLine);
break;
}
if(startLineDetected)
{
strBuilder.Append(newLine);
}
}
var resultData = strBuilder.ToString();
Related
I have the following vCard text, my purpose is to parse the text to a list of vCard objects
BEGIN:VCARD
VERSION:2.1
N:Kleit;Ali;;;
FN:Ali Kleit
TEL;CELL:70101010
END:VCARD
BEGIN:VCARD
VERSION:2.1
N:Kleit;Saeed;;;
FN:Saeed Kleit
TEL;CELL:03494949
END:VCARD
the following is my code to do that
List<string> cards = new List<string>();
if (text != null)
{
while (text.Length != 0)
{
int idx_begin = text.IndexOf("BEGIN:VCARD");
if (idx_begin == -1)
break;
string endToken = "END:VCARD";
int idx_end = text.IndexOf(endToken);
if (idx_end == -1)
break;
string card = text.Substring(idx_begin, idx_end + endToken.Length);
text = text.Substring(idx_end + endToken.Length);
cards.Add(card);
}
}
next, using Thought.vCards.vCard .NET Library parser to parse each found vCard text
List<Thought.vCards.vCard> vCards = new List<Thought.vCards.vCard>();
List<string> failedStrings = new List<string>();
foreach (string card in cards)
{
using (TextReader sr = new StringReader(card))
{
var vCard = new Thought.vCards.vCard(sr);
if (vCard == null)
{
failedStrings.Add(card);
continue;
}
vCards.Add(vCard);
}
}
Is there any more efficient way to accomplish that knowing that the text might be in an incorrect format?
Something like this?
var vcards = File.ReadAllText(Path.Combine(Path.GetDirectoryName(Util.CurrentQueryPath), "Contacts.vcf"));
var vcardRe = new Regex(#"BEGIN:VCARD\s+(.+?)\s+END:VCARD", RegexOptions.Compiled | RegexOptions.Singleline);
var res = vcardRe.Matches(vcards)
.Cast<Match>()
.Select(x => x.Groups[0].Captures.Cast<Capture>().Select(c => c.Value).Last())
;
List<Thought.vCards.vCard> vCards = new List<Thought.vCards.vCard>();
List<string> failedStrings = new List<string>();
foreach(string card in res)
{
using (TextReader sr = new StringReader(card))
{
var vCard = new Thought.vCards.vCard(sr);
if (vCard == null)
{
failedStrings.Add(card);
continue;
}
vCards.Add(vCard);
}
}
vCards.Dump();
I used following code snippet to replace text
private void textBox1_TextChanged(object sender, EventArgs e)
{
string A = textBox1.Text.Trim();
string B = textBox1.Text.Trim();
A = A.Replace("AB", "CD");
A = A.Replace("GF", "HI");
A = A.Replace("AC", "QW");
A = A.Replace("VB", "GG");
textBox2.Text = (A);
}
but i wants to ignore this replace technique within || these symbol.As a example my code do this
when i type AB GF in a txtbox1,txtbox2 replace as following CD HI.
Now i need when i type |AB GF| in txtbox1 ,txtbox2 replace as AB GF
i used this code to do this
textBox2.Text = ((B.Contains("|")) ? B.Replace("|", "") : A);
but this isn't work,after | this symbol all containing things in txtbox1 not replaced,how can i do this
Per your comments, you will want to split your string on the spaces prior to doing the replacement. Afterwards you will join it all back together. This is pretty easy with Linq.
public Main()
{
var strings = new string[]{ "AB GF", "|AB| GF" };
foreach (var s in strings)
Console.WriteLine(String.Join(" ", s.Split(' ').Select(x => ReplaceText(x))));
}
string ReplaceText(string text)
{
if (text.Contains("|"))
return text.Replace("|", String.Empty);
else
{
text = text.Replace("AB", "CD");
text = text.Replace("GF", "HI");
text = text.Replace("AC", "QW");
return text.Replace("VB", "GG");
}
}
Prints:
CD HI
AB HI
Looking at your code. If you need to avoid a ReplaceText method. Something like this would work.
string A = textBox1.Text.Trim();
var subStrings = A.Split(' ');
for (int i = 0; i < subStrings.Count(); i++)
{
if (subStrings[i].Contains("|"))
subStrings[i] = subStrings[i].Replace("|", String.Empty);
else
{
subStrings[i] = subStrings[i].Replace("AB", "CD");
subStrings[i] = subStrings[i].Replace("GF", "HI");
subStrings[i] = subStrings[i].Replace("AC", "QW");
subStrings[i] = subStrings[i].Replace("VB", "GG");
}
}
textBox2.Text = String.Join(" ", subStrings);
I am trying to search my text-file for a sentence by date and by name. Then I want this sentence to load it to some textboxes in my form. I am new in VS but I know some things about C.
I have came up with this code:
string pattern = dateTimePicker1Is.Text;
string pattern1 = _txtNameIs.Text;
IList<string> result = new List<string>();
using (var reader = new StreamReader(#"C:\Users\user\Desktop\Testet System\isto.txt"))
{
string currentLine;
while ((currentLine = reader.ReadLine()) != null)
{
if (currentLine.Contains(pattern))
{
if (currentLine.Contains(pattern1))
{
result.Add(currentLine);
string[] tempArray = currentLine.Split(',');
_txtNameIs.Text = tempArray[0];
_txtSurnameIs.Text = tempArray[1];
_txtApokxT.Text = tempArray[2];
_txtApoktT.Text = tempArray[3];
_txtEpanxT.Text = tempArray[4];
_txtEpandT.Text = tempArray[5];
_txtApokkT.Text = tempArray[6];
_txtEpankT.Text = tempArray[7];
_txtApoksT.Text = tempArray[8];
_txtEpansT.Text = tempArray[9];
_txtGenSun.Text = tempArray[10];
break;
}
else
{
MessageBox.Show("There are no records!");
}
}
}
}
When I press the search button it loads me all the data that I need, but if I have the same name and different date a message-box pops up and tells 'there are no records'.
I believe there is better way doing this:
string pattern = dateTimePicker1Is.Text;
string pattern1 = _txtNameIs.Text;
string pathToFile = #"C:\Users\user\Desktop\Testet System\isto.txt";
List<string> result = new List<string>();
foreach (var line in File.ReadAllLines(pathToFile))
{
if (line.Contains(pattern) && line.Contains(pattern1))
{
result.Add(line);
string[] tempArray = line.Split(',');
if(tempArray.Length >= 11)
{
_txtNameIs.Text = tempArray[0];
_txtSurnameIs.Text = tempArray[1];
_txtApokxT.Text = tempArray[2];
_txtApoktT.Text = tempArray[3];
_txtEpanxT.Text = tempArray[4];
_txtEpandT.Text = tempArray[5];
_txtApokkT.Text = tempArray[6];
_txtEpankT.Text = tempArray[7];
_txtApoksT.Text = tempArray[8];
_txtEpansT.Text = tempArray[9];
_txtGenSun.Text = tempArray[10];
break;
}
}
}
It is better to show message if the list count is 0.
I think your There are no records error should happen
AFTER the while statement
IF no matches were found
Right?
So put if there was a match found in a bool, and then after the while if !IsMatchFound then throw your error.
I have a textfile with blogposts, each blogpost is divided in a header and content shown below
#Header
A post
#Content
My content goes here...
#Header
Another post
#Content
My content goes here...
Now I want to grab all the headers, the text that comes after #Header and before #Content and put that in a List<>. How can I do that?
This is what I have come up with so far:
var headers = new List<string>();
using (StreamReader reader = new StreamReader(Path))
{
string line;
while ((line = reader.ReadLine()) != null)
{
headers.AddRange(line)
.SkipWhile(l => l != "#Header")
.Skip(1)
.TakeWhile(l => !l.StartsWith("#"))
.ToList();
}
}
Linq is preferred.
Untested, but how about something like this (assuming the file isn't that long):
var headers = reader.ReadToEnd()
.Split(new[]{"#Header"}, StringSplitOptions.RemoveEmptyEntries)
.Select(x => x.Split(new[]{"#Content"})[0].Trim())
.ToList();
Or, reading line-by-line, if the file is long:
List<string> headers = new List<string>();
string line;
bool inHeader = false;
StringBuilder header = new StringBuilder();
while((line = reader.ReadLine()) != null)
{
if(!inHeader)
{
if (line == "#Header") inHeader = true;
}
else if (line == "#Content")
{
headers.Add(header.ToString());
header.Clear();
inHeader = false;
}
else
{
header.AppendLine(line);
}
}
if(inHeader) headers.Add(header.ToString());
assuming your file can be very long:
bool header = false;
while(line = reader.readLine())
{
if(header) headers.add(line);
if(String.Compare(line,"#Header", false) == 0)
{
header = true;
}
else if(String.Compare(line,"#Content", false) == 0)
{
header = false;
}
}
Of course this assumes that your headers are always exactly one line long (otherwise one header can result in multiple entries in your headers variable).
You can use regex with LINQ
string contents = File.ReadAllText("yourTextFile.txt");
List<string> header=Regex.Matches(contents,#"#Header\s*(.*?)\s*#",RegexOptions.IgnoreCase | RegexOptions.Singleline)
.Cast<Match>()
.Select(x=>x.Groups[1].Value).ToList<string>();
I have strings and each contain a value of RowKey stored like this:
data-RowKey=029
This occurs only once in each file. Is there some way I can get the number out with a C# function or do I have to write some kind of select myself. I have a team mate who suggested linq but I'm not sure if this even works on strings and I don't know how I could use this.
Update:
Sorry I changed this from file to string.
Linq does not really help you here. Use a regular expression to extract the number:
data-Rowkey=(\d+)
Update:
Regex r = new Regex(#"data-Rowkey=(\d+)");
string abc = //;
Match match = r.Match(abc);
if (match.Success)
{
string rowKey = match.Groups[1].Value;
}
Code:
public string ExtractRowKey(string filePath)
{
Regex r = new Regex(#"data-Rowkey=(\d+)");
using (StreamReader reader = new StreamReader(filePath))
{
string line;
while ((line = reader.ReadLine()) != null)
{
Match match = r.Match(line);
if (match.Success) return match.Groups[1].Value;
}
}
}
Assuming that it only exists once in a file, i would even throw an exception otherwise:
String rowKey = null;
try
{
rowKey = File.ReadLines(path)
.Where(l => l.IndexOf("data-RowKey=") > -1)
.Select(l => l.Substring(12 + l.IndexOf("data-RowKey=")))
.Single();
}
catch (InvalidOperationException) {
// you might want to log this exception instead
throw;
}
Edit: The simple approach with a string, take the first occurence which is always of length 3:
rowKey = text.Substring(12 + text.IndexOf("data-RowKey="), 3);
Assuming following
File must contain data-Row (with exact match including case)
Number length is 3
Following is the code snippet
var fileNames = Directory.GetFiles("rootDirPath");
var tuples = new List<Tuple<String, int>>();
foreach(String fileName in fileNames)
{
String fileData =File.ReadAllText(fileName) ;
int index = fileData.IndexOf("data-RowKey=");
if(index >=0)
{
String numberStr = fileData.Substring(index+12,3);// ASSUMING data-RowKey is always found, and number length is always 3
int number = 0;
int.TryParse(numberStr, out number);
tuples.Add(Tuple.Create(fileName, number));
}
}
Regex g = new Regex(#"data-RowKey=(?<Value>\d+)");
using (StreamReader r = new StreamReader("myFile.txt"))
{
string line;
while ((line = r.ReadLine()) != null)
{
Match m = g.Match(line);
if (m.Success)
{
string v = m.Groups["Value"].Value;
// ...
}
}
}