Reading from a file in by specifying start point and end point - c#

I want to read from an input file in C#. Below is my code.
public string ReadFromNewEntityFile()
{
string template=null;
StringBuilder s = new StringBuilder();
//char[] sourcesystemhost=null;
string inputFileName = ConfigurationManager.AppSettings["inputNewEntityFilePath"].ToString();
System.IO.StreamReader myFile;
try
{
myFile = new System.IO.StreamReader(inputFileName);
myFile.ReadLine();
while ((template = myFile.ReadLine()) != "[[END SourceSystemHost]]")
{
s.AppendLine(template);
}
}
catch (Exception ex)
{
log.Error("In Filehandler class :" + ex.Message);
throw new Exception("Input file not read" + ex.Message);
}
return template;
}
The problem is want to specify the starting point and end point for reading the contents. Here I am able to specify only the end point. How can i specify the starting point?
Please help

Assuming your start/end "points" are actually lines, you basically need to read from the start and skip the lines until you reach the right one. Here's an easy way of doing it using File.ReadLines:
var lines = File.ReadLines(inputFileName)
.SkipWhile(line => line != "[[START SourceSystemHost]]")
.Skip(1) // Skip the intro line
.TakeWhile(line => line != "[[END SourceSystemHost]]");

You could use File.ReadLines which does the same but more readable. Then use LINQ to find your start- and end-points:
var range = File.ReadLines(inputFileName)
.SkipWhile(l => !l.TrimStart().StartsWith("[[Start SourceSystemHost]]"))
.TakeWhile(l => !l.TrimStart().StartsWith("[[END SourceSystemHost]]"));
string result = string.Join(Environment.NewLine, range);

Related

Writing a certain amount of lines in a file C#

