finding a line that contains… etc - c#

Ok, well i'm basically trying to find a certain line withing "Users.txt"
Heres my code so far.
if (ok == "b" || ok == "B")
{
using (StreamWriter w = File.AppendText("Users.txt"))
{
//Test
Out.WriteLine("Please state the username");
string user = Console.ReadLine();
Out.WriteLine("Checking..");
if (w.Equals(user))
{
Out.WriteLine("Username is taken");
}
Thread.Sleep(pause);
Out.WriteLine("Please state the password for the user");
string pass = Console.ReadLine();
Logger(user, pass, w);
// Close the writer and underlying file.
w.Close();
Out.WriteLine("Checking..");
Out.WriteBlank();
Thread.Sleep(pause);
Out.WriteLine("Anything else Mr." + Environment.UserName + " ?");
}
string choice = Console.ReadLine();
if (choice == "no")
{
Boot();
}
if (choice == "yes")
{
Console.Clear();
Console.Title = "Administrator Panel";
Panel();
}
}
want it to see if the "user" is taken, then stop them from executing the process.
Thanks for the help.

Try reading (StreamReader with File.Open) each existing username into an array/List and then comparing user input against that list.
Your current code doesn't actually read anything since you're using a StreamWriter with File.AppendText which just lets you write to the end of a file.
Examples:
Reading File into a List
List<string> users = new List<string>();
using (StreamReader r = new StreamReader("Users.txt"))
{
string line;
while ((line = r.ReadLine()) != null)
{
users.Add(line);
}
}
...
string user = Console.ReadLine();
Out.WriteLine("Checking..");
if (users.Contains(user))
{
Out.WriteLine("Username is taken");
}

There are various problems with your code. Let's see if we can break it down one piece at a time.
using (StreamWriter w = File.AppendText("Users.txt"))
This code would be useful if you wanted to open "Users.txt" and append text to it. Since you want to open a file and read from it, you need to use a different object, the StreamReader object:
using (StreamReader r = File.Open("Users.txt"))
Next, you want to check if the given Username is in the file. You're doing:
if (w.Equals(user))
{
Out.WriteLine("Username is taken");
}
This isn't going to work. You are comparing a StreamWriter object with a String object. They will never be equal.
What you need to do instead is change the order of your program like this:
First, read the entire contents of the file into memory. Then, outside of the Using statement, process your user input and your username/password checking.
Let's assume the file is organized like this:
username,password
username2,password2
johnsmith,mysecretcode
janedoe,blahblah
You could, for example, read each line into a Dictionary object, where the Key is the username and the Value is the password.
Dictionary<String, String> myDictionary = new Dictionary<String, String>
// Example of adding ONE username/password to the dictionary
myDictionary.Add("username", "password");
Then, checking for the username would be as simple as
bool containsUsername = myDictionary.ContainsKey(username);
And checking the password would be:
bool doesPasswordMatch = myDictionary[username] == givenPassword;
Give it a shot! C# is a great language to learn.

Related

C# Comparing user input with data from external file C#

