C# 如何使用StreamReader并读取文本文件的某些部分?
我正在尝试建立一个已经完成注册的登录系统。我想让它成为您按下登录按钮,然后它使用StreamReader读取已使用我的注册表单更新的文件的地方。问题是,我已经构建了文件的编写方式(例如:当用户输入其详细信息时,它会在我的注册表单中使用StreamWriter将其详细信息保存在类似Username:johndoe Password:Password1的结构中)。但当我使用StreamReader时,它会读取整行内容,而不是某些部分。如何只读取文本文件的某些部分 注册表格代码:C# 如何使用StreamReader并读取文本文件的某些部分?,c#,visual-studio,winforms,C#,Visual Studio,Winforms,我正在尝试建立一个已经完成注册的登录系统。我想让它成为您按下登录按钮,然后它使用StreamReader读取已使用我的注册表单更新的文件的地方。问题是,我已经构建了文件的编写方式(例如:当用户输入其详细信息时,它会在我的注册表单中使用StreamWriter将其详细信息保存在类似Username:johndoe Password:Password1的结构中)。但当我使用StreamReader时,它会读取整行内容,而不是某些部分。如何只读取文本文件的某些部分 注册表格代码: bo
bool valid = true;
List<string> errorMessages = new List<string>();
if (string.IsNullOrWhiteSpace(txtUsername.Text))
{
valid = false;
errorMessages.Add("Username cannot be left empty.");
}
if (string.IsNullOrWhiteSpace(txtPassword.Text))
{
valid = false;
errorMessages.Add("Please enter a password.");
}
if (txtConfirmPass.Text != txtPassword.Text)
{
valid = false;
errorMessages.Add("Passwords do not match. Please enter matching passwords.");
}
if (valid == false)
{
string message = string.Join(Environment.NewLine, errorMessages);
MessageBox.Show(message, "Validate Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else if(valid == true)
{
Random rnd = new Random();
string userID = rnd.Next(0, 100000).ToString("D6");
//Use StreamWriter class.
using (StreamWriter sw = new StreamWriter("Test.txt", true))
{
sw.Write("\n" + "UserID: " + userID + "\n");
sw.Write("Username: " + txtUsername.Text + "\n");
sw.Write("Password: " + txtPassword.Text + "\n");
sw.Write("------------------------------------");
MessageBox.Show("Details have been saved");
frmLogin login = new frmLogin();
login.Show();
this.Hide();
}
}
您可以尝试在StreamReader中使用
ReadLine()
方法,如下图所示,您应该跟踪第2行包含用户名,第3行包含密码。此外,您应该使用Regex
拆分并从文本中获取值,或者可以使用:
分隔符并在比较之前修剪值
using (StreamReader sr = new StreamReader(path))
{
int counter = 0;
while (sr.Peek() >= 0)
{
string content = sr.ReadLine();
var userName = content.split(':')[1].trim()...
counter++;
}
}
注意:
StreamReader直接读取文件,因此您必须执行字符串操作。相反,您还可以考虑其他方法,如缓存或数据库操作,以跨页/窗口持久化值。 < P>是否要检查用户是否已经通过遍历TXT文件输入了正确的用户名和密码? 测试信息结构:
UserID: 016696
Username: kkk
Password: p123
这里有一个简单的例子,你可以参考
private void btnLogin_Click(object sender, EventArgs e)
{
string username = "";
string password = "";
bool ischecked = false; // check if the Username line is read
bool loginsuccess = false; // check if succeed
string line;
// Read the file and display it line by line.
System.IO.StreamReader file = new System.IO.StreamReader("Test.txt");
while ((line = file.ReadLine()) != null)
{
// if true, this is password line
if (ischecked)
{
// get password
// call Trim to remove extra spaces
password = line.Split(':')[1].Trim();
// check username and password
if (txtUsername.Text == username && txtPassword.Text == password)
{
MessageBox.Show("Login Successfully");
loginsuccess = true; // login in success
break;
}
// reset boolean
ischecked = false;
}
// read Username line, next line is the corresponding password
if (line.Split(':')[0] == "Username")
{
username = line.Split(':')[1].Trim();
// set boolean to true
ischecked = true;
}
}
file.Close();
// login failed
if(!loginsuccess)
{
MessageBox.Show("Wrong username or password");
}
}
您的代码有问题,因为您想在一个方法中做太多的事情。你应该 在您的情况下:您不应该将与运算符的通信与输入数据序列化的方式混为一谈 如果将HMI与保存和读取输入的方式分开:
- 更易于重用:如果需要读取保存的登录数据,无需再次向操作员询问:只需读取即可
- 更容易更改:如果您想要不同的HMI,您仍然可以以原始格式保存。如果您想以加密格式保存,您的HMI不需要更改
- 易于测试:您可以通过单元测试保存/读取文件,而无需操作员输入
class User
{
public int Id {get; set;}
public string Name {get; set;}
public string Password {get; set;}
}
用户人机界面
在HMI中显示用户,或从HMI获取用户。在你的课堂上:
public User ReadUser()
{
return new User
{
Id = this.CreateUserId(),
Name = this.txtUserName.Text,
Password = this.txtPassword.Text,
};
}
// not sure if you need this:
public void DisplayUser(User user)
{
this.txtUserName.Text = user.Name,
this.txtPassword.Text = user.Password,
}
考虑创建一个属性:
public User User
{
get => new User {Id = this.CreateUserId(), ...},
set
{
this.txtUserName.Text = value.Name,
...
}
}
如果将来您希望以不同的方式显示用户,比如在DataGridView或组合框中,那么只有一个地方需要实现更改
序列化用户
我的建议是坚持使用常见格式,如CSV、XML、JSon。这将使您的生活更加轻松,因为您可以使用NUGET软件包来实现这一点
如果您无法说服项目负责人这将是一个更好的解决方案,而他仍然希望您使用自己发明的格式,那么您需要两种方法:
public void Serialize(User user, string fileName)
{
using (var textWriter = System.IO.File.CreateText(fileName, ...))
{
... // see your own code
}
}
顺便问一下:你为什么写“`\n,为什么不使用
反序列化用户
当前,您的文件具有以下布局:
- 空行
- 带有“UserId:+Id”的行
- 带有“用户名:”+名称的行
- 带有“Password:+Password”的行
公共用户反序列化(字符串文件名)
{
使用(var textReader=System.IO.File.OpenText(文件名,…)
{
字符串emptyLine=textReader.ReadLine();
if(emptyLine==null)
…//TODO:决定如果文件格式无效该怎么办。异常
}string txtId = textReader.ReadLine(); if (txtId == null) ... // TODO: decide what to do if invalid file format int id = Int32.Parse(txtId); // TODO: handle invalid txtId format. Exception? string name = textReader.ReadLine(); string password = textReader.ReadLine(); // TODO: handle invalid name / password; return new User { Id = id, Name = name, Password = password, } }
string txtId = textReader.ReadLine();
if (txtId == null)
... // TODO: decide what to do if invalid file format
int id = Int32.Parse(txtId);
// TODO: handle invalid txtId format. Exception?
string name = textReader.ReadLine();
string password = textReader.ReadLine();
// TODO: handle invalid name / password;
return new User
{
Id = id,
Name = name,
Password = password,
}
}