I am currently writing a program that takes in a file, loops through all of the lines.
The file contains a lot of variables + values in this format:
Message =
"alfjawejf1ij4l2jr183fhaalfjawejf1ij4l2jr183fhahalfjawejf1ij4l2jr183fhahalfjawejf1ij4l2jr183fhahalfjawejf1ij4l2jr183fhahh" //the string will encompass multiple
lines of length
Answer = ?
My program will modify the value within message and write it in a new file.
How do I store multiple lines of the value into one string (so I can modify it)?
I need it so that it recognizes "message", starts storing the next few lines, detects "answer" and stops.
For the string holding the message value, I believe some sort of concatenation will be used (concatenating multiple lines).
string[] file = System.IO.File.ReadAllLines(#path); //file is read
string pathNew = Path.GetDirectoryName(path) + "\\completed_" + Path.GetFileName(path);
using (StreamWriter writer = File.CreateText(#pathNew))
{
foreach (string line in file)
{
for (int i = 0; i < line.Length; i++)
{
if (line.Substring(0,6).Equals("Msg = "))
{
foreach (string msg in file)
{
}
}
}
}
}
You could create it pretty easily, if you would provide a method that returns an IEnumerable<string>, and then use the File.WriteAllLines( string, IEnumerable<string> ) utility method
A way you could do it could be
private IEnumerable<string> ReturnAllMessages( IEnumerable<string> lines )
{
bool isMessage = false;
foreach (var line in lines)
{
if (line.StartsWith('Msg ='))
{
isMessage = true;
// set a flag that the next lines are part of the message
// this would exclude the rest of the line from the results
// if you want it, you could use:
// yield return line.Substring('Msg ='.Length));
continue;
}
if (line.StartsWith('Answer ='))
{
// remove the flag
isMessage = false;
continue;
}
if (isMessage)
{
// yield a line that is a message
yield return line;
}
}
}
and then use the method in the following way
File.WriteAllLines( #newPath, ReturnAllMessages( File.ReadAllLines( #path ) ) );
(didn't really test the code though, so just use it as a reference ;) )
One way to do this would be to read all the text as a single string using File.ReadAllText, and then split it on "Message =" to get all the messages, and then split each message on "Answer = " to get the answer for each message (assuming the format is "Message = some message Answer = some answer Message = some other message Answer = some other answer").
It would be helpful if you included an actual sample from the file, since your code clearly was not written for the sample you've provided (there is no line where line.Substring(0,6).Equals("Msg = ") is true).
I've included a method in my sample below that creates a text file with a multi-line message, and then showed how you can read the message into a variable and display it in the console window.
Hope this helps:
private static void CreateFile(string filePath)
{
if (File.Exists(filePath)) File.Delete(filePath);
Directory.CreateDirectory(Path.GetDirectoryName(filePath));
var fileLines = new List<string>
{
"Message = ",
"I weigh nothing, but you can still see me.",
"If you put me in a bucket, I make the bucket lighter.",
"What am I?",
"Answer = A hole",
"Message = ",
"What’s the difference between",
"a hippo and a Zippo?",
"Answer = ",
"A hippo is really heavy, ",
"and a Zippo is a little lighter."
};
File.WriteAllLines(filePath, fileLines);
}
private static void Main()
{
// Set this to a file that doesn't exist or that you don't care about
var filePath = #"f:\private\temp\temp.txt";
// Create a file with multi-line messages
CreateFile(filePath);
// Read all the file text
var fileText = File.ReadAllText(filePath);
// Split it into the message/answers
var messageAnswers = fileText.Split(new[] {"Message ="},
StringSplitOptions.RemoveEmptyEntries);
// Split each message into a message/answer array
foreach (var messageAnswer in messageAnswers)
{
var parts = messageAnswer.Split(new[] {"Answer ="},
StringSplitOptions.RemoveEmptyEntries);
var message = parts[0].Trim();
var answer = parts.Length > 1 ? parts[1].Trim() : "";
Console.WriteLine(message);
var userResponse = Console.ReadLine().Trim();
if (userResponse.Equals(answer, StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine("Correct!");
}
else
{
Console.WriteLine("The actual answer is: " + answer);
}
}
GetKeyFromUser("\nDone! Press any key to exit...");
}

How to delete all lines in text file that is NOT a number greater than a specific value? (Including strings)

My Issue:
I am looking into a text file and i need to delete all the lines, or use string.empty that does not meet the requirement. For example,
The requirement is 50000. There are words/text in the file and also numbers that are smaller than the requirement. How can i delete all line in a text file that do not meet the requirement? I do not want to be specific with the other values in the text file as they can differ.
My Research:
I have searched and found to delete specific values then rewrite them onto a new file which i am trying to do. I have found different ways that dont meet my needs. I am using what i have found below but am missing something to make it complete
My Effort:
DialogResult openFile = openFileDialog1.ShowDialog();
if (openFile == DialogResult.OK)
{
string file = openFileDialog1.FileName;
string content = File.ReadAllText(file);
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = "Text File|*.txt";
sfd.FileName = "New Text Doucment";
sfd.Title = "Save As Text File";
if (sfd.ShowDialog() == DialogResult.OK)
{
string path = sfd.FileName;
StreamWriter bw = new StreamWriter(File.Create(path));
bw.WriteLine(content);
bw.Close();
File.WriteAllLines(path, File.ReadAllLines(path).Select(x => string.Format("{0},", x)));
string newContent = File.ReadAllText(path);
newContent = newContent.Remove(newContent.LastIndexOf(","));
File.WriteAllText(path, newContent);
string secondContent = File.ReadAllText(path);
int number = int.Parse(File.ReadAllText(path));
if (checkBox1.Checked == true)
{
secondContent = secondContent.Replace("BRUSH(1,0)", string.Empty);
secondContent = secondContent.Replace("REGION 1,", string.Empty);
secondContent = secondContent.Remove(secondContent.LastIndexOf(","));
File.WriteAllText(path, secondContent);
if (secondContent.Contains())
{
number = 0;
secondContent = secondContent.Replace(number.ToString(), string.Empty);
File.WriteAllText(path, secondContent);
}
}
else if (checkBox2.Checked == true)
{
secondContent = secondContent.Replace("BRUSH(1,0),", ")),");
secondContent = secondContent.Replace("REGION 1,", string.Empty);
secondContent = secondContent.Remove(secondContent.LastIndexOf(","));
File.WriteAllText(path, secondContent);
}
//Just trying
foreach (char c in secondContent)
{
if (secondContent.All(char.IsDigit))
{
char = string.Empty;
}
}
}
}
What i am doing above:
Grabbing an existing file,
adding the contents to a new file,
add a comma at the end of each line,
removing the last comma at the end of the file.
removing a line that contains brush or region
Now here are examples of the file:
TYPE_CODE char(2),
DESCRIPT0 char(25),
TYPE_COD0 char(3),
DESCRIPT1 char(36),
DATA,
BRUSH(1,0),
REGION(1,0),
13502,
319621.99946835 110837.002493295,
319640.501385461 110850.59860145,
319695.199120806 110879.700271183,
319728.303041127 110879.300385649,
319752.898058391 110876.501186912,
319767.401120868 110872.702274339,
The numbers at the bottom of that example is what the entire document should look like
To address just the issue stated try the following:
//Get the lines from the file
List<string> lines = System.IO.File.ReadAllLines("MyFile.txt").ToList();
//Removed the lines which are empty or when split using ' ' contain items other the numbers >= 50000
double d = 0;
lines.RemoveAll(x => string.IsNullOrWhiteSpace(x) || x.TrimEnd(',').Split(' ').Any(y => !double.TryParse(y, out d) || double.Parse(y) < 50000));
//Write the new file
System.IO.File.WriteAllLines("MyFile2.txt", lines.ToArray());
To add a comma to the end of each line add the following lines before saving:
//Remove any existing ',' and add our own
lines = lines.Select(x => x.TrimEnd(',') + ",").ToList();
//Remove any trailing ',' from the last line
lines[lines.Count - 1] = lines[lines.Count - 1].TrimEnd(',');
(Edited to handle multiple numbers per line)
(Fixed conversion errors)
(Fixed for existing ',')
First, abstraction would be your friend here. Break up your code into different peices to make it a little easier to handle. Plus when you have to change your requirements later, you will have an easy spot to do it.
Second, File.ReadLines is also your friend because it will give you a collection of strings, which will let you use LINQ.
Which brings me to your third friend, LINQ, which will let you query the collection of file lines.
public void FormatFile(string sourcePath, string targetPath)
{
IEnumerable<String> originalContent = GetFileLines(sourcePath);
IEnumerable<String> formatedContent = ProcessFileLines(originalContent);
OutputResults(targetPath, formatedContent);
}
public IEnumerable<String> GetFileLines(string path) {
return File.ReadLines(path);
}
public IEnumerable<string> ProcessFileLines(IEnumerable<string> fileLines)
{
// In this method you can process the logic that applies to the whole
// set of file lines (e.g. lineCount, removing empyLines, etc)
return processedLines.Select(l => ProcessLine(l)
.Where(l => !string.IsNullOrEmpty(l))
.GetRange(0, MAX_LINE_COUNT);
}
public string ProcessLine(string fileLine)
{
// In this method just focus on logic applied to each specific line.
string s = fileLine.Substring(0, 5);
if (s.Equals("BRUSH", StringComparison.InvariantCultureIgnoreCase)
return string.Empty;
return fileLine;
}
public void OutputResults(string targetPath, IEnumerable<string> fileLines)
{
string outputText = fileLines.Join($",{Environment.NewLine}");
File.WriteAllText(targetPath, outputText);
}
So basically you can just call FormatFile(#"C:\mySource", #"C:\myTarget"); and you will be good to go.

How find and remove specific line with next or previous lines in large text document

I'm trying to figure out, how to remove specific string from large text document with 500 000 lines. Find line by content, but at the same time get current line index value in text document order, which must not be disturbed, to remove next or previous line of found line, in other words find closest by index, to remove both for large document. Because any method I've tried with using File.WriteAllLines program hangs with such size. I have active requesting to this file and seems like need to find some other way. For example file content is:
1. line 1
2. line 2
3. line 3
4. line 4
5. line 5
and line to find and remove is:
string input = "line 3"
to get this result with removing of found line index and next line index + 1 of next line, if found line index number is odd:
line 1
line 2
line 5
and at the same time be able to remove found line index and index - 1 previous line, if found line index is even number for searching string:
string input = "line 4"
and result should be:
line 1
line 2
line 5
And to know if line is does not exist in the text document.
Write to the same single file.
If you want to process very large file, the you should use FileStream to avoid loading all of the contents into memory.
To meet your last requirement, you can read the lines two by two. It actually makes your code simpler.
var inputFileName = #"D:\test-input.txt";
var outputFileName = Path.GetTempFileName();
var search = "line 4";
using (var strInp = File.Open(inputFileName, FileMode.Open))
using (var strOtp = File.Open(outputFileName, FileMode.Create))
using (var reader = new StreamReader(strInp))
using (var writer = new StreamWriter(strOtp))
{
while (reader.Peek() >= 0)
{
var lineOdd = reader.ReadLine();
var lineEven = (string)null;
if (reader.Peek() >= 0)
lineEven = reader.ReadLine();
if(lineOdd != search && lineEven != search)
{
writer.WriteLine(lineOdd);
if(lineEven != null)
writer.WriteLine(lineEven);
}
}
}
// at this point, operation is sucessfull
// rename temp file with original one
File.Delete(inputFileName);
File.Move(outputFileName, inputFileName);
Use a System.IO.StreamReader.
private static void RemoveLines(string lineToRemove, bool skipPrevious, bool skipNext)
{
string previousLine = string.Empty;
string currentLine;
bool isNext = false;
using (StreamWriter sw = File.CreateText(#"output.txt"))
{
using (StreamReader sr = File.OpenText(#"input.txt"))
{
while ((currentLine = sr.ReadLine()) != null)
{
if (isNext)
{
currentLine = string.Empty;
isNext = false;
}
if (currentLine == lineToRemove)
{
if (skipPrevious)
{
previousLine = string.Empty;
}
if (skipNext)
{
currentLine = string.Empty;
isNext = true;
}
}
if (previousLine != string.Empty && previousLine != lineToRemove)
{
sw.WriteLine(previousLine);
}
previousLine = currentLine;
}
}
if (previousLine != string.Empty && previousLine != lineToRemove)
{
sw.WriteLine(previousLine);
}
}
}
Haven't tested it, but this would give required directions.
Let the input file is inputFile.txt then you can use File.ReadAllLines() method to get all lines in that particular file. Then use IndexOf() method to find the index of specific line in that list, if it is not found means it will return -1 then use RemoveAt() to remove the line at that particular index. Consider the code:
List<string> linesInFile = File.ReadAllLines(filePath).ToList(); // gives you list of lines
string input = "line 3";
int lineIndex = linesInFile.IndexOf(input);
if (lineIndex != -1)
{
linesInFile.RemoveAt(lineIndex);
}
// If you may have more number of match for particular line means you can try this as well :
linesInFile.RemoveAll(x=> x== input);
If you want to write it back to the file means use this line:
File.WriteAllLines(filePath,linesInFile);

Read a Text File and Populate an Array

I am to read a file and populate a String array. My data is like:
Accident.
An unplanned event, unexpected and undesigned, which occurs suddenly and at a definite place.
Accident Frequency.
The rate of the occurrence of accidents, often expressed in terms of the number of accidents over a period of time. It is one method used for measuring the effectiveness of loss prevention services. Contrast with Accident Severity.
Accident Prevention.
See Loss Prevention Service.
Accident Severity.
A measure of the severity or seriousness of losses, rather than the number of losses. It is measured in terms of time lost from work rather than the number of individual accidents. It is another way of measuring the effectiveness of loss prevention services. Contrast with Accident Frequency.
My code is:
private void openfile_Click(object sender, EventArgs e)
{
if (text.Text == String.Empty)
{
err.SetError(text, "Needs to contain Text");
}
DialogResult result = open_dialog.ShowDialog();
if (result == DialogResult.OK)
{
try
{
string file_name = open_dialog.FileName;
System.IO.StreamReader sr = new System.IO.StreamReader(file_name);
String line;
String[] wordslist=new String[count];
using (StreamReader reader = File.OpenText(file_name))
{
// read each line, ensuring not null (EOF)
while ((line = reader.ReadLine()) != null)
{
if (line == String.Empty)
{
}
else
{
wordslist = line.Split(' ');
count += 1;
}
}
}
for (int i=0;i<wordslist.Length;i++)
{
//if (str==(text.Text))
//{
//var index = Array.FindIndex(wordslist, row => row.Contains(text.Text));
Console.WriteLine("\ncapacity " + wordslist[i]);
//Console.WriteLine("\n" + wordslist[index - 1]+" capacity");
//}
}
}
catch (Exception ex)
{
Console.WriteLine("\n\nERROR= " + ex);
}
}
}
I simply want to print the contents of the array being populated with the file contents but the array is not being populated. But when I remove the Blank lines between my data the array will be populated with some few lines and I'm able to print some but not ALL contents.
The problem is that my data is so large that I can't remove lines and don't want to be! Is there any solution so that i can do this thing correctly?
You can use Linq
var wordslist= System.IO.File.ReadAllLines("filename")
.Where(x => !string.IsNullOrWhiteSpace(x))
.SelectMany(x => x.Split(' '));
foreach(var word in wordlist)
{
Console.WriteLine("\ncapacity " + word);
}
There is a combination of issues. Firstly this line;
String[] wordslist=new String[count];
That does nothing. It creates an array of length zero and sets the wordslist reference to that.
Then this is the real problem;
wordslist = line.Split(' ');
Split returns a new string array, it doesn't add to the current one. You only get the final line because wordslist gets set to the result of calling split on that line in the last iteration of the loop. You can fix your code by doing;
List<string> wordslist = new List<string>();
then doing;
wordslist.Add(line.Split(' '));
to add items. List<T> is a dynamic array and will grow as necessary. T[] (an array) cannot grow dynamically and because of that is not a good collection choice for reading the file.
Here's another suggestion (how I would do it);
string[] words = File.ReadAllLines(path).Where(x => !x.IsNullOrEmpty())
.Select(x => x.Split(' '))
.SelectMany();
That one liner will first, read every line of the file into a string[], the Where is then applied and all of the empty lines are removed. After that each line is split on space which gives you an IEnumerable<string[]> (a list of string arrays where each array is a lines worth of words) and finally the SelectMany "flattens" the list meaning it combines all of those arrays into one.
private void openfile_Click(object sender, EventArgs e) {
if (text.Text == String.Empty) {
err.SetError(text, "Needs to contain Text");
}
DialogResult result = open_dialog.ShowDialog();
if (result == DialogResult.OK)
{
try
{
string file_name = open_dialog.FileName;
System.IO.StreamReader sr = new System.IO.StreamReader(file_name);
String line;
List<string> wordslist=new List<string>(count);
using (StreamReader reader = File.OpenText(file_name))
{
// read each line, ensuring not null (EOF)
while ((line = reader.ReadLine()) != null)
{
if (line != String.Empty) {
// Here instead of replacing array with new content
// we add new words to already existing list of strings
wordslist.AddRange(line.Split(' '));
count += 1;
}
}
}
// Count instead of Length because we're using List<T> now
for (int i=0;i<wordslist.Count;i++)
{
Console.WriteLine("\ncapacity " + wordslist[i]);
}
}
catch (Exception ex)
{
Console.WriteLine("\n\nERROR= " + ex);
}
}
}
I am not sure if I understand what you ask for, but it appears you want to read content of file without empty lines?
Your code is quite a mess, here you got little bit that will return all non-empty lines from file.
List<string> readIt(string fileName)
{
string line;
List<string> data = new List<string>();
StreamReader file = new StreamReader(fileName);
while((line = file.ReadLine()) != null)
{ if (line!="") data.Add(line); }
file.Close();
return data;
}

Remove blank lines in a text file

How can you remove blank lines from a text file in C#?
If file is small:
var lines = File.ReadAllLines(fileName).Where(arg => !string.IsNullOrWhiteSpace(arg));
File.WriteAllLines(fileName, lines);
If file is huge:
var tempFileName = Path.GetTempFileName();
try
{
using (var streamReader = new StreamReader(inptuFileName))
using (var streamWriter = new StreamWriter(tempFileName))
{
string line;
while ((line = streamReader.ReadLine()) != null)
{
if (!string.IsNullOrWhiteSpace(line))
streamWriter.WriteLine(line);
}
}
File.Copy(tempFileName, inptuFileName, true);
}
finally
{
File.Delete(tempFileName);
}
File.WriteAllLines(path, File.ReadAllLines(path).Where(l => !string.IsNullOrWhiteSpace(l)));
Read all of the contents of a file into a string then just run
string output = null;
try {
output = Regex.Replace(input, #"^\s*$", "", RegexOptions.Multiline);
} catch (Exception e) {
}
Other similar options can be found in How to remove empty lines from a formatted string?
We can achieve it very easily by using LINQ technique for Huge or small file.
1.Explanation: It will read the file and skip all empty lines and store all the data into an string array
string[] text = File.ReadAllLines(path with file name).Where(s => s.Trim() != string.Empty).ToArray();
It will delete that file.
File.Delete(path with file name);
It will create new file as same name and append all the array data into new file
File.WriteAllLines(path with file name, text);
Complete Code
string[] text = File.ReadAllLines(LoraWan_Parameter_Check_Tool.Properties.Settings.Default.csv_file_path.ToString()).Where(s => s.Trim() != string.Empty).ToArray();
File.Delete(LoraWan_Parameter_Check_Tool.Properties.Settings.Default.csv_file_path.ToString());
File.WriteAllLines(LoraWan_Parameter_Check_Tool.Properties.Settings.Default.csv_file_path.ToString(), text);
Problem solved
Thank you

Categories

Resources