Sorry if the post is duplicated, but I couldn't find any case like mine that is posted here or somewhere else.
I am working on a C# console application that should save the user input and then read it again "Something like a simple sign up and login application".
using System;
using System.IO;
namespace Reader
{
class Program
{
static void Main(string[] args)
{
string filepath = #"C:\myProgramingFiles\password.txt";
StreamReader reader = File.OpenText(filepath);
string line = reader.ReadLine();
Console.WriteLine("Write your username:");
string userInput = Console.ReadLine();
Console.WriteLine("Write your password:");
string password = Console.ReadLine();
Console.WriteLine(userInput);
Console.WriteLine(password);
while(line != null)
{
Console.WriteLine(userInput == line);
Console.WriteLine(password == line);
if (userInput == line)
{
Console.WriteLine("Your username is: " + line);
}
if(password == line)
{
Console.WriteLine("Your password is: " + line);
}
line = reader.ReadLine();
}
reader.Close();
}
}
}
I have this code that reads the data from password.txt, and everything works fine, but when I do the if-else it's first checks if both user inputs are the same as the username, and then it loops again and checks if both user inputs are like the password. Sorry if I couldn't make it clear, you can run this code if you want and mock up the password.txt, and check it.
It is actually a logical and expected result, but the thing is that I don't know how else I should do it. Can you please help me?
I have tried a lot of things that didn't work, and this was my last try, so I know that it is not the best code, but it explains the problem
Let's suppose your password.txt file is like this (which appears to be the case):
password.txt
User1
Pass123
User2
Pass456
etc.
The way your code is written, with that loop you have, if the user enters User1 for the username and Pass123 for the password, the output will be:
Your username is: User1
Your password is: Pass123
BUT if the same user enters User1 and Pass456 the output will be:
Your username is: User1
Your password is: Pass456
Which is obviously undesirable logic.
So what you need is to use your loop to check for the matching username, and only when that condition is met, check for the matching password.
Otherwise you even get results like this, if the user enters Pass123 for the username and Pass456 for the password:
Your username is: Pass123
Your password is: Pass456
This can happen because you are not associating the password with the username. To make them connected you would write the code like this, assuming that username and password are on separate lines:
SOLUTION:
while(line != null)
{
Console.WriteLine(userInput == line);
Console.WriteLine(password == line);
if (userInput == line)
{
// ** CHANGES BEGIN
line = reader.ReadLine(); // get password on next line
if (line == password)
{
Console.WriteLine("Credentials are valid");
}
else
{
Console.WriteLine("Credentials are invalid");
}
break; // no need to continue this loop
}
else {
// Important: skip past password line since the username didnt match
line = reader.ReadLine();
}
// ** CHANGES END
line = reader.ReadLine(); // this is now reading the next username or EOF
}
Put the following into your text file:
hello:world
Put the following into your code:
static void Main(string[] args)
{
string filepath = #"C:\myProgramingFiles\password.txt";
Console.WriteLine("Write your username:");
string username = Console.ReadLine();
Console.WriteLine("Write your password:");
string password = Console.ReadLine();
var lines = File.ReadAllLines(filepath);
var usrpwd = username + ":" + password;
foreach(line in lines)
{
if(usrpwd == line)
Console.WriteLine("Credentials accepted");
}
}
Run the app and type hello as the username and world as the password. Build from there ..
When it comes to saving new data in your text file look at File.AppendAllLines or read all your lines in, add new data in memory and then overwrite the whole file. That's probably most easily arranged by having the data in a list, rather than an array:
var lines = new List<string>(File.ReadAllLines(...));
Then you can lines.Add(...) a user:password pair and write it out again

Looping through a list and checking for contents?

I'm trying to set up a simple command for entering all callers into a .txt file, everything is working out nicely except for the part where I want to loop through the list and check that no one is trying to enter more than once, it's not causing any problems to the application itself but it's not doing what it's supposed to do.
Any help would be much appreciated.
string filePath = Secret.Secrets.fileDestination;
var username = msg.Author.Username;
//ulong
var ID = msg.Author.Id;
string IDout = ID.ToString();
List<string> entries = File.ReadAllLines(filePath).ToList();
if(entries.Contains(IDout))
{
await msg.Channel.SendMessageAsync($"{msg.Author.Mention}, you have already been entered.");
Console.ForegroundColor = ConsoleColor.DarkRed;
Console.WriteLine($"Denied entry for {msg.Author.Mention}");
return;
}
entries.Add($"{username}, {ID}");
File.WriteAllLines(filePath, entries);
await msg.Channel.SendMessageAsync($"{msg.Author.Mention} has been entered!");

Display a button based on a login comparison

