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);
Related
actualy its a basic question.
Im trying to read a CSV file and write in the console only the ones that includes the "Honda" word.
class Program
{
static void Main(string[] args)
{
var reader = new StreamReader(File.OpenRead(#"C:\Users\Vitor\Downloads\LogCombustivel.csv"));
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split(',');
if (values[0] == "Honda")
{
Console.WriteLine(line);
}
}
Console.ReadLine();
}
}
In this way, the console its not giving any results.
But the basic way to show me all the results like as follow, its working
class Program
{
static void Main(string[] args)
{
var reader = new StreamReader(File.OpenRead(#"C:\Users\Vitor\Downloads\LogCombustivel.csv"));
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
Console.WriteLine(line);
}
Console.ReadLine();
}
}
Any clues about what i'm doing wrong?
The following code will only display a line if the first element is "Honda":
if (values[0] == "Honda")
{
}
That isn't right if you want to load every element that contains "Honda". You can use Linq's Contains() method for this.
Add the namespace for Linq:
using System.Linq;
And use the following code instead, which will look in the array for any "Honda" element:
if (values.Contains("Honda"))
{
// Your Code
}
Added linq query that searches for the string Honda.
class Program
{
static void Main(string[] args)
{
var reader = new StreamReader(File.OpenRead(#"C:\Users\Vitor\Downloads\LogCombustivel.csv"));
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split(',');
if (values.Any( x=> x == "Honda"))
{
Console.WriteLine(line);
}
}
Console.ReadLine();
}
}
I have a csv file with the following data:
500000,0.005,6000
690000,0.003,5200
I need to add each line as a separate array. So 50000, 0.005, 6000 would be array1. How would I do this?
Currently my code adds each column into one element.
For example data[0] is showing 500000
690000
static void ReadFromFile(string filePath)
{
try
{
// Create an instance of StreamReader to read from a file.
// The using statement also closes the StreamReader.
using (StreamReader sr = new StreamReader(filePath))
{
string line;
// Read and display lines from the file until the end of
// the file is reached.
while ((line = sr.ReadLine()) != null)
{
string[] data = line.Split(',');
Console.WriteLine(data[0] + " " + data[1]);
}
}
}
catch (Exception e)
{
// Let the user know what went wrong.
Console.WriteLine("The file could not be read:");
Console.WriteLine(e.Message);
}
}
Using the limited data set you've provided...
const string test = #"500000,0.005,6000
690000,0.003,5200";
var result = test.Split('\n')
.Select(x=> x.Split(',')
.Select(y => Convert.ToDecimal(y))
.ToArray()
)
.ToArray();
foreach (var element in result)
{
Console.WriteLine($"{element[0]}, {element[1]}, {element[2]}");
}
Can it be done without LINQ? Yes, but it's messy...
const string test = #"500000,0.005,6000
690000,0.003,5200";
List<decimal[]> resultList = new List<decimal[]>();
string[] lines = test.Split('\n');
foreach (var line in lines)
{
List<decimal> decimalValueList = new List<decimal>();
string[] splitValuesByComma = line.Split(',');
foreach (string value in splitValuesByComma)
{
decimal convertedValue = Convert.ToDecimal(value);
decimalValueList.Add(convertedValue);
}
decimal[] decimalValueArray = decimalValueList.ToArray();
resultList.Add(decimalValueArray);
}
decimal[][] resultArray = resultList.ToArray();
That will give the exact same output as what I've done with the first example
If you may use a List<string[]> you do not have to worry about the array length.
In the following example, the variable lines will be a list arrays, like:
["500000", "0.005", "6000"]
["690000", "0.003", "5200"]
static void ReadFromFile(string filePath)
{
try
{
// Create an instance of StreamReader to read from a file.
// The using statement also closes the StreamReader.
using (StreamReader sr = new StreamReader(filePath))
{
List<string[]> lines = new List<string[]>();
string line;
// Read and display lines from the file until the end of
// the file is reached.
while ((line = sr.ReadLine()) != null)
{
string[] splittedLine = line.Split(',');
lines.Add(splittedLine);
}
}
}
catch (Exception e)
{
// Let the user know what went wrong.
Console.WriteLine("The file could not be read:");
Console.WriteLine(e.Message);
}
}
While other have split method, I will have a more "scolar"-"specified" method.
You have some Csv value in a file. Find a name for this object stored in a Csv, name every column, type them.
Define the default value of those field. Define what happends for missing column, and malformed field. Header?
Now that you know what you have, define what you want. This time again: Object name -> Property -> Type.
Believe me or not, the simple definition of your input and output solved your issue.
Use CsvHelper to simplify your code.
CSV File Definition:
public class CsvItem_WithARealName
{
public int data1;
public decimal data2;
public int goodVariableNames;
}
public class CsvItemMapper : ClassMap<CsvItem_WithARealName>
{
public CsvItemMapper()
{ //mapping based on index. cause file has no header.
Map(m => m.data1).Index(0);
Map(m => m.data2).Index(1);
Map(m => m.goodVariableNames).Index(2);
}
}
A Csv reader method, point a document it will give your the Csv Item.
Here we have some configuration: no header and InvariantCulture for decimal convertion
private IEnumerable<CsvItem_WithARealName> GetCsvItems(string filePath)
{
using (var fileReader = File.OpenText(filePath))
using (var csvReader = new CsvHelper.CsvReader(fileReader))
{
csvReader.Configuration.CultureInfo = CultureInfo.InvariantCulture;
csvReader.Configuration.HasHeaderRecord = false;
csvReader.Configuration.RegisterClassMap<CsvItemMapper>();
while (csvReader.Read())
{
var record = csvReader.GetRecord<CsvItem_WithARealName>();
yield return record;
}
}
}
Usage :
var filename = "csvExemple.txt";
var items = GetCsvItems(filename);
I have a task to create an UI to run methods from scripts.
I made a method that shows the names of Methods from Script, and on the UI there is a checkbox next to them.
I have a problem that when I click on the checkbox, I do not know to invite only a pieces of code of this method.
private void GetAllDSCConfigurationName(string psFile, DSCTreeViewItemFolder item)
{
var file = new DSCTreeViewItemScipt() { Script = psFile };
item.AddChild(file);
try
{
using (StreamReader sr = new StreamReader(psFile))
{
string line;
while ((line = sr.ReadLine()) != null)
{
if (line.StartsWith("Configuration"))
{
file.AddChild(new DSCTreeViewItemConfiguration() { ConfigurationName = line });
}
}
}
}
catch (Exception e)
{
Console.WriteLine("The file could not be read:");
Console.WriteLine(e.Message);
}
}
You can check in the same if statement:
if(line.StartsWith("Configuration") && line.Contains("LogOff"))
{
// do your stuff
break; // cause you don't need to look for other methods
}
If you have a name of your method from UI you can pass it to Contains method.
Also you can improve a bit your code:
string allLines = sr.ReadToEnd();
string configurations = allLines.Split("Configuration");
string methodToCall = configurations.FirstOrDefault(conf => conf.Contains("LogOff")); // or you can pass name of your method from parameter
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);
I am new to C# and to programming in general. I am trying to read the contents of a txt file and load them to an arraylist. I can't figure out what condition to use in my while loop.
void LoadArrayList()
{
TextReader tr;
tr = File.OpenText("C:\\Users\\Maattt\\Documents\\Visual Studio 2010\\Projects\\actor\\actors.txt");
string Actor;
while (ActorArrayList != null)
{
Actor = tr.ReadLine();
if (Actor == null)
{
break;
}
ActorArrayList.Add(Actor);
}
}
void LoadArrayList()
{
TextReader tr;
tr = File.OpenText("C:\\Users\\Maattt\\Documents\\Visual Studio 2010\\Projects\\actor\\actors.txt");
string Actor;
Actor = tr.ReadLine();
while (Actor != null)
{
ActorArrayList.Add(Actor);
Actor = tr.ReadLine();
}
}
You can do it with just 2 lines of code
string[] Actor = File.ReadAllLines("C:\\Users\\Maattt\\Documents\\Visual Studio 2010\\Projects\\actor\\actors.txt");
ArrayList list = new ArrayList(Actor);
This is how it should be
void LoadArrayList()
{
string[] lines = System.IO.File.ReadAllLines(#"C:\Users\Maattt\Documents\Visual Studio 2010\Projects\actor\actors.txt");
// Display the file contents by using a foreach loop.
foreach (string Actor in lines)
{
ActorArrayList.Add(Actor);
}
}
Just rearrange it like this:
Actor = tr.ReadLine();
while (Actor != null)
{
ActorArrayList.Add(Actor);
Actor = tr.ReadLine();
}
If you look at the documentation for the TextReader.ReadLine method, you'll see that it returns either a string, or null if there are no more lines. So, what you can do is loop and check null against the results of the ReadLine method.
while(tr.ReadLine() != null)
{
// We know there are more items to read
}
With the above, though, you're not capturing the result of ReadLine. So you need to declare a string to capture the result and to use inside the while loop:
string line;
while((line = tr.ReadLine()) != null)
{
ActorArrayList.Add(line);
}
Also, I would suggest using a generic list, such as List<T> instead of the non-generic ArrayList. Using something like List<T> gives you more type safety and reduces the possibility of invalid assignments or casts.