Returning values from text file : C# - c#

I have a .txt file that contains information about vehicles that I add via another project. I want to read the text file, retrieve each VIN number, and place just the actual number itself in a combo box when the form is loaded.
The info for each vehicle in the txt file looks like:
Model: 'model'
Manufacturer: 'manufacturer'
VIN Number: 'VIN number'
This is what I have:
using (StreamReader reader = new StreamReader(#"D:\carCenter\carCenter\bin\Debug\Vehicles.txt"))
{
string[] lines = File.ReadAllLines(#"D:\carCenter\carCenter\bin\Debug\Vehicles.txt");
foreach(string line in lines)
{
if (line.Contains("VIN"))
{
Char colon = ':';
string[] vins = line.Split(new string[] {"VIN Number: "}, StringSplitOptions.None);
for (int i = 0; i < 1; i++)
{
foreach(var vin in vins)
{
vinComboBox.Items.Add(vins[i]);
}
}
}
}

One solution is to have a general purpose function like this:
private String GetDataToRightOfLastColon(String line)
{
line = line.Trim();
var indexOfLastColon = line.LastIndexOf(':');
/* If line does not contain a ':' character,
or ':' is the last non-space character in line,
throw an exception. */
if ((indexOfLastColon == -1) || (indexOfLastColon == (line.Length - 1)))
throw new ArgumentException(
String.Format("The line '{0}' does not have the correct format.", line));
return line.Substring(indexOfLastColon + 1).Trim();
}
Next, apply that function via LINQ to process the text file and populate the combobox:
vinComboBox.Items.AddRange(
File
.ReadAllLines(#"D:\carCenter\carCenter\bin\Debug\Vehicles.txt")
.Where(line => line.Trim().StartsWith("VIN"))
.Select(line => GetDataToRightOfLastColon(line))
.ToArray()
);

Related

How to remove texts after a character?

I have an array that holds user and passwords in user:pass form, and I like ro remove lines which pass is less than 8 characters or password uses repetitive chars like 111111,22222222222,...
I have tried string.take but it takes lines completely, I need conditional deletion.
public string[] lines;
//open file dialogue to load the user pass file
lines = File.ReadAllLines(openFileDialog1.FileName);
//delete button click event
//the place that I have problem
I have email:pass combination like so:
email1:1234567895121
email2:12345
email4:11111
email5"454545454545
and I would like the output to be like
email1:1234567895121
email5"454545454545
Just loop the characters of every line and see if the current is equal to the previous:
public string[] lines = File.ReadAllLines(openFileDialog1.FileName);
var filteredLines = new List<string>(lines);
foreach(var line in lines)
{
var pair = line.Split(':');
var mail = pair[0];
var pass = pair[1]; // may throw exception on invalid format of your line
for(int i = 1; i < pass.Length; i++)
{
if(pass[i] == pass[i - 1])
{
filteredLines.Remove(line);
break; // will break inner loop and continue on next line
}
}
}
string[] lines =
{
"email1:1234567895121",
"email2:12345",
"email3:22222222222",
"email4:11111",
"email5:454545454545"
};
lines = lines
.Where(s =>
{
string pass = s.Split(new[] { ':' }, 2)[1];
return pass.Length >= 8 && pass.Any(c => c != pass[0]);
})
.ToArray();
foreach (var s in lines)
Console.WriteLine(s);
Output:
email1:1234567895121
email5:454545454545

text parsing application c# without third party libraries

For example, there is a line:
name, tax, company.
To separate them i need a split method.
string[] text = File.ReadAllLines("file.csv", Encoding.Default);
foreach (string line in text)
{
string[] words = line.Split(',');
foreach (string word in words)
{
Console.WriteLine(word);
}
}
Console.ReadKey();
But how to divide if in quotes the text with a comma is indicated:
name, tax, "company, Ariel";<br>
"name, surname", tax, company;<br> and so on.
To make it like this :
Max | 12.3 | company, Ariel
Alex, Smith| 13.1 | Oriflame
It is necessary to take into account that the input data will not always be in an ideal format (as in the example). That is, there may be 3 quotes in a row or a string without commas. The program should not fall in any case. If it is impossible to parse, then issue a message about it.
Split using double quotes first. And Split using comma on the first string.
You can use TextFieldParser from Microsoft.VisualBasic.FileIO
var list = new List<Data>();
var isHeader=true;
using (TextFieldParser parser = new TextFieldParser(filePath))
{
parser.Delimiters = new string[] { "," };
while (true)
{
string[] parts = parser.ReadFields();
if(isHeader)
{
isHeader = false;
continue;
}
if (parts == null)
break;
list.Add(new Data
{
People = parts[0],
Tax = Double.Parse(parts[1]),
Company = parts[2]
});
}
}
Where Data is defined as
public class Data
{
public string People{get;set;}
public double Tax{get;set;}
public string Company{get;set;}
}
Please note you need to include Microsoft.VisualBasic.FileIO
Example Data,
Name,Tax,Company
Max,12.3,"company, Ariel"
Ariel,13.1,"company, Oriflame"
Output
Here's a bit of code that might help, not the most efficient but I use it to 'see' what is going on with the parsing if a particular line is giving trouble.
string[] text = File.ReadAllLines("file.csv", Encoding.Default);
string[] datArr;
string tmpStr;
foreach (string line in text)
{
ParseString(line, ",", "!####!", out datArr, out tmpStr)
foreach(string s in datArr)
{
Console.WriteLine(s);
}
}
Console.ReadKey();
private static void ParseString(string inputString, string origDelim, string newDelim, out string[] retArr, out string retStr)
{
string tmpStr = inputString;
retArr = new[] {""};
retStr = "";
if (!string.IsNullOrWhiteSpace(tmpStr))
{
//If there is only one Quote character in the line, ignore/remove it:
if (tmpStr.Count(f => f == '"') == 1)
tmpStr = tmpStr.Replace("\"", "");
string[] tmpArr = tmpStr.Split(new[] {origDelim}, StringSplitOptions.None);
var inQuote = 0;
StringBuilder lineToWrite = new StringBuilder();
foreach (var s in tmpArr)
{
if (s.Contains("\""))
inQuote++;
switch (inQuote)
{
case 1:
//Begin quoted text
lineToWrite.Append(lineToWrite.Length > 0
? newDelim + s.Replace("\"", "")
: s.Replace("\"", ""));
if (s.Length > 4 && s.Substring(0, 2) == "\"\"" && s.Substring(s.Length - 2, 2) != "\"\"")
{
//if string has two quotes at the beginning and is > 4 characters and the last two characters are NOT quotes,
//inquote needs to be incremented.
inQuote++;
}
else if ((s.Substring(0, 1) == "\"" && s.Substring(s.Length - 1, 1) == "\"" &&
s.Length > 1) || (s.Count(x => x == '\"') % 2 == 0))
{
//if string has more than one character and both begins and ends with a quote, then it's ok and counter should be reset.
//if string has an EVEN number of quotes, it should be ok and counter should be reset.
inQuote = 0;
}
else
{
inQuote++;
}
break;
case 2:
//text between the quotes
//If we are here the origDelim value was found between the quotes
//include origDelim so there is no data loss.
//Example quoted text: "Dr. Mario, Sr, MD";
// ", Sr" would be handled here
// ", MD" would be handled in case 3 end of quoted text.
lineToWrite.Append(origDelim + s);
break;
case 3:
//End quoted text
//If we are here the origDelim value was found between the quotes
//and we are at the end of the quoted text
//include origDelim so there is no data loss.
//Example quoted text: "Dr. Mario, MD"
// ", MD" would be handled here.
lineToWrite.Append(origDelim + s.Replace("\"", ""));
inQuote = 0;
break;
default:
lineToWrite.Append(lineToWrite.Length > 0 ? newDelim + s : s);
break;
}
}
if (lineToWrite.Length > 0)
{
retStr = lineToWrite.ToString();
retArr = tmpLn.Split(new[] {newDelim}, StringSplitOptions.None);
}
}
}

How to parse a .txt file with uncommon delimiters in C#

I am currently trying to parse a .txt file containing information listed like this: name/ID number/email/GPA. Here are a few lines showing what the text file looks like.
(LIST (LIST 'Doe 'Jane 'F ) '8888675309 'jfdoe#mail.university.edu 2.3073320999676614 )
(LIST (LIST 'Doe 'John 'F ) 'NONE 'johnfdoe#mail.university.edu 3.1915725161177115 )
(LIST (LIST 'Doe 'Jim 'F ) '8885551234 'jimdoe#mail.university.edu 3.448215586562192 )
In my current code all I am doing is printing the text file line by line to a console window.
static void Main(string[] args)
{
StreamReader inFile;
string inLine;
if (File.Exists("Students.txt"))
{
try
{
inFile = new StreamReader("Students.txt");
while ((inLine = inFile.ReadLine()) != null)
{
Console.WriteLine(inLine);
}
}
catch (System.IO.IOException exc)
{
Console.WriteLine("Error");
}
Console.ReadLine();
}
}
I need to able to, for example, find all the students that have a GPA above 3.0 and print their name and GPA to another text file. I understand how to print to another file, however, I am unsure how to access the individual columns, such as the GPA, since this file does not seem to have any common delimiters that would make using a Split() practical. Any help or insight on how to accomplish this would be appreciated.
IMPORTANT
I considered that the provided string in your question has a fixed format as shown.
IMPLEMENTATION
First, you need to create a class that is blueprint of the information you are getting from the string. It will give you a container to hold a meaningful information about the data.
public class StudentInfo
{
public string Name { get; set; }
public string Number { get; set; }
public string Email { get; set; }
public double GPA { get; set; }
}
Following is an example how to parse the string (string from your question) and convert it to relative information. I assume that you can read/write files in C#.
This sample demonstrates parsing and storing iformation in List. You can further use this to write files.
In you code, you are reading lines and that is why in this sample, I tried to read lines from string so you can understand it better.
I created this sample in C# Console application.
static void Main(string[] args)
{
List<StudentInfo> studentInfo = new List<StudentInfo>();
string input = "(LIST(LIST 'Abbott 'Ashley 'J ) '8697387888 'ajabbott#mail.university.edu 2.3073320999676614 )" + Environment.NewLine +
"(LIST(LIST 'Abbott 'Bradley 'M ) 'NONE 'bmabbott#mail.university.edu 3.1915725161177115 )" + Environment.NewLine +
"(LIST(LIST 'Abbott 'Ryan 'T ) '8698689793 'rtabbott#mail.university.edu 3.448215586562192 )";
string[] lines = input.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
if (lines != null && lines.Count() > 0)
{
foreach (var line in lines)
{
var data = line.Replace("(LIST(LIST ", string.Empty)
.Replace(")", string.Empty)
.Replace("'", string.Empty)
.Trim()
.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
if (data != null && data.Count() > 0)
{
studentInfo.Add(
new StudentInfo()
{
Name = data[0] + " " + data[1] + " " + data[2],
Number = data[3],
Email = data[4],
GPA = Convert.ToDouble(data[5])
});
}
}
}
// GET STUDENTS WHO GOT GPA > 3 (LINQ QUERY)
if (studentInfo.Count > 0)
{
var gpaGreaterThan3 = studentInfo.Where(s => s.GPA >= 3).Select(s => s).ToList();
if (gpaGreaterThan3 != null && gpaGreaterThan3.Count > 0)
{
// LOOP gpaGreaterThan3 TO PRINT STUDENT DATA
foreach (var stud in gpaGreaterThan3)
{
Console.WriteLine("Name: " + stud.Name);
Console.WriteLine("Number: " + stud.Number);
Console.WriteLine("Email: " + stud.Email);
Console.WriteLine("GPA: " + stud.GPA);
Console.WriteLine(string.Empty);
}
}
}
Console.ReadLine();
}
Try this:
var data = inLine.Replace("(LIST(LIST ", string.Empty)
.Replace(")", string.Empty)
.Replace("'", string.Empty)
.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
There are many ways to go about this, but most importantly you need to consider variations to the string format that might trip up any of the approaches
is gpa field always present and at the end?
will it have a defined identifiable format etc
Can there be more than one and if so which one would you pick etc
Below are a couple of approaches with assumptions. You would have to adjust the code per your assumption and how critical this piece of code would be.
// split on both space and closing bracket
// Assumption: GPA field is present and at the end
Console.WriteLine(line.Split(new[] { " ", ")" }, StringSplitOptions.RemoveEmptyEntries).LastOrDefault());
// regex for gpa defined as digit followed by literal . followed by one or more digits
// Assumption: GPA field is present once somewhere in the string.
// No other token conflicts with similar format
var gpaRegex = new Regex(#"\d\.\d+");
Console.WriteLine(gpaRegex.Matches(line)[0]);
See https://dotnetfiddle.net/6Xy0uW for working example
See https://regex101.com/r/P1D7zf/1 for the regex in action where you might try more strict variations

Change a text in files in a folder next to string "Text_ID"

  Example of a text file below 
text_file a
Text_ID "441124_aad0656_1234"
Text_FILE_NAME
I would like to keep only last index of string "1234"
StreamReader streamReader = new StreamReader(text);
string text2;
while ((text2 = streamReader.ReadLine()) != null)
{
num++;
string[] array3 = text2.Split(new char[0]);
if (array3[0] == "Text_ID")
{
string[] array4 = array3[1].Split(new char[] {'_'});
string value = "Text_ID" + " " + '"' + array4[1];
streamWriter.WriteLine(value);
}
else
{
streamWriter.WriteLine(text2);
}
}
try below code, and hope it should work for you.
var startsWith = "Text_ID";
var allLines = File.ReadAllLines("a.txt").ToList();
allLines = allLines.Select(ln =>
{
if(ln.StartsWith(startsWith))
{
var finalValue = ln.Split(' ')[1].Trim('"').Split('_').Last();
//get update line
return string.Format("{0} \"{1}\"", startsWith, finalValue);
}
return ln;
}).ToList();
//Write back to file.
File.WriteAllLines("a.txt", allLines.ToArray());
Content before code execution.
Record 1
Text_ID "441124_aad0656_1234"
other content.
Record 2
Text_ID "Deepak_Sharma"
other content for line 2
Content in file after execution.
Record 1
Text_ID "1234"
other content.
Record 2
Text_ID "Sharma"
other content for line 2
You could use File.ReadAllLines to read the file into an array, then search through the array for the line you want to change, replace that line with the new string, and then use File.WriteAllLines to write the array back to the file:
var filePath = #"f:\public\temp\temp.txt";
// The string to search for
var searchTxt = "Text_ID";
// Read all the lines of the file into an array
var fileLines = File.ReadAllLines(filePath);
// Loop through each line in the array
for(int i = 0; i < fileLines.Length; i++)
{
// Check if the line begins with our search term
if (fileLines[i].Trim().StartsWith(searchTxt, StringComparison.OrdinalIgnoreCase))
{
// Get the end of the line, after the last underscore
var lastPartOfLine = fileLines[i].Substring(fileLines[i].LastIndexOf("_") + 1);
// Combine our search string, a quote, and the end of the line
fileLines[i] = $"{searchTxt} \"{lastPartOfLine}";
// We found what we were looking for, so we can exit the for loop now
// Remove this line if you expect to find more than one match
break;
}
}
// Write the lines back to the file
File.WriteAllLines(filePath, fileLines);
If you only want to save the last four lines of the file, you can call Skip and pass in the Length of the array minus the number of lines you want to keep. This skips all the entries up to the number that you want to save:
// Read all the lines of the file into an array
var fileLines = File.ReadAllLines(filePath);
// Take only the last 4 lines
fileLines = fileLines.Skip(fileLines.Length - 4).ToArray();

Pick a specific line from a text file and spilt the line in an array

What I would like to do is pick a line from a text file. That line number is corresponding with a local variable. So if the variable is 1, pick line one. The text file is in Resources and called nl_5.txt. After that the picked line (a word) should placed in a new array, but each letter should be placed at a new index. So if the variable is 1, line one is apple. Something like this:
string[] arr1 = new string[] { "a", "p", "p", "l", "e" }; (0=a 1=p 2=p 3=l 4=e)
If the local variable is changing to 2, line two should be read and the array should be changed with the other line (other word, other letters). How should I do this?
I found different variants like read the complete file or read specific lines who're defined, but I've tried a lot with no correct result.
int lineCount = File.ReadAllLines(#"C:\test.txt").Length;
int count = 0;
private void button1_Click(object sender, EventArgs e)
{
var reader = File.OpenText(#"C:\test.txt");
if (lineCount > count)
{
textBox1.Text = reader.ReadLine();
count++;
}
}
First, let's obtain the word via Linq:
int line = 3; // one based line number
string word = File
.ReadLines(#"C:\test.txt") //TODO: put actual file name here
.Skip(line - 1) // zero based line number
.FirstOrDefault();
Then convert word into the array
string[] arr1 = word
.Select(c => c.ToString())
.ToArray();
If you have to read the file for many different line you can cache the file:
// Simplest, not thread safe
private static string[] file;
// line is one-based
private static string[] getMyArray(int line) {
if (null == file)
file = File.ReadAllLines(#"C:\test.txt");
// In case you have data in resource as string
// read it and (split) from the resource
// if (null == file)
// file = Resources.MyString.Split(
// new String[] { Environment.NewLine }, StringSplitOptions.None);
string word = (line >= 1 && line < file.Length - 1) ? file[line - 1] : null;
if (null == word)
return null; // or throw an exception
return word
.Select(c => c.ToString())
.ToArray();
}

Categories