Csharp substring text and add it to list - c#

I have file.txt like:
EDIT: I didn't wrote but this is important i guess- In file.txt there can be others lines!
folder=c:\user;c:\test;c:\something;
I need to add one path like one list item (List<string> Folders).
So my List should looks like:
Folders[0] = c:\user
Folders[1] = c:\test
etc. (without text "folder=" which starts line in file.txt and ";" which means end of path).
file can contain much more paths.
I did something like this:
using (FileStream fss = new FileStream(path, FileMode.Open))
{
using (StreamReader sr = new StreamReader(fss))
{
while (sr.EndOfStream == false)
{
string line = sr.ReadLine();
if(line.StartsWith("folders"))
{
int index = line.IndexOf("=");
int index1 = line.IndexOf(";");
string folder = line.Substring(index + 1, index1 - (index + 1));
Folders.Add(folder);
Now in List Folders i have first path but what now? I can't go ahead :(

using(var sr = new StreamReader(path))
{
var folders = sr.ReadToEnd()
.Split(new char[]{';','\n','\r'}, StringSplitOptions.RemoveEmptyEntries)
.Select(o => o.Replace("folder=",""))
.ToArray();
Folders.AddRange(folders);
}

You can try following code, using File.ReadAllText
string Filepath = "c:\abc.txt";
string filecontent = File.ReadAllText(Filepath);
string startingString = "=";
var startIndex = filecontent.IndexOf(startingString);
filecontent = filecontent.Substring(startIndex + 1, filecontent.Length - startIndex - 2);
List<String> folders = filecontent.Split(';').ToList();

Here's a simple example:
List<String> Folders = new List<string>();
private void button1_Click(object sender, EventArgs e)
{
string path = #"C:\Users\mikes\Documents\SomeFile.txt";
string folderTag = "folder=";
using (FileStream fss = new FileStream(path, FileMode.Open))
{
using (StreamReader sr = new StreamReader(fss))
{
while (!sr.EndOfStream)
{
string line = sr.ReadLine();
if (line.StartsWith(folderTag))
{
line = line.Substring(folderTag.Length); // remove the folderTag from the beginning
Folders.AddRange(line.Split(";".ToCharArray(), StringSplitOptions.RemoveEmptyEntries));
}
}
}
}
foreach(string folder in Folders)
{
Console.WriteLine(folder);
}
}
I'd use this approach if you're going to read line by line, and do something else based on what each line starts with. In that case you could add different else if(...) blocks:
if (line.StartsWith(folderTag))
{
line = line.Substring(folderTag.Length); // remove the folderTag from the beginning
Folders.AddRange(line.Split(";".ToCharArray(), StringSplitOptions.RemoveEmptyEntries));
}
else if(line.StartsWith("parameters="))
{
// do something different with a line starting with "parameters="
}
else if (line.StartsWith("unicorns="))
{
// do something else different with a line starting with "unicorns="
}

Related

c# load txt file and split it to X files based on number of lines

this is the code that i've written so far...
it doesnt do the job except re-write every line on the same file over and over again...
*RecordCntPerFile = 10K
*FileNumberName = 1 (file number one)
*Full File name should be something like this: 1_asci_split
string FileFullPath = DestinationFolder + "\\" + FileNumberName + FileNamePart + FileExtension;
using (System.IO.StreamReader sr = new System.IO.StreamReader(SourceFolder + "\\" + SourceFileName))
{
for (int i = 0; i <= (RecordCntPerFile - 1); i++)
{
using (StreamWriter sw = new StreamWriter(FileFullPath))
{
{ sw.Write(sr.Read() + "\n"); }
}
}
FileNumberName++;
}
Dts.TaskResult = (int)ScriptResults.Success;
}
If I understood correctly, you want to split a big file in smaller files with maximum of 10k lines. I see 2 problems on your code:
You never change the FullFilePath variable. So you will always rewrite on the same file
You always read and write the whole source file to the target file.
I rewrote your code to fit the behavior I said earlier. You just have to modify the strings.
int maxRecordsPerFile = 10000;
int currentFile = 1;
using (StreamReader sr = new StreamReader("source.txt"))
{
int currentLineCount = 0;
List<string> content = new List<string>();
while (!sr.EndOfStream)
{
content.Add(sr.ReadLine());
if (++currentLineCount == maxRecordsPerFile || sr.EndOfStream)
{
using (StreamWriter sw = new StreamWriter(string.Format("file{0}.txt", currentFile)))
{
foreach (var line in content)
sw.WriteLine(line);
}
content = new List<string>();
currentFile++;
currentLineCount = 0;
}
}
}
Of course you can do better than that, as you don't need to create that string and do that foreach loop. I just made this quick example to give you the idea. To improve the performance is up to you

StreamWriter: Starting and ending on a specific line number

I would like to ask some tips and help on a reading/writing part of my C#.
Situation:
I have to read a CSV file; - OK
If the CSV file name starts with "Load_", I want to write on another CSV the data from line 2 to the last one;
If the CSV file name starts with "RO_", I want to write on 2 different CSVs, 1 with the line 1 to 4 and the other 4 to the last one;
What I have so far is:
public static void ProcessFile(string[] ProcessFile)
{
// Keeps track of your current position within a record
int wCurrLine = 0;
// Number of rows in the file that constitute a record
const int LINES_PER_ROW = 1;
int ctr = 0;
foreach (string filename in ProcessFile)
{
var sbText = new System.Text.StringBuilder(100000);
int stop_line = 0;
int start_line = 0;
// Used for the output name of the file
var dir = Path.GetDirectoryName(filename);
var fileName = Path.GetFileNameWithoutExtension(filename);
var ext = Path.GetExtension(filename);
var folderbefore = Path.GetFullPath(Path.Combine(dir, #"..\"));
var lineCount = File.ReadAllLines(#filename).Length;
string outputname = folderbefore + "output\\" + fileName;
using (StreamReader Reader = new StreamReader(#filename))
{
if (filename.Contains("RO_"))
{
start_line = 1;
stop_line = 5;
}
else
{
start_line = 2;
stop_line = lineCount;
}
ctr = 0;
while (!Reader.EndOfStream && ctr < stop_line)
{
// Add the text
sbText.Append(Reader.ReadLine());
// Increment our current record row counter
wCurrLine++;
// If we have read all of the rows for this record
if (wCurrLine == LINES_PER_ROW)
{
// Add a line to our buffer
sbText.AppendLine();
// And reset our record row count
wCurrLine = 0;
}
ctr++;
} // end of the while
}
int total_lenght = sbText.Length
// When all of the data has been loaded, write it to the text box in one fell swoop
using (StreamWriter Writer = new StreamWriter(dir + "\\" + "output\\" + fileName + "_out" + ext))
{
Writer.Write.(sbText.);
}
} // end of the foreach
} // end of ProcessFile
I was thinking about using the IF/ELSE: "using (StreamWriter Writer = new StreamWriter(dir + "\" + "output\" + fileName + "_out" + ext))" part. However, I am not sure how to pass, to StreamWriter, to only write from/to a specific line number.
Any Help is welcome! If I am missing some information, please, let me know (I am pretty new on stackoverflow).
Thank you.
Code is way too complicated
using System.Collections.ObjectModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace ConsoleApplication57
{
class Program
{
static void Main(string[] args)
{
}
public static void ProcessFile(string[] ProcessFile)
{
foreach (string filename in ProcessFile)
{
// Used for the output name of the file
var dir = Path.GetDirectoryName(filename);
var fileName = Path.GetFileNameWithoutExtension(filename);
var ext = Path.GetExtension(filename);
var folderbefore = Path.GetFullPath(Path.Combine(dir, #"..\"));
var lineCount = File.ReadAllLines(#filename).Length;
string outputname = folderbefore + "output\\" + fileName;
using (StreamWriter Writer = new StreamWriter(dir + "\\" + "output\\" + fileName + "_out" + ext))
{
int rowCount = 0;
using (StreamReader Reader = new StreamReader(#filename))
{
rowCount++;
string inputLine = "";
while ((inputLine = Reader.ReadLine()) != null)
{
if (filename.Contains("RO_"))
{
if (rowCount <= 4)
{
Writer.WriteLine(inputLine);
}
if (rowCount == 4) break;
}
else
{
if (rowCount >= 2)
{
Writer.WriteLine(inputLine);
}
}
} // end of the while
Writer.Flush();
}
}
} // end of the foreach
} // end of ProcessFile
}
}
You can use LINQ to Take and Skip lines.
public abstract class CsvProcessor
{
private readonly IEnumerable<string> processFiles;
public CsvProcessor(IEnumerable<string> processFiles)
{
this.processFiles = processFiles;
}
protected virtual IEnumerable<string> GetAllLinesFromFile(string fileName)
{
using(var stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
using(var reader = new StreamReader(stream))
{
var line = String.Empty;
while((line = reader.ReadLine()) != null)
{
yield return line;
}
}
}
protected virtual void ProcessFiles()
{
var sb1 = new StringBuilder();
var sb2 = new StringBuilder();
foreach(var file in this.processFiles)
{
var fileName = Path.GetFileNameWithoutExtension(file);
var lines = GetAllLinesFromFile(file);
if(fileName.StartsWith("RO_", StringComparison.InvariantCultureIgnoreCase))
{
sb1.AppendLine(lines.Take(4)); //take only the first four lines
sb2.AppendLine(lines.Skip(4).TakeWhile(s => !String.IsNullOrEmpty(s))); //skip the first four lines, take everything else
}
else if(fileName.StartsWith("Load_", StringComparison.InvariantCultureIgnoreCase)
{
sb2.AppendLine(lines.Skip(1).TakeWhile(s => !String.IsNullOrEmpty(s)));
}
}
// now write your StringBuilder objects to file...
}
protected virtual void WriteFile(StringBuilder sb1, StringBuilder sb2)
{
// ... etc..
}
}

C# compare 2 files substrings for matches

I am trying to find a way to compare some text in 2 files and if a match is found .
Here are examples of the files;
'File A'
ex1,TEXAS,24
ex2,MIAMI,78
ex3,ATLANTA,56
ex4,NY,90
...
'File B'
ex1,JHON,1110
exA,DAVID,1060
exB,CATHY,230
ex4,ROBERT,1200
...
Using my 2 example files, I want to search them both and find matches(
ex1,TEXAS,24
&
ex4,NY,90
)??!
Here is my try
private void button4_Click(object sender, EventArgs e)
{
string fileA, fileB, fileC;
fileA = textBox1.Text;
fileB = textBox2.Text;
fileC = "result.txt";
string alphaFilePath = fileA;
List<string> alphaFileContent = new List<string>();
using (FileStream fs = new FileStream(alphaFilePath, FileMode.Open))
using (StreamReader rdr = new StreamReader(fs))
{
while (!rdr.EndOfStream)
{
}
}
string betaFilePath = fileB;
StringBuilder sb = new StringBuilder();
using (FileStream fs = new FileStream(betaFilePath, FileMode.Open))
using (StreamReader rdr = new StreamReader(fs))
{
while (!rdr.EndOfStream)
{
string[] betaFileLine = rdr.ReadLine().Split(Convert.ToChar(","));
}
}
using (FileStream fs = new FileStream(fileC, FileMode.Create)){
using (StreamWriter writer = new StreamWriter(fs))
{
writer.Write(sb.ToString());
}
} foreach (var item in alphaFileContent)
{
if (item.StartsWith(betaFileLine[0]))
{
sb.AppendLine(String.Format("{0}", betaFileLine[0]));
}
}
}
You can get all the lines of a file into an array using File.ReadAllLines:
var alphaFileContents = File.ReadAllLines(fileA);
In your code, you are checking to see which items from file A StartWith the same text as an item from file B up to the first comma. We can get all the prefixes (line contents up to the first comma) from fileB by using string.Split(',')[0], which splits the string into an array on the comma character, and then returns the first item (at index 0):
var betaFilePrefixes = File.ReadAllLines(fileB).Select(line => line.Split(',')[0]);
Now, we can find the similar items by getting all items in fileA that start with an item from fileB. The Where clause below says, "where any alpha item starts with an item in betaFilePrefixes:
var similarItems = alphaFileContents
.Where(alpha => betaFilePrefixes.Any(beta => alpha.StartsWith(beta)));
Then, you can write all the matching lines to the results file using File.WriteAllLines:
File.WriteAllLines(fileC, similarItems);
So, to put it all together, you can do this:
private void button4_Click(object sender, EventArgs e)
{
var fileA = textBox1.Text;
var fileB = textBox2.Text;
var fileC = "result.txt";
// Read the alpha file contents into a list
var alphaFileContents = File.ReadAllLines(fileA);
// Read each line of the beta file, and select the first part
// (up to the first comma) into a list
var betaFilePrefixes = File.ReadAllLines(fileB).Select(line => line.Split(',')[0]);
// Get all alpha lines that start with an item in the beta list
var similarItems = alphaFileContents
.Where(alpha => betaFilePrefixes.Any(alpha.StartsWith));
// Write the lines to our result file
File.WriteAllLines(fileC, similarItems);
}
var matches = File.ReadAllText(fileA).Split(',')
.Intersect(File.ReadAllText(fileB).Split(','));

Read text file and split it over

So, I know my headline is a bit confusing, I will explain.
My code looks like this:
string filename = "C:\\C#\\maplist.txt"; // please put the text file path.
string filename2 = "C:\\C#\\zemaplist.txt";
string map;
StreamReader sr = new StreamReader(filename);
StreamWriter sw = new StreamWriter(filename2);
List<string> maps = new List<string> { };
while ((map = sr.ReadLine()) != null)
{
maps.Add(map);
}
sr.Close();
for (int i = 0; i < maps.Count; i++)
{
Console.WriteLine(maps[i]);
sw.WriteLine(maps[i]);
}
sw.Close();
and what i need to do is when the code read a new line, in my line there is
"Hey,Hey"
I want to split the , from each other so I can take both of them as other parameters, so that the first Hey will be added to maps and the other hey will be maps2,
How can I do that?
You can use Split() function to Split the given String based on delimiter.
Try This:
while ((map = sr.ReadLine()) != null)
{
maps.Add(map.Split(',')[0].Trim());
maps2.Add(map.Split(',')[1].Trim());
}
Simple Code:
using System.IO;
string filename = "C:\\C#\\maplist.txt"; // please put the text file path.
string filename2 = "C:\\C#\\zemaplist.txt";
string map;
StreamWriter sw = new StreamWriter(filename2);
List<string> maps = new List<string> { };
List<string> maps2 = new List<string> { };
String [] allLines = File.ReadAllLines(filename);
foreach(String line in allLines)
{
maps.Add(line.Split(',')[0].Trim());
maps2.Add(line.Split(',')[1].Trim());
}
for (int i = 0; i < maps.Count; i++)
{
Console.WriteLine(maps[i]);
sw.WriteLine(maps[i]);
}
sw.Close();
Solution 2:
String mapItem1="";
String mapItem2="";
if(maps.Count == maps2.Count)
{
for(int i=0;i<maps.Count;i++)
{
mapItem1=maps[i];
mapItem2=maps2[i];
}
}
while ((map = sr.ReadLine()) != null)
{
string[] split = map.Split(',');
//First Hey would be split[0], second Hey would be split[1]
maps.Add(split[0].Trim());
maps2.Add(split[1].Trim());
}
The Split method should help you out with that.
If you want to trim leading whitespace characters, you can use the .Trim() method on a string.
Use Split().
string heys = "Hey,Hey";
string[] splitArray = heys.Split(',');
Then you have:
splitArray[0] = "Hey";
splitArray[1] = "Hey";
Why even bother reading line by line? Read the entire file, replace the new line chars for a "," (to prevent last and first elements from different lines to be treated as one), and loop through a clean string.
string fileContent = Regex.Replace(File.ReadAllText("test.txt"), #"\r", ",");
List<string> mapList = new List<string>();
foreach (string map in Regex.Split(fileContent.Replace(#"\s+", ""), ","))
{
mapList.Add(map.Trim());
}

Using StreamReader to check if a file contains a string

I have a string that is args[0].
Here is my code so far:
static void Main(string[] args)
{
string latestversion = args[0];
// create reader & open file
using (StreamReader sr = new StreamReader("C:\\Work\\list.txt"))
{
while (sr.Peek() >= 0)
{
// code here
}
}
}
I would like to check if my list.txt file contains args[0]. If it does, then I will create another process StreamWriter to write a string 1 or 0 into the file. How do I do this?
Are you expecting the file to be particularly big? If not, the simplest way of doing it would be to just read the whole thing:
using (StreamReader sr = new StreamReader("C:\\Work\\list.txt"))
{
string contents = sr.ReadToEnd();
if (contents.Contains(args[0]))
{
// ...
}
}
Or:
string contents = File.ReadAllText("C:\\Work\\list.txt");
if (contents.Contains(args[0]))
{
// ...
}
Alternatively, you could read it line by line:
foreach (string line in File.ReadLines("C:\\Work\\list.txt"))
{
if (line.Contains(args[0]))
{
// ...
// Break if you don't need to do anything else
}
}
Or even more LINQ-like:
if (File.ReadLines("C:\\Work\\list.txt").Any(line => line.Contains(args[0])))
{
...
}
Note that ReadLines is only available from .NET 4, but you could reasonably easily call TextReader.ReadLine in a loop yourself instead.
You should not add the ';' at the end of the using statement.
Code to work:
string latestversion = args[0];
using (StreamReader sr = new StreamReader("C:\\Work\\list.txt"))
using (StreamWriter sw = new StreamWriter("C:\\Work\\otherFile.txt"))
{
// loop by lines - for big files
string line = sr.ReadLine();
bool flag = false;
while (line != null)
{
if (line.IndexOf(latestversion) > -1)
{
flag = true;
break;
}
line = sr.ReadLine();
}
if (flag)
sw.Write("1");
else
sw.Write("0");
// other solution - for small files
var fileContents = sr.ReadToEnd();
{
if (fileContents.IndexOf(latestversion) > -1)
sw.Write("1");
else
sw.Write("0");
}
}
if ( System.IO.File.ReadAllText("C:\\Work\\list.txt").Contains( args[0] ) )
{
...
}
The accepted answer reads all file in memory which can be consuming.
Here's an alternative inspired by VMAtm answer
using (var sr = new StreamReader("c:\\path\\to\\file", true))
for (string line; (line = sr.ReadLine()) != null;) //read line by line
if (line.Contains("mystring"))
return true;

Categories

Resources