I have a function which searching a text in a string and returning me the line which contains the specific substring.Here is the function..
private static string getLine(string text,string text2Search)
{
string currentLine;
using (var reader = new StringReader(text))
{
while ((currentLine= reader.ReadLine()) != null)
{
if (currentLine.Contains(text2Search,StringComparison.OrdinalIgnoreCase))
{
break;
}
}
}
return currentLine;
}
Now in my condition i have to start searching the lines after a particular line suppose here its 10.Means have to start searching the string for specific text after 10 line.So my query is how can i add this into my current function..
Please help me.
You can use File.ReadLines method with Skip:
var line = File.ReadLines("path").Skip(10)
.SkipWhile(line => !line.Contains(text2Search,StringComparison.OrdinalIgnoreCase))
.First();
You can introduce a counter into your current code as so:
private static string getLine(string text,string text2Search)
{
string currentLine;
int endPoint = 10;
using (var reader = new StringReader(text))
{
int lineCount = 0;
while ((currentLine= reader.ReadLine()) != null)
{
if (lineCount++ >= endPoint &&
currentLine.Contains(text2Search,StringComparison.OrdinalIgnoreCase))
{
return currentLine;
}
}
}
return string.Empty;
}
Alternatively, use your current code to add all lines to a list in which you will then be able to use Selmans answer.
String.Contains doesn't have an overload taking StringComparison.OrdinalIgnoreCase
var match = text.Split(new char[]{'\n','\r'})
.Skip(10)
.FirstOrDefault(line=>line.IndexOf("", StringComparison.OrdinalIgnoreCase)>=0);
Related
I try to get my nunit TestCases by reading a textfile, which contains a TestCase per line. I'm using the TestCaseSourceAttribute in that case.
[Test, TestCaseSource("TestSelection")]
//TestMethod
public static object[] TestSelection()
{
var amountOfTestCases = GetAmountTestCases(#"path\TestCases.txt");
var result = new object[amountOfTestCases];
for (var i = 0; i < amountOfTestCases; i++)
{
result[i] = new object[] { GetTestCase(i, #"path\TestCases.txt") };
}
return result;
}
With GetAmountTestCases() I get lines of text within a textfile and GetTestCase() reads the specific line of text to get my TestCase.
public static int GetAmountTestCases(String path)
{
var lineCount = 0;
using (var reader = File.OpenText(path))
{
while (reader.ReadLine() != null)
{
lineCount++;
}
}
return lineCount;
}
public static String GetTestCase(int lineNum, String path)
{
var lineCount = 0;
String testCase = String.Empty;
using (var reader = File.OpenText(path))
{
while (reader.ReadLine() != null)
{
if (lineCount == lineNum)
{
testCase = reader.ReadLine();
}
else
{
lineCount++;
}
}
}
return testCase;
}
After building the .dll contains test modules with 'null' as content. I cant even Debug without a specific TestCase within my Code.
You have quite a complex way of going about it, the following code works for me:
[Test, TestCaseSource("GetMyFileData")]
//Method
public static string[] GetMyFileData()
{
var path = #"C:\temp\MyFile.txt";
return File.ReadAllLine(path)
.ToArray();
}
Please double check if your path is correct.
If it is a relative path to the file that is deployed on build, check if it is configured correctly: its Build Action should be something like Content and Copy to output directory should be Copy of newer or Copy always
I'm relatively new to c# and I am trying to write a program that finds the mean of every xth value in a file using Streamreader. (For example if I wanted to find the mean of every fifth value in that file)
I written some code that reads the file and splits it into a new line for each comma, and this works fine, when I try and read each specific value.
However I'm struggling to think of a way to find every specific value, such as every 4th one and then find the mean of these and output it in the same program.
static void Main(string[] args)
{
using (var reader = new StreamReader(#"file"))
{
List<string> list = new List<string>();
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split(',');
list.Add(values[0]);
}
}
}
Any suggestions or help would be greatly appreciated
Try like this;
static void Main()
{
using (var reader = new StreamReader(#"file"))
{
int lineNumber = 4;
bool streamEnded = false;
List<string> list = new List<string>();
while (!streamEnded)
{
var line = ReadSpecificLine(reader, lineNumber,out streamEnded);
if (string.IsNullOrEmpty(line))
{
continue;
}
var values = line.Split(',');
list.Add(values[0]);
}
}
}
public static string ReadSpecificLine(StreamReader sr, int lineNumber,out bool streamEnded)
{
streamEnded = false;
for (int i = 1; i < lineNumber; i++)
{
if (sr.EndOfStream)
{
streamEnded = true;
return "";
}
sr.ReadLine();
}
if (sr.EndOfStream)
{
streamEnded = true;
return "";
}
return sr.ReadLine();
}
I am trying to read from a text file that has multiple outputs from when writing to it but when I want to read from the textfile that I already outputted stuff to, I want to choose the last entry(bear in mind each entry when writing has 5 lines and I just want the line containing "Ciphered text:")
But with this it is reading the lines containing that but I cannot work how to make it show only the last entry containing the string I specified.
using System;
using System.IO;
namespace ReadLastContain
{
class StreamRead
{
static void Main(string[] args)
{
string TempFile = #"C:\Users\Josh\Desktop\text2.txt";
using (var source = new StreamReader(TempFile))
{
string line;
while ((line = source.ReadLine()) != null)
{
if (line.Contains("Ciphered Text:"))
{
Console.WriteLine(line);
}
}
}
}
}
}
I would suggest to use LINQ for better readability:
string lastCipheredText = File.ReadLines(TempFile)
.LastOrDefault(l => l.Contains("Ciphered Text:"));
it is null if there was no such line. If you can't use LINQ:
string lastCipheredText = null;
while ((line = source.ReadLine()) != null)
{
if (line.Contains("Ciphered Text:"))
{
lastCipheredText = line;
}
}
It will be overwritten always, so you automatically get the last line that contained it.
You can use Linq:
var text = File
.ReadLines(#"C:\Users\Josh\Desktop\text2.txt")
.LastOrDefault(line => line.Contains("Ciphered Text:"));
if (null != text) // if thereĀ“s a text to print out
Console.WriteLine(text);
I have some sql commands that are separated by an additional newline character:
ALTER TABLE XXX
ALTER COLUMN xxx real
ALTER TABLE YYY
ALTER COLUMN yyy real
ALTER TABLE ZZZ
ALTER COLUMN zzz real
I've tried reading the file by using an array of character separators such as the following,
new char[] { '\n', '\r'}
inside this method:
private static List<string> ReadFile(string FileName, char[] seps)
{
if (!File.Exists(FileName))
{
Console.WriteLine("File not found");
return null;
}
using (StreamReader sr = new StreamReader(FileName, Encoding.Default))
{
string content = sr.ReadToEnd();
return content.Split(seps, StringSplitOptions.RemoveEmptyEntries).ToList();
}
}
However, this doesn't seem to be working. I would like to have each command represented by a separate string. How can I do this?
Why not use File.ReadAllLines()?
private static List<string> ReadFile(string FileName)
{
if (!File.Exists(FileName))
{
Console.WriteLine("File not found");
return null;
}
var lines = File.ReadAllLines(FileName);
return lines.ToList();
}
This will automatically read and split your file by newlines.
If you want to filter out empty lines, do this:
var nonEmpty = ReadFile(path).Where(x => !string.IsNullOrEmpty(x)).ToList();
Side note, I would change your if statement to throw an exception if the file cannot be found.
if (!File.Exists(FileName))
{
throw new FileNotFoundException("Can't find file");
}
You can filter the examples. When I read them in, the empty lines had a length 1 and its char value said 131 for some reason. So I just filtered by length > 1
void Main()
{
var results = ReadFile(#"C:\temp\sql.txt", new char[]{'\n'});
Console.WriteLine(results.Count);
foreach (var result in results)
{
Console.WriteLine(result);
}
}
private static List<string> ReadFile(string FileName, char[] seps)
{
if (!File.Exists(FileName))
{
Console.WriteLine("File not found");
return null;
}
using (StreamReader sr = new StreamReader(FileName, Encoding.Default))
{
string content = sr.ReadToEnd();
return content.Split(seps, StringSplitOptions.RemoveEmptyEntries).Where (c => c.Length > 1).ToList();
}
}
Try This:
private static List<string> ReadFile(string FileName)
{
List<string> commands = new List<string>();
StringBuilder command = new StringBuilder();
if (!File.Exists(FileName))
{
Console.WriteLine("File not found");
return null;
}
foreach (var line in File.ReadLines(FileName))
{
if (!String.IsNullOrEmpty(line))
{
command.Append(line + "\n");
}
else
{
commands.Add(command.ToString());
command.Clear();
}
}
commands.Add(command.ToString());
return commands;
}
If you are sure you'll always have \r\n line endings, you can use:
var commands = content.Split(new []{"\r\n\r\n"}, StringSplitOptions.RemoveEmptyEntries);
Otherwise, try using regex:
var commands = Regex.Split(content, #"\r?\n\r?\n")
Thank you everyone for your answers. I ended up going with this helper method:
private static List<string> GetCommands(string location)
{
List<string> ret = new List<string>();
List<string> tmp = ReadFile(location, new string[] { "\r\n\r\n"});
for (int i = 0; i < tmp.Count; i++)
{
string rem = tmp[i].Replace("\r", "");
ret.Add(rem);
}
return ret;
}
As an aside, the equivalent is so much easier in Python. For example, what I'm trying to do can be expressed in these three lines:
with open('commands.txt', 'r') as f:
content = f.read()
commands = [ command for command in content.split('\n\n') ]
I usually add some strings from a text file into a list or array line by line, although I am now using "#"'s as separators in the text file. How would it be possible to read the two strings "softpedia.com" and "download.com" into a list using the two "#" signs as a breaking point? Baring in mind that there might be more or less strings inbetween the two hashes
e.g.
# Internal Hostnames
softpedia.com
download.com
# External Hostnames
Expected output:
softpedia.com
download.com
class Program
{
static void Main()
{
using (var reader = File.OpenText("test.txt"))
{
foreach (var line in Parse(reader))
{
Console.WriteLine(line);
}
}
}
public static IEnumerable<string> Parse(StreamReader reader)
{
string line;
bool first = false;
while ((line = reader.ReadLine()) != null)
{
if (!line.StartsWith("#"))
{
if (first)
{
yield return line;
}
}
else if (!first)
{
first = true;
}
else
{
yield break;
}
}
}
}
and if you wanted to just get them in a list:
using (var reader = File.OpenText("test.txt"))
{
List<string> hostnames = Parse(reader).ToList();
}
Read it into a buffer and let regex do the work.
string input = #"
# Internal Hostnames
softpedia.com
download.com
# External Hostnames
";
string pattern = #"^(?!#)(?<Text>[^\r\s]+)(?:\s?)";
Regex.Matches(input, pattern, RegexOptions.Multiline)
.OfType<Match>()
.Select (mt => mt.Groups["Text"].Value)
.ToList()
.ForEach( site => Console.WriteLine (site));
/* Outputs
softpedia.com
download.com
*/
It sounds like you want to read all of the lines in between a set of # start lines. If so try the following
List<string> ReadLines(string filePath) {
var list = new List<string>();
var foundStart = false;
foreach (var line in File.ReadAllLines(filePath)) {
if (line.Length > 0 && line[0] == '#') {
if (foundStart) {
return list;
}
foundStart = true;
} else if (foundStart) {
list.Add(line);
}
}
return line;
}