Removing a line from a text file in C# - c#

i am a newbie in C# and i have a simple console application with method validateVoters() which takes a studentID argument, compares it against text file then return appropriate boolean value.
However i want it to delete that specific studentID if it exists then return true, but there is no generic delete from file method so i used a method recommended by a member here:
Giving me an error with the method in double asterics ** :
Error 2
The name 'RemoveUnnecessaryLine' does not exist in the current context c:\Users\Hlogoyatau\Documents\Visual Studio 2010\Projects\Ijoo\Ijoo\Program.cs 28 43 Ijoo
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace SRCVotingSystem
{
public class Program
{
public bool validateVoter(String cisNo)
{
bool found = false;
try
{
string[] ID = System.IO.File.ReadAllLines(#"C:\Users\Hlogoyatau\Pictures\votersRoll.txt");
foreach (string line in ID)
{
//compares it against text file contents
if (cisNo == line)
{
string[] allLines= File.ReadAllLines("votersRoll.txt");
string[] newIDs= **RemoveUnnecessaryLine**(allLines);
File.WriteAllLines("votersRoll.txt", newIDs);
found = true;
}
}
}
catch (IOException e)
{
Console.WriteLine(e.ToString());
}
return found;
}
public static void Main()
{
Program vv = new Program();
Console.WriteLine(vv.validateVoter("cis11-005"));
}
}
}

/* sample data in text.tx
ID 1 asdfsdaf
ID 2 asdfdsafasdfsadf
ID 3 lkjasdfjsdf
*/
private static void Main(string[] args)
{
var id = 2;
var lines = File.ReadAllLines("C:\\temp\\text.txt");
var remaining = lines.Where(x => !x.Contains(id.ToString())).ToArray();
File.WriteAllLines("C:\\temp\\out.txt", remaining);
}

Try this:
public bool validateVoter(String cisNo)
{
bool found = false;
try
{
string[] ID = System.IO.File.ReadAllLines(#"C:\Users\Hlogoyatau\Pictures\votersRoll.txt");
for (int i = 0; i < ID.Length; i++)
{
string line = ID[i];
//compares it against text file contents
if (cisNo == line)
{
//Shift remaining lines up, overwriting current line
for (int j = i; j < ID.Length - 1; j++)
{
ID[j] = ID[j+1];
}
//Set last line to empty string
ID[ID.Length - 1] = "";
//Write file back to disk
System.IO.File.WriteAllLines(#"C:\Users\Hlogoyatau\Pictures\votersRoll.txt", ID);
found = true;
//Exit loop after something is found
break;
}
}
}
catch (IOException e)
{
Console.WriteLine(e.ToString());
}
return found;
}
It will read the file, and when a match is found, then it shifts the remaining lines up one line. The last line will be cleared, then the file gets written back to disk. If you do not want to have an empty last line, then you can resize the array (see Array.Resize).

Try using LINQ
public void validateVoter(String cisNo)
{
var newIDs = System.IO.File.ReadAllLines(#"C:\Users\Hlogoyatau\Pictures\votersRoll.txt").Where(l => l != cisNo);
File.WriteAllLines(#"C:\Users\Hlogoyatau\Pictures\votersRoll.txt", newIDs);
}

Related

When executing second for loop into listbox program populates no data

so the assignment is to read from the student file into an array and read into the answer key array, compare the two and output a grade based on the array comparison.
the issue i'm having is that when i try to load the answer key into it's array it's like its not even getting the data, because all the questions output as wrong.
below is the code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace AshleyBrown_CPT185A01S_Chapter7Lab
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//variables
private const int SIZE = 20; //current # of q's on test
private int index = 0, count = 1; //counter variables
private int wrong = 0, right = 0; //grade variables
these are the arrays that are used for the answers:
//arrays
private char[] studentAnswers = new char[SIZE];
private char[] answerKey = new char[SIZE];
private void calculateBtn_Click(object sender, EventArgs e)
{
//prevents any file errors
try
{
ReadStudentFile();
ReadAnswerKey();
CompareAnswers();
}
catch
{
MessageBox.Show("File doesn't exist or has the wrong name.");
}
}
private void clearBtn_Click(object sender, EventArgs e)
{
//Clear Form
studentAListBox.Items.Clear();
correctAListBox.Items.Clear();
wrongAListBox.Items.Clear();
incorrectBox.Text = "";
correctBox.Text = "";
percentBox.Text = "";
}
private void exitBtn_Click(object sender, EventArgs e)
{
//close program
Close();
}
method for reading the student file that works:
private void ReadStudentFile()
{
//Stream Reader Setup
StreamReader studentFile;
studentFile = File.OpenText("C:\\Users\\aabro\\Documents\\_CPT 185\\AshleyBrown_CPT185A01S_Chapter7Lab\\Student File.txt");
//Read Student Answers into studentAnswers Array
while (index < studentAnswers.Length && !studentFile.EndOfStream)
{
studentAnswers[index] = char.Parse(studentFile.ReadLine());
index++;
}
//Close Student Answer file
studentFile.Close();
//Display Student Answers
foreach (char answer in studentAnswers)
{
studentAListBox.Items.Add(count + ". " + answer.ToString());
count++;
}
}
method for reading answer key that populates with no data:
private void ReadAnswerKey()
{
//Stream Reader Setup
StreamReader answerFile;
answerFile = File.OpenText("C:\\Users\\aabro\\Documents\\_CPT 185\\AshleyBrown_CPT185A01S_Chapter7Lab\\Answer Key.txt");
//Read Answer Key in answerKey Array
while (index < answerKey.Length && !answerFile.EndOfStream)
{
answerKey[index] = char.Parse(answerFile.ReadLine());
index++;
}
//Close answer key file
answerFile.Close();
//clear count
count = 1;
//display answer key in correct answer list box
foreach (char key in answerKey)
{
correctAListBox.Items.Add(count + ". " + key.ToString());
count++;
}
}
private void CompareAnswers()
{
//reset count
count = 1;
for (index = 0; index < answerKey.Length; index++)
{
//determine if answer is right
if (studentAnswers[index] != answerKey[index])
{
wrongAListBox.Items.Add(count + ". " + answerKey[index]);
wrong++;
count++;
}
}
//fail display
if (wrong > 5)
{
MessageBox.Show("Student has failed");
}
//calculations
double pointPerQ = 5;
double wrongTotal = wrong;
double wrongPointTotal = wrong * pointPerQ;
double grade = 100 - wrongPointTotal;
//output grade information
incorrectBox.Text = wrong.ToString();
correctBox.Text = right.ToString();
percentBox.Text = grade.ToString("p0");
}
}
}
this is the current output from running the program, I did double check the file names and contents as well.
output of current code
One issue that I saw in code is using of index in multiple while loops without previously assigning to 0.
I suggest using of local variables(variable which exists only in the current block of code).
Also in my opinion it will be good to declare and initialize new variable in for-loop like this:
for(int index = 0; index < answerKey.Length; index++)
{
// your code
}
it will be more readable and easier if you want later to separate loops in methods or move in service or helper.

Save and load a game by using StreamWriter and ReadWriter (C#)

I'm creating a small program which can save and load char array values. Then, I got stuck with two problems.
I have no idea how to make the program end after saving the data.
After loading the char array, it looks the game starts where I saved last time. However, when I put "#" on the place where is already marked, it is accepted. (It is supposed to display error message)
This is when I start new game.
It displays error message properly.
Here is class which includes streamWriter and streamReader.
public class History
{
public char QUIT = 'Y';
public char CONTINUE = 'N';
public char inputGameContinue;
public void WriteFile(char []arr)
{
FileStream sb = new FileStream("MyFile.txt", FileMode.OpenOrCreate);
StreamWriter sw = new StreamWriter(sb);
WriteLine("If you want to save the data, enter" + QUIT +"| To continue, enter "+CONTINUE );
inputGameContinue = char.Parse(ReadLine());
if(inputGameContinue=='Y')
{
sw.Write(arr);
WriteLine("The data is saved!");
}
sw.Close();
}
public void ReadFile()
{
string path = "MyFile.txt";
WriteLine("New game? >> 1 | Load saved data? >>2 ");
int command = int.Parse(ReadLine());
if (command == 2)
{
using (StreamReader sr = new StreamReader(path))
{
while (sr.Peek() >= 0)
{
WriteLine(sr.ReadLine());
}
}
}
}
}
Class2
using System;
using static System.Console;
using System.IO;
namespace createSample
{
public class writeRead
{
public static void Main(string[] args)
{
InputClass inputClass = new InputClass();
ArrayValue arrayValue = new ArrayValue();
History history = new History();
WriteLine("Welcome to game!");
WriteLine("");
history.ReadFile();
do
{
inputClass.inputNumber();
while (true)
{
if (arrayValue.arr[inputClass.input] == '#')
{
WriteLine("{0} already marked '#'. Try another.", inputClass.input);
inputClass.inputNumber();
}
else
{
arrayValue.arr[inputClass.input] = '#';
arrayValue.printArray();
history.WriteFile(arrayValue.arr);
break;
}
}
}
while (checkWhenFinish(arrayValue)!=1 );
WriteLine("All letters are marked with '#'");
Read();
}
public static int checkWhenFinish(ArrayValue a)
{
if(a.arr[0] != '0' && a.arr[1] != '1' && a.arr[2] != '2' && a.arr[3] != '3' && a.arr[4] != '4')
{
return 1;
}
else
{
return 0;
}
}
}
}
Class3
using System;
using System;
using System.Numerics;
using System.Reflection.Emit;
using static System.Console;
using System.IO;
namespace createSample
{
public class ArrayValue
{
public char []arr = { '0','1', '2', '3', '4' };
public void printArray()
{
WriteLine("{0},{1},{2},{3},{4}", arr[0], arr[1], arr[2], arr[3], arr[4]);
}
}
}
Class 4
using System;
using System;
using System.Numerics;
using System.Reflection.Emit;
using static System.Console;
using System.IO;
namespace createSample
{
public class InputClass
{
public int input;
public void inputNumber()
{
while (true)
{
Write("Enter number ? (0 to 4) >> ");
if (!int.TryParse(ReadLine(), out input))
{
input = -1;
}
if (input == 0|| input == 1 || input == 2 || input == 3 || input == 4 )
{
break;
}
else
{
WriteLine("Error! Try again!");
}
}
}
}
}
The problem is when you call history.ReadFile() it can read the file and display its contents, but it never updates arrayValue.arr so when the check is done later, arrayValue.arr[inputClass.input] is still 2.
You might want to pass in arrayValue by reference to ReadFile() to have it updated:
history.ReadFile(ref arrayValue);
then in History
public void ReadFile(ref ArrayValue arrayValue)
{
...
while (sr.Peek() >= 0)
{
var line = sr.ReadLine();
WriteLine(line);
for (int i = 0; i < arrayValue.arr.Length; i++)
{
arrayValue.arr[i] = line[i];
}
}
...
}

How to LINQ-ify the following loop?

I have a method in a C# program. It enumerates all the .cs files in a certain folder and then runs through the list. For each file, I read all the lines using File.ReadAllLines on it. I only want to process a file if it contains a class, whether conventional, static, or abstract, whose name begins with a certain phrase and does not end with the word Tests. Moreover, I wish to find the line index in the line of lines containing the declaration of the class --- i.e., the public static class Foo part.
Given that I take the result of File.ReadAllLines and call ToList() on it to create a List<string>, I wish to use the FindIndex method to find the index of the line matching my criteria (if it exists) using a Predicate.
My question is: What is a good way to write such a predicate?
I realize I could probably use more sophisticated methods, but I am just putting this code into a quick-and-dirty LINQPad script. So, I don't have to get super fancy.
Let me show you what I have so far (assume that the outermost namespace and class are already suitably declared):
void Main()
{
var files = Directory
.EnumerateDirectories(
Path.Combine(
Environment.GetFolderPath(
Environment.SpecialFolder.UserProfile
), #"source\repos\astrohart\MFR"
), "*", SearchOption.TopDirectoryOnly
).SelectMany(
x => Directory.EnumerateFiles(
x, "FileSystemEntry*.cs", SearchOption.AllDirectories
)
)
.Where(x => !"FileSystemEntry.cs".Equals(Path.GetFileName(x)))
.ToList();
if (files == null || !files.Any()) return;
foreach (var file in files)
{
var contents = string.Empty;
try
{
contents = File.ReadAllText(file);
}
catch (Exception ex)
{
Console.WriteLine($"ERROR: {ex.Message}");
contents = string.Empty;
}
if (string.IsNullOrWhiteSpace(contents)) continue;
if (contents.Contains("[TestFixture]")) continue;
if (contents.Contains("[Log(AttributeExclude = true)]")) continue;
file.Dump();
var lines = new List<string>();
lines.TrimExcess();
try
{
lines = File.ReadAllLines(file).ToList();
}
catch (Exception ex)
{
Console.WriteLine($"ERROR: {ex.Message}");
lines = new List<string>();
lines.TrimExcess();
}
if (lines == null || !lines.Any()) continue;
var index = -1;
for (var i = 0; i < lines.Count; i++)
{
var currentLine = lines[i].Trim();
if (currentLine.EndsWith("Tests")) continue;
if (currentLine.StartsWith("public static class FileSystemEntry"))
{
index = i;
break;
}
if (currentLine.StartsWith("public class FileSystemEntry"))
{
index = i;
break;
}
if (currentLine.StartsWith("public abstract class FileSystemEntry"))
{
index = i;
break;
}
}
if (index < 0) continue;
/*...*/
}
}
How do I translate the for loop in:
var index = -1;
for (var i = 0; i < lines.Count; i++)
{
var currentLine = lines[i].Trim();
if (currentLine.EndsWith("Tests")) continue;
if (currentLine.StartsWith("public static class FileSystemEntry"))
{
index = i;
break;
}
if (currentLine.StartsWith("public class FileSystemEntry"))
{
index = i;
break;
}
if (currentLine.StartsWith("public abstract class FileSystemEntry"))
{
index = i;
break;
}
}
if (index < 0) continue;
into a call thus:
var index = lines.FindIndex(currentLine => /*...*/);
I need help with how to derive the proper body of the lambda expression that matches what the for loop does.
Thanks in advance!
EDIT 1
I squinted my eyes at my loop just a little more. I am looking for a predicate to use specifically with the FindIndex method. I thought a little harder and I figured out maybe I can get away with:
var index = lines.FindIndex(currentLine => !currentLine.Trim.EndsWith("Tests") && currentLine.Trim().StartsWith("public static class FileSystemEntry") || currentLine.Trim().StartsWith("public class FileSystemEntry") || currentLine.Trim().StartsWith("public abstract class FileSystemEntry"));
Perhaps I can implement an extension method
public static bool StartsWithAnyOf(this string value, params string[] testStrings)
{
var result = false;
try
{
if (string.IsNullOrWhiteSpace(value.Trim())) return result;
if (testStrings == null || !testStrings.Any()) return result;
foreach(var element in testStrings)
if (value.Trim().StartsWith(element))
{
result = true;
break;
}
}
catch
{
result = false;
}
return result;
}
Then I'd declare another method:
public static bool KeepLine(string currentLine)
{
if (string.IsNullOrWhiteSpace(currentLine.Trim())) return false;
if (currentLine.Trim().EndsWith("Tests")) return false;
return currentLine.StartsWithAnyOf(
"public static class FileSystemEntry",
"public class FileSystemEntry",
"public abstract FileSystemEntry"
);
}
Then use it thus:
var index = lines.FindIndex(KeepLine);
Would that work?
I havent tested this thoroughly but it seems to pass basic sanity if I compare to original code supplied above. Note that this is not best when it comes to measuring performance. The 'foreach' loop with anonymous function has flaw that you cannot break away from the anonymous function. The only way to come out of a foreach is to run all foreach statements. In order to preserve first index where criteria matches against line contents, I am using index in else if() comparison statement. This means the foreach loop will run for all lines despite of having the first occurrence of matching lines found.
lines.ForEach((l) =>
{
if (l.EndsWith("Tests")) ;
else if (index ==0 && (l.StartsWith("public static class FileSystemEntry") ||
l.StartsWith("public class FileSystemEntry") ||
l.StartsWith("public abstract class FileSystemEntry")))
{
index = lines.IndexOf(l);
}
});

Continuous same char list and I cannot delete all of them

When I want to delete my specific char which is "o" in list in this code it delete some of them and others it does not delete. I mean when I debug it the result is (Roazooooor). I want to delete all of "o" chars not half of them
and when I debug it, I want it to give me (razr) without "o".
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string name = "Rooazoooooooooor";
var nameChar = new List<char>();
nameChar.AddRange(name);
for (int i = 0; i < nameChar.Count; i++)
{
if (nameChar[i] == 'o')
nameChar.Remove(nameChar[i]);
Console.Write(nameChar[i]);
}
Console.WriteLine();
}
}
}
The problem is that when you remove an item, you're then moving onto the next index, even though you'll have shuffled everything after that item up one.
In this particular case, the simplest option would be to use string.Replace first:
name = name.Replace("o", "");
var nameChar = new List<char>(name);
Or you could keep your existing code and use:
while (nameChar.Remove('o')) ;
Or
nameChar.RemoveAll(c => c == 'o');
All of these would leave you with a list without any 'o' elements.
For absolute minimal changes in your current code, you could change your loop to:
for (int i = 0; i < nameChar.Count; i++)
{
if (nameChar[i] == 'o')
{
// After removing the element at index i,
// we want to try index i again, so decrement
// and continue without printing.
nameChar.Remove(nameChar[i]);
i--;
continue;
}
Console.Write(nameChar[i]);
}
Is it necessary to use List in your case? If not then:
class Program
{
static void Main(string[] args)
{
string name = "Rooazoooooooooor";
string resultName = string.Empty;
foreach (var currentChar in name)
{
if (currentChar != 'o')
resultName += currentChar;
}
Console.Write(resultName);
Console.ReadKey();
}
}
`

How can I make 1 button click fill out 2 different text boxes

I need help making this program fill out 2 different text boxes. It works if I only use it to fill out 1 text box using a First name. But when I try and add another text box to generate a random Last name it just seems to do fail.
private void button1_Click(object sender, EventArgs e)
{
Random r = new Random();
int currentLine = 1;
string pick = null;
foreach (string line in File.ReadLines("C:\\First Names.txt"))
{
if (r.Next(currentLine) == 0)
{
pick = line;
}
++currentLine;
textBox1.Text = pick;
}
Random n = new Random();
int currentLine1 = 1;
string pick1 = null;
foreach (string line1 in File.ReadLines("C:\\Last Names.txt"))
{
if (n.Next(currentLine1) == 0)
{
pick1 = line1;
}
++currentLine1;
textBox2.Text = pick1;
}
}
}
}
Check whether the path for the file is appropriate.
You need not create two objects for the same class and access them differently.One object is enough.
3.Check whether data is there in the file or not.`Random r = new Random();
int currentLine = 1;
string pick = null;
foreach (string line in File.ReadLines("C:\\First Names.txt"))
{
if (r.Next(currentLine) == 0)
{
pick = line;
}
++currentLine;
textBox1.Text = pick;
}
currentLine=0;pick=0;
foreach (string line in File.ReadLines("C:\\Last Names.txt"))
{
if (r.Next(currentLine) == 0)
{
pick = line;
}
++currentLine;
textBox2.Text = pick;
}
}`
If the first iteration gets the value, then the second must also get. Else there is some problem with Text file or the 'textBox2' is not the correct ID you are looking for.

Categories

Resources