I'm new to C# and I'm trying to implement a button.visible true/false based on the contents of a txt file. Everything I've written to date is unstable at best. This is for a Winform stand alone application in the main dialog box.
In an ideal world it seems it should be simpler. I want the code to open Permissions.txt, which I know I am successfully accessing as the MessageBox will show the first name in the list, and compare the Environment.UserName with all of the names in the .txt file. Once the button is displayed it opens a new dialog box.
Anyone willing to teach a newcomer. I've been searching for a while and I don't see it.
I have also tried working with File.Readlines with no success.
Thank you in advance for any assistance you're willing to provide.
Frank Pytel
public void hideWidget()
{
//gets the users login name from the system
string newName = userNameOnly();
// Read the file and display it line by line.
System.IO.StreamReader file =
new System.IO.StreamReader(dataFolder + "\\Permissions.txt");
//This next bit called Original Code works on my local when I access it, when accessed from a server, but not for other users.
//Original code
//while ((line = file.ReadLine()) != null)
//{
// if (line == newName)
// {
// WidgetForm.Visible = true;
// }
// else
// {
// WidgetForm.Visible = false;
// }
// //MessageBox.Show(line);
// counter++;
//}
//file.Close();
//This is where I am at currently. Again it's not picking up all of the names in the .txt file.
while (file.ReadLine() != null)
{
//string line;
string line = file.ReadLine();
if (newName == file.ReadLine())
{
WidgetForm.Visible = false;
}
else
{
WidgetForm.Visible = true;
}
int counter = 0;
//MessageBox.Show(line);
//MessageBox.Show(file.ReadLine());
counter ++;
}
//file.Close();
}
EDITED....
Also if there is anyone that could possibly explain how string line; is being set to my user name. That is how it should have been set, but I've never told it line == newName in the original code. I thought that is what the While is for. To check to see if they are equal..
FINAL EDIT.
Here is what I got to work. Thanks #Bedford.
This portion goes directly below the Form1 class
string[] lines = File.ReadAllLines(dataFolder + "\\Permissions.txt");
This is the logic behind the hideWidget() button
public void hideWidget()
{
//Make all userNames available to the logic
string newName = userNameOnly();
//variable to decide if userExists is true/false
bool userExists;
//Loop through all of the userNames in the file and see if it matches the userName login
while (lines != null)
{
//Decide to make the button available if userExists does exist in the file
if (lines != null)
{
userExists = lines.Any(ln => ln == newName);
WidgetForm.Visible = userExists;
}
//Do nothing if the userName does not match anyone in the Permissions.txt file. The button default Visible is false
else
{
}
return;
}
}
I'm posting this snippet so that others might benefit from it. Thanks again #Bedford. This NEWB really appreciates the assistance. HAGD!! :-)
You can read all the lines from a file with the File.ReadAllLines static method, and then use a LINQ query to check whether any of the lines match the user name:
string[] lines = File.ReadAllLines(Path.Combine(dataFolder, "Permissions.txt"));
bool userExists = lines.Any(ln => ln == newName); // or any comparison you like
// use the bool variable to set the visibility
WidgetForm.Visible = userExists;

faulty login system, will not allow logins

