Read text file from resource - c#

I am trying the following code to split the words in a text file.
The file is written like this:
Apple"Juice"Martini
Lemon"Juice"Party
Banana"Smoothie"Aligns
and the code following:
string resource_data = Properties.Resources.textfile;
string[] result = resource_data.Split('"');
foreach (string lines in result)
{
if(comboBox1.Text == result[0])
{
richTextBox2.Text = result[2];
}
}
Taken & edited from a c++ program I was working on which worked perfectly with the same txt file.
String^ resource_data = "textfile.txt";
try
{
StreamReader^ DataIn = File::OpenText(resource_data);
String^ DataStr;
int count = 0;
array<String^>^ result;
array<Char>^ separ = gcnew array<Char>{'"'};
while((DataStr = DataIn->ReadLine()) != nullptr)
{
count++;
result = DataStr->Split(separ);
if(comboBox1->Text == result[0]) // result[0] = Name
{
What the code does..
Read each line as it own.
Gives first word in each line result[0] as second word on each line is result[1] etc.
When I select a word in the combobox I check if it is the same as in the text file and that line is used in result[x].
But in the C# it gives ALL words own result[x] and lines does not matter.
How can I make the following code in c++ to work in C# but having the text file in the resources.resx?

I think I see what the problem is. You first need to split the string resource_data into separate lines. You could do this by splitting resource_data on the new line character(s):
string[] lines = resource_data.Split(new string[1] { Environment.NewLine }, StringSplitOptions.None);
foreach (var line in lines)
{
string[] parts = line.Split('"');
if (comboBox1.Text == result[0])
{
richTextBox2.Text = result[2];
}
}
You could also do this using a StringReader:
using (StringReader reader = new StringReader(resource_data))
{
while (reader.Peek() >= 0)
{
string[] parts = reader.ReadLine().Split('"');
if (comboBox1.Text == result[0])
{
richTextBox2.Text = result[2];
}
}
}
Additionally if you are only storing the path to the file in the resources, you could open the file and read from it:
using (StreamReader reader = File.OpenText(resource_path)) // path to file
{
while (reader.Peek() >= 0)
{
string[] parts = reader.ReadLine().Split('"');
if (comboBox1.Text == result[0])
{
richTextBox2.Text = result[2];
}
}
}

Related

How do I delete all lines in text file below certain text?

I have a code which iterates through the entire text file searching for a specific text "[names]", and "tried" to delete all the lines below the text. I tried File.WriteAllText(INILoc, string.Empty);, but this just deletes everything in the entire text file. How do I make it so only all the lines below "[names]" gets deleted?
I have set up the iteration likes this :
string[] lines = File.ReadAllLines(INILoc);
bool containsSearchResul = false;
foreach (string line in lines)
{
if (containsSearchResul)
{
File.WriteAllText(INILoc, string.Empty);
}
if (line.Contains("[names]"))
{
containsSearchResul = true;
}
}
You need to store lines before "[names]" text into a string variable, and when condition (line.Contains("[names]")) satisfy then just break the loop and write string value into the same file.
Something like,
string[] lines = File.ReadAllLines(INILoc); //Considering INILoc is a string variable which contains file path.
StringBuilder newText = new StringBuilder();
bool containsSearchResul = false;
foreach (string line in lines)
{
newText.Append(line);
newText.Append(Environment.NewLine); //This will add \n after each line so all lines will be well formatted
//Adding line into newText before if condition check will add "name" into file
if (line.Contains("[names]"))
break;
}
File.WriteAllText(INILoc, newText.ToString());
//^^^^^^^ due to string.Empty it was storing empty string into file.
Note: If you are using StringBuilder class, then do not miss to add Using System.Text in your program
Use StreamReader as it will give you the best performance as you don't need to read the whole file. Swap 'PATH TO INPUT FILE' with your file path and the result will be stored at the path you provide for 'PATH TO OUTPUT FILE'.
using (var sr = new StreamReader("PATH TO INPUT FILE"))
{
using (var sw = new StreamWriter("PATH TO OUTPUT FILE"))
{
var line = sr.ReadLine();
while (line != null)
{
sw.WriteLine(line);
if (line.Contains("[names]"))
{
sw.Close();
sr.Close();
}
else
{
line = sr.ReadLine();
}
}
}
}
If you need to write to the same file:
var sb = new StringBuilder();
using (var sr = new StreamReader("PATH TO INPUT FILE"))
{
var line = sr.ReadLine();
while (line != null)
{
sb.AppendLine(line);
if (line.Contains("[names]"))
{
sr.Close();
}
else
{
line = sr.ReadLine();
}
}
}
File.WriteAllText("PATH TO INPUT FILE", sb.ToString());
Based on the requested code I have put together modifications.
string[] lines = File.ReadAllLines(INILoc);
//create a list to hold the lines
List<string> output = new List<string>();
//loop through each line
foreach (string line in lines)
{
//add current line to ouput.
output.Add(line);
//check to see if our line includes the searched text;
if (line.Contains("[names]"))
{
//output to the file and then exit loop causing all lines below this
//one to be skipped
File.WriteAllText(INILoc, output.ToArray());
break;
}
}
The problem with your code is that it delete all the lines before the [names], not after (more exactly, write only the lines after that text). Also, any time you rewrite all the file content, and so remove all previous wrote line. It'll work as follows:
string[] lines = File.ReadAllLines(INILoc);
using (StreamWriter writer = new StreamWriter(INILoc)) // https://learn.microsoft.com/en-us/dotnet/standard/io/how-to-write-text-to-a-file
{
bool containsSearchResul = false;
foreach (string line in lines)
{
if (!containsSearchResul)
{
writer.Write(INILoc, string.Empty);
}
if (line.Contains("[names]"))
{
containsSearchResul = true;
}
}
}
You have another, better option to do this with break:
string[] lines = File.ReadAllLines(INILoc);
using (StreamWriter writer = new StreamWriter(INILoc)) // https://learn.microsoft.com/en-us/dotnet/standard/io/how-to-write-text-to-a-file
{
foreach (string line in lines)
{
if (line.Contains("[names]"))
{
break;
}
writer.WriteLine(INILoc, string.Empty);
}
}
But you can do this in prefered, more-readable way, by using LINQ:
using System.Linq;
// ...
string[] lines = File.ReadAllLines(INILoc);
string[] linesTillNames = lines
.Take( // Take just N items from the array
Array.IndexOf(lines, "[names]") // Until the index of [names]
)
.ToArray();
File.WriteAllLines(INILoc, linesTillNames);
You can also use: WriteAllLines(string path, IEnumerable<string> contents) like this:
string[] lines = File.ReadAllLines(INILoc);
List<string> linesToWrite = new List<string>();
foreach(string line in lines)
{
linesToWrite.Add(line);
if (line.Contains("[names]")) break;
}
File.WriteAllLines(INILoc, linesToWrite);

C# search all files in a directory that contain a string, then return that string

Using user input into a textbox, I want to search for which file in the directory contains that text. I would then like to parse out the information
but I can't seem to find the string or at least return the information. Any help would be greatly appreciated.
My current code:
private void btnSearchSerial_Click(object sender, EventArgs e)
{
dynamic dirScanner = #"\\mypath\";
string strSerial;
string strSID;
string strInputLine;
string strOutput;
strSerial = Convert.ToString(txtSerialSearch);
strSID = Convert.ToString(txtSID);
if (txtSerialSearch.Text != "" && txtSID.Text != "")
{
try
{
string[] allFiles = Directory.GetFiles(dirScanner);
foreach (string file in allFiles)
{
if (file.EndsWith(".txt"))
{
using (StreamReader sr = new StreamReader(file))
{
while (sr.Peek() >= 0)
{
strInputLine = sr.ReadLine();
if (strInputLine.Contains(strSerial))
{
strOutput = Convert.ToString(strInputLine);
lblOutput.Text = Convert.ToString(strOutput);
}
}
}
}
}
}
}
}
You seem quite lost. Why are you using a dynamic when a string is all that you need? Your code has too many unnecessary variables and convertions. Here's a much simpler way to do it. I don't know what you want the label to have if there are many matching lines, here I'm only placing the first one there:
string dirScanner = #"\\mypath\";
if (string.IsNullOrWhiteSpace(txtSerialSearch.Text) || string.IsNullOrWhiteSpace(txtSID.Text))
return;
string[] allFiles = Directory.GetFiles(dirScanner, "*.txt");
foreach (string file in allFiles)
{
string[] lines = File.ReadAllLines(file);
string firstOccurrence = lines.FirstOrDefault(l => l.Contains(txtSerialSearch.Text));
if (firstOccurrence != null)
{
lblOutput.Text = firstOccurrence;
break;
}
}
I have implemented the same using Regular Expressions. You need to use namespace using System.Text.RegularExpressions;
string strSerial = #"Microsoft";
Regex match = new Regex(strSerial);
string matchinglines = string.Empty;
List<string> filenames = new List<string>(Directory.GetFiles(textBox1.Text));
foreach(string filename in filenames)
{
//StreamReader strFile = new StreamReader(filename);
string fileContent = File.ReadAllText(filename);
if(match.IsMatch(fileContent))
{
label1.Text = Regex.Match(fileContent, strSerial).ToString();
break;
}
}
Use System.LINQ:
var list_of_files_that_match = Directory.EnumerateFiles(dir).Where(delegate (string t)
{
return System.IO.File.ReadAllText(t).Contains(your_text);
}).ToList();
This worked for me. Quick and simple.

Read file, check correctness of column, write file C#

I need to check certain columns of data to make sure there are no trailing blank spaces. At first thought I thought it would be very easy, but after attempting to achieve the goal I have got stuck.
I know that there should be 6-digits in the column I need to check. If there is less I will reject, if there are more I will trim the blank spaces. After doing that for the entire file, I want to write it back to the file with the same delimiters.
This is my attempt:
Everything seems to be working correctly except for writing the file.
if (File.Exists(filename))
{
using (StreamReader sr = new StreamReader(filename))
{
string lines = sr.ReadLine();
string[] delimit = lines.Split('|');
while (delimit[count] != "COLUMN_DATA_TO_CHANGE")
{
count++;
}
string[] allLines = File.ReadAllLines(#filename);
foreach(string nextLine in allLines.Skip(1)){
string[] tempLine = nextLine.Split('|');
if (tempLine[count].Length == 6)
{
checkColumn(tempLine);
writeFile(tempLine);
}
else if (tempLine[count].Length > 6)
{
tempLine[count] = tempLine[count].Trim();
checkColumn(tempLine);
}
else
{
throw new Exception("Not enough numbers");
}
}
}
}
}
public static void checkColumn(string[] str)
{
for (int i = 0; i < str[count].Length; i++)
{
char[] c = str[count].ToCharArray();
if (!Char.IsDigit(c[i]))
{
throw new Exception("A non-digit is contained in data");
}
}
}
public static void writeFile(string[] str)
{
string temp;
using (StreamWriter sw = new StreamWriter(filename+ "_tmp", false))
{
StringBuilder builder = new StringBuilder();
bool firstColumn = true;
foreach (string value in str)
{
if (!firstColumn)
{
builder.Append('|');
}
if (value.IndexOfAny(new char[] { '"', ',' }) != -1)
{
builder.AppendFormat("\"{0}\"", value.Replace("\"", "\"\""));
}
else
{
builder.Append(value);
}
firstColumn = false;
}
temp = builder.ToString();
sw.WriteLine(temp);
}
}
If there is a better way to go about this, I would love to hear it. Thank you for looking at the question.
edit:
file structure-
country| firstname| lastname| uniqueID (column I am checking)| address| etc
USA|John|Doe|123456 |5 main street|
notice the blank space after the 6
var oldLines = File.ReadAllLines(filePath):
var newLines = oldLines.Select(FixLine).ToArray();
File.WriteAllLines(filePath, newLines);
string FixLine(string oldLine)
{
string fixedLine = ....
return fixedLine;
}
The main problem with writing the file is that you're opening the output file for each output line, and you're opening it with append=false, which causes the file to be overwritten every time. A better approach would be to open the output file one time (probably right after validating the input file header).
Another problem is that you're opening the input file a second time with .ReadAllLines(). It would be better to read the existing file one line at a time in a loop.
Consider this modification:
using (StreamWriter sw = new StreamWriter(filename+ "_tmp", false))
{
string nextLine;
while ((nextLine = sr.ReadLine()) != null)
{
string[] tempLine = nextLine.Split('|');
...
writeFile(sw, tempLine);

Parsing CSV data

I am trying to parse a CSV file with data with no luck, i have tried a bunch of tools online and none has been able to parse the CSV file correctly. I am baffled by the fact that i am in here asking for help as one would think parsing CSV data would be something super easy.
The format of the CSV data is like this:
",95,54070,3635,""Test Reservation"",0,102,0.00,0.00,2014-12-31,""Name of customer"",""$12.34 + $10, special price"",""extra information"",,CustomerName,,,,,1234567890,youremail#domain.com,CustomerName,2014-12-31,23:59:59,16,0,60,2,120,0,NULL,NULL,NULL,"
Current code:
private void btnOpenFileDialog_Click(object sender, EventArgs e)
{
DialogResult result = openFileDialog1.ShowDialog();
if (result == DialogResult.OK)
{
using (StreamReader reader = new StreamReader(openFileDialog1.FileName))
{
string line;
while ((line = reader.ReadLine()) != null)
{
ParseCsvLine(line);
}
}
}
}
private void ParseCsvLine(string line)
{
if (line != string.Empty)
{
string[] result;
using (var csvParser = new TextFieldParser(new StringReader(line)))
{
csvParser.Delimiters = new string[] { "," };
result = csvParser.ReadFields();
}
foreach (var item in result)
{
Console.WriteLine(item + Environment.NewLine);
}
}
}
The result variable only has one item and its:
,95,54070,3635,"Test Reservation",0,102,0.00,0.00,2014-12-31,"Name of customer","$12.34 + $10, special price","extra information",,CustomerName,,,,,1234567890,youremail#domain.com,CustomerName,2014-12-31,23:59:59,16,0,60,2,120,0,NULL,NULL,NULL,
// Add Microsoft.VisualBasic.dll to References.
using Microsoft.VisualBasic.FileIO;
// input is your original line from csv.
// Remove starting and ending quotes.
input = input.Remove(0, 1);
input = input.Remove(input.Length - 1);
// Replace double quotes with single quotes.
input = input.Replace("\"\"", "\"");
string[] result;
using (var csvParser = new TextFieldParser(new StringReader(input)))
{
csvParser.Delimiters = new string[] { "," };
result = csvParser.ReadFields();
}
You can check out a previous post that deals with those pesky commas in csv files. I'm linking it here.
Also Mihai, your solution works well for just the one line but will fail once there are many lines to parse.

Extract data from text file

I need to extract some data from a text file and insert to columns in excel sheet. I know how to do this if the rows and the length of the string is known.
try
{
using (System.IO.StreamReader sr = new System.IO.StreamReader("test.txt")
{
string line;
while ((line = sr.ReadLine()) != null)
{
listSNR.Items.Add(line.Substring (78,4));
}
}
}
But the particular text file is complex and the starting index or the length cannot be provided. But the starting word (PCPU01) of the row is known.
Eg: PCPU01,T2716,0.00,0.01,0.00,0.00
output:
T2716 0 0.01 0 0
In that case can somebody please let me know how to extract the texts?
using(System.IO.StreamReader sr = new System.IO.StreamReader("test.txt"))
{
string line;
while((line = sr.ReadLine()) != null)
{
string[] split = line.Split(',');
//...
}
}
split[0] will return "PCPU01", split[1] "T2716" and so on.
You can split one string into an array of strings, separated by a given character. This way, you could split the source string by a comma and use the resulting strings to build your output. Example:
string source = "PCPU01,T2716,0.00,0.01,0.00,0.00";
string[] parts = source.Split(',');
StringBuilder result = new StringBuilder();
result.Append(parts[1]); // The second element in the array, i.e. T2716
result.Append(" ");
result.Append(parts[2]); // 0.00
... // And so on...
return result.ToString() // return a string, not a StringBuilder
I hope this helps a little bit. You might have to tweak it to your needs. But this is a higher level code that gives you general idea of extracting data off a notepad.
DialogResult result = openFileDialog.ShowDialog();
Collection<Info> _infoCollection = new Collection<Info>();
Collection<string> listOfSubDomains = new Collection<string>();
string[] row;
string line;
// READ THE FILE AND STORE IT IN INFO OBJECT AND STORE TAHT INFO OBJECT IN COLLECTION
try
{
using (StreamReader reader = new StreamReader(openFileDialog.FileName))
{
while((line = reader.ReadLine()) != null)
{
Info _info = new Info();
row = line.Split(' ');
_info.FirstName = row[0];
_info.LastName = row[1];
_info.Email = row[2];
_info.Id = Convert.ToInt32(row[3]);
_infoCollection.Add(_info);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
thanks for the answers. What i wanted is to identify the particular line in the text file and split the line into columns. So i was able to do this by calling a GetLine method:
string line15=GetLine(#"test.txt",15);
public string GetLine(string fileName, int line)
{
using (System.IO.StreamReader ssr = new System.IO.StreamReader("test.txt"))
//using (var ssr = new StreamReader("test.txt"))
{
for (int i = 1; i < line; i++)
ssr.ReadLine();
return ssr.ReadLine();
}
}
Then i splitted this line by using the delimiter (,)
This was my approach in C#. It takes a string input (which you can get out of a text file) and an int with which line you want to get. It then separates the string at a given seperator char to a list which in turn is then read out. If the given line number is lower than the count of the created list, the entry is given back.
public string GetLine(string multiline,int line)
{
List<string> lines = new List<string>();
lines = multiline.Split('\n').ToList<string>();
return lines.Count >= line ? lines[line] : "";
}

Categories

Resources