ok, i got it sorted thanks to LordALMMa, but now i have another problem. I want to determine if the user clicks Admin or User radiobutton when registering. I think i should append it to the end of the line on the text file where the name and password is, but how would i do it? Here is the relevant code:
Radio Button Check
public bool radioButtons()
{
string usertypebutton;
if (!userButton.Checked && !adminButton.Checked)
{
MessageBox.Show("You must select an account type");
return false;
}
else
{
if (userButton.Checked)
{
usertypebutton = "User";
}
else
{
usertypebutton = "Admin";
}
return true;
}
}
Streamwriter for registering:
public void mySW()
{
string path = #"C:\Other\myFile.txt";
string userName = userNameBox.Text;
string password = passwordBox.Text;
string usertype = usertypebutton;
using (StreamWriter writer = new StreamWriter(path, true))
{
writer.WriteLine("Username: {0} Password: {1} Type: {3}" , userName, password, usertype);
// No need to close nor dispose your StreamWriter.
// You're inside a using statement for that!
}
MessageBox.Show("Thanks for registering! \n\nYou may now log in!", "Registration SuccessFul");
Application.OpenForms[0].Show();
this.Close();
}
Logging In:
private void logonButton_Click(object sender, EventArgs e)
{
// Loads your users storage
var users = File.ReadAllLines(#"C:\Other\myFile.txt");
// Creates the line with username + password
var usernamePassword = String.Format("Username: {0} Password: {1}", userNameBox.Text, passwordBox.Text);
// Locates the user on your storage
var userFound = users.SingleOrDefault(_u => _u.Equals(usernamePassword));
if (userFound != null)
{
MessageBox.Show("Welcome back, " + userNameBox.Text);
}
else
{
MessageBox.Show("Sorry, you have entered incorrect details\n\nPlease try again");
userNameBox.Text = "";
passwordBox.Text = "";
}
}
So (I think) essentially i want to pass the value usertypebutton from radiobutton method, to the SW. How would i do it, as i'm already passing a boolean value?
Anthony
One part of the problem is that you are not writing the same string that you're reading:
writer.WriteLine("Password: " + userName + " " + "Password: " + password);
I'm guessing that was a typo in your post... but if not that could be your issue.
The other problem is probably this right here:
using (StreamWriter writer = new StreamWriter(path, true))
If you look up the documentation on that overload of the StreamWriter constructor, you'd see that you specified append = true. You are appending each set of login credentials to a file on its own line. But then later, you are only reading the first line of that file. So you will always read the first set of credentials that were entered when the file was first created.
That aside, I hope you are just doing this as an experiment since it is not a secure way of managing passwords to write them to a file like that. Also, you don't need to call Close and Dispose on a Stream if you wrap it in a using block, so you should stick to doing that.
Anthony, dispite the fact that storing logins this way is a major security problem (it's not even a risk anymore), there are some changes to your code that I'd do.
The issue is that you're not storing "Username: [username] Password: [password]".
If you double-check your saving method, you're storing "Password: [username] Password: [password]". That's why they are never found.
Here follows some changes:
Consider:
public void mySW()
{
string path = #"C:\Other\myFile.txt";
string userName = userNameBox.Text;
string password = passwordBox.Text;
using (StreamWriter writer = new StreamWriter(path, true))
{
// This overload makes your life easier by auto-formatting variables for you.
// Also, avoid the "string1 + string2" concatenation mode.
// Use String.Format instead. It's easier to read and keep over time.
writer.WriteLine("Username: {0} Password: {1}", userName, password);
// No need to close nor dispose your StreamWriter.
// You're inside a using statement for that!
}
MessageBox.Show("Thanks for registering! \n\nYou may now log in!", "Registration SuccessFul");
Application.OpenForms[0].Show();
this.Close();
}
And your other method should look like:
{
// Loads your users storage
var users = File.ReadAllLines(#"C:\Other\myFile.txt");
// Creates the line with username + password
var usernamePassword = String.Format("Username: {0} Password: {1}", userNameBox.Text, passwordBox.Text);
// Locates the user on your storage
// This uses Linq syntax with lambda. Linq without lamba looks similar to SQL.
// Lambda is a bit more advanced but reduces code-size and it's easier to understand (IMHO).
// This code will iterate through users (list of string) and try to retrieve one that's equal to the contents of usernamePassword.
var userFound = users.SingleOrDefault(_u => _u.Equals(usernamePassword));
// If null, indicates that no username/password combination was found.
if (userFound != null)
{
MessageBox.Show("Welcome back, " + userNameBox.Text);
}
else
{
MessageBox.Show("Sorry, you have entered incorrect details\n\nPlease try again");
userNameBox.Text = "";
passwordBox.Text = "";
}
}
I'm not checking for the exception. SingleOrDefault will throw an exception if 2 or more records are found mathing the search pattern.
I'm not checking that because this will increase complexity here with try-catch and also because for that to work properly, I'd have to check if they exits BEFORE recording, so changing the register method.
But I think you've got the idea here.
Have you checked your output files? You are writing Password: X Password: Y:
writer.WriteLine("Password: " + userName + " " + "Password: " + password);
and you are checking Username: X Password: Y
if (user == ("Username: "+userNameBox.Text.Trim()+" "+"Password: "+passwordBox.Text.Trim()))
You are adding line as
writer.WriteLine("Password: " + userName + " " + "Password: " + password);
^1 ^2
^1 must be Username:
There are some points which I cannot pass without pointing:
What would you do if file structure corrupted?
What if a user wants to register twice with same username and password?
Please encode the passwords. This is not ethic. You put at risk your members who uses same account information in somewhere else.
Try using a database which is stronger and faster than a text file.

How can I read a value from an INI file in C#?

I have an INI file that I want to read the line DeviceName=PHJ01444-MC35 from group [DEVICE] and assign the value to a string.
[BEGIN-DO NOT CHANGE/MOVE THIS LINE]
[ExecList]
Exec4=PilotMobileBackup v1;Ver="1.0";NoUninst=1
Exec3=MC35 108 U 02;Ver="1.0.8";NoUninst=1
Exec2=FixMGa;Ver="1.0";Bck=1
Exec1=Clear Log MC35;Ver="1.0";Bck=1
[Kiosk]
Menu8=\Program Files\PilotMobile\Pilot Mobile Backup.exe
MenuCount=8
AdminPwd=D85F72A85AE65A71BF3178CC378B260E
MenuName8=Pilot Mobile Backup
Menu7=\Windows\SimManager.exe
MenuName7=Sim Manager
UserPwd=AF2163B24AF45971
PasswordPolicy=C34B3DE916AA052DCB2A63D7DCE83F17
DisableBeam=0
DisableBT=0
DisableSDCard=0
EnableAS=1
ActionCount=0
Url=file://\Application\MCPortal.htz
AutoLaunch=0
Menu6=\Windows\solitare.exe
MenuName6=Solitare
Menu5=\Windows\bubblebreaker.exe
MenuName5=Bubble Breaker
Menu4=\Windows\wrlsmgr.exe
MenuName4=Communications
Menu3=\Windows\Calendar.exe
MenuName3=Calendar
Menu2=\Windows\tmail.exe
MenuName2=Text Messaging
Menu1=\Program Files\PilotMobile\Pilot.Mobile.exe
MenuName1=Pilot Mobile
ShowStartMenu=1
CustomTaskBar=0
IdleTimeout=0
NoTaskbar=0
PPCKeys=1111111111111111
On=1
[Status]
MCLastConn=2006/10/01 00:50:56
[Connection]
DeploySvr1=********
[Locations]
Backup=Backup
Install=\Application
[Comm]
RetryDelay=60000
NoInBoundConnect=0
TLS=0
Broadcast=1
[Info]
LID=090128-117
PWDID=081212-10
TimeSyncID={249CEE72-5918-4D18-BEA8-11E8D8D972BF}
TimeSyncErrorInterval=5
TimeSyncInterval=120
AutoTimeSync=1
SecondarySNTPServer=ntp1.uk.uu.net
DefaultSNTPServer=ntp0.uk.uu.net
DepServerTimeSyncType=4
TimeSyncServerType=1
DFID=080717-8
Platform=PPC
Method=39
SiteName=*****
[Device]
SyncTimer=4
Ver=1
DeviceID={040171BD-3603-6106-A800-FFFFFFFFFFFF}
ShowTrayIcon=1
DeviceIDType=2
DeviceClass=AADE7ECE-DF8C-4AFC-89D2-DE7C73B579D0
DeviceName=PHJ01444-MC35
NameType=2
[END-DO NOT CHANGE/MOVE THIS LINE]
You could use Windows API for this. See http://jachman.wordpress.com/2006/09/11/how-to-access-ini-files-in-c-net/
Edit: As noted in the comments the page is no longer available on the original site, however it's still accessible on the Wayback Machine.
Additionally there is a more recent article on MSDN about accessing the required functions.
Because writing everything in one line makes me a better person than you:
string s = File.ReadAllText("inifile.ini").Split('\r', '\n').First(st => st.StartsWith("DeviceName"));
If you wanted the very simple but not very clean answer:
using System.IO;
StreamReader reader = new StreamReader(filename);
while(reader.ReadLine() != "[DEVICE]") { continue; }
const string DeviceNameString = "DeviceName=";
while(true) {
string line = reader.ReadLine();
if(line.Length < DeviceNameString.Length) { continue; }
else if(line.Substring(0, DeviceNameString.Length) != DeviceNameString) { continue; }
return line.Substring(DeviceNameString.Length);
}
If you're only intending to read one value from the file, it's a plausible option. I would probably combine the loops and add for some end of file checking though myself if you're serious about using this code.
string line;
string deviceName = string.Empty;
// Read the file and display it line by line.
using (System.IO.StreamReader file =
new System.IO.StreamReader("c:\\file.ini"))
{
while ((line = file.ReadLine()) != null)
{
if (line.ToLower().StartsWith("devicename"))
{
string[] fullName = line.Split('=');
deviceName = fullName[1];
break;
}
}
}
Console.WriteLine("Device Name =" + deviceName);
Console.ReadLine();
I am sure there are other ways.

Categories

Resources