【问题标题】:Cannot find txt file StreamReader找不到 txt 文件 StreamReader
【发布时间】:2018-06-20 11:17:45
【问题描述】:

'未处理的异常:

System.IO.FileNotFoundException:找不到文件“/Logins.txt”发生'

您好,新手在 xamarin c# 中制作了一个非常基本的登录/注册系统,该系统使用 Systsem.IO 中的 StreamReader 来读取存储了用户名和密码的文本文件。 txt 文件与 .cs 文件本身位于同一目录中,并且在解决方案资源管理器中可见。 我尝试输入完整路径但没有成功,并以管理员身份运行,以防万一它与权限有关。 有什么问题吗?

public partial class LoginPage : ContentPage
{
    public LoginPage()
    {
        InitializeComponent();
    }
    List<string> user = new List<string>();
    List<string> pass = new List<string>();

    public void btnLogin_Clicked(object sender, EventArgs e)
    {
        //Read the txt
        StreamReader sr = new StreamReader("Logins.txt");
        string line = "";

        //Read every line until there is nothing in the next line
        while ((line = sr.ReadLine()) != null)
        {
            //Grab items within new lines separated by a space and chuck them into their array
            string[] components = line.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
            user.Add(components[0]);
            pass.Add(components[0]);
        }
        //Check entries are on the same line and match
        if (user.Contains(txtUsername.Text) && pass.Contains(txtPassword.Text) && Array.IndexOf(user.ToArray(), txtUsername.Text) == Array.IndexOf(pass.ToArray(), txtPassword.Text))
        {
            Navigation.PushModalAsync(new HomeScreen());
        }
        else
            DisplayAlert("Error", "The username or password you have entered is incorrect", "Ok");
    }
    private void Cancel_Clicked(object sender, EventArgs e)
    {
        Navigation.PushModalAsync(new MainPage());
    }
}

【问题讨论】:

  • 当前目录可能有误。
  • 将 .txt 文件放在可执行文件旁边,并确保从该目录运行应用程序
  • 将 Logins.txt 文件属性更改为 Embedded Resource
  • 在解决方案资源管理器中右键单击 txt 文件,然后单击属性。在此之后,将您的构建配置更改为嵌入式资源。
  • 已经尝试使用可执行文件旁边的 txt 来填充路径,使用 @"C:\---pathing---\AppAttempt\Logins.txt" 和 "Logins.txt"没有成功。嵌入式资源? (编辑:已将 txt 更改为嵌入式资源。这是做什么的?)

标签: c# xamarin.forms streamreader


【解决方案1】:

如果您将Logins.txt 文件更改为嵌入式资源,则可以在运行时从程序集中加载该资源,如下所示:

var assembly = IntrospectionExtensions.GetTypeInfo(typeof(LoginPage)).Assembly;
Stream stream = assembly.GetManifestResourceStream("YourAssembly.Logins.txt");
string text = "";
using (var reader = new System.IO.StreamReader (stream)) 
{
    text = reader.ReadToEnd();
}

YouAssembly 指的是在您构建项目时将生成的程序集 (dll) 的名称。如果您不知道这是什么,或者没有更改它,它很可能与项目同名。

Xamarin 文档有一个很好的例子来说明如何做到这一点:File Handling in Xamarin.Forms

编辑:

在构造函数中执行此操作的更完整示例,处理内容,以便您可以进行身份​​验证处理。

但首先,让我们定义一个 POCO 来保存用户名/密码详细信息:

public class UserCredentials
{
    public string Username {get;set;}
    public string Password {get;set;}
}

添加一个属性来保存这个类:

List<UserCredentials> CredentialList {get;set;}

现在,在构造函数中:

public LoginPage()
{
    InitializeComponent();

    // Read in the content of the embedded resource, but let's read 
    // each line to make processing a little easier
    var assembly = IntrospectionExtensions.GetTypeInfo(typeof(LoginPage)).Assembly;
    Stream stream = assembly.GetManifestResourceStream("YourAssembly.Logins.txt");
    var textLines = new List<string>();
    string line = null;
    using (var reader = new System.IO.StreamReader (stream)) 
    {
        while ((line = sr.ReadLine()) != null) 
        {
            textLines.Add(line);
        }
    }

    // Init our cred list
    this.CredentialList = new List<UserCredentials>();

    // Read out the contents of the username/password combinations
    foreach (var line in textLines)
    {
        // Grab items within new lines separated by a space and chuck them into their array
        string[] components = line.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries);

        // Add the combination to our list
        this.CredentialList.Add(new UserCredential 
        {
            Username = user.Add(components[0]),
            Password = pass.Add(components[0])
        });
    }
}

现在我们的登录变得容易多了。以前我们首先检查用户名/密码是否都存在于我们的已知数据集中,然后检查它们是否在两个列表中的相同索引处。

public void btnLogin_Clicked(object sender, EventArgs e)
{
    // Now can use linq to validate the user
    // NOTE: this is case sensitive
    if (this.CredentialList.Any(a => a.Username == txtUsername.Text && a.Password == txtPassword.Text))
    {
        // NOTE: you've only validated the user here, but aren't passing
        // or storing any detail of who the currently logged in user is
        Navigation.PushModalAsync(new HomeScreen());
    }
    else
    {
        DisplayAlert("Error", "The username or password you have entered is incorrect", "Ok");
    }
}

【讨论】:

  • 好吧,试着理解这一点。所以这应该在没有按钮的情况下运行?如果我需要将其放入自己的“空白区域”(如果有技术术语,则为 idk),我还需要添加拆分功能并参考它以进行检查? “你的程序集”应该是我的命名空间吗?
  • 我已经更新了答案。将此代码放在哪里实际上取决于访问它的频率以及一系列特定于您的用例的其他因素。也就是说,您可以将此加载代码放在LoginPage 的构造函数中,将每一行存储在List&lt;string&gt; 中。然后你的处理代码会做一个foreach (var theLine in _lines) { ... }
  • 这是否意味着我可以将它放在我的 InitialiseComponent 中?
  • 调用InitialiseComponent()之后,是的
  • 我添加了一个更完整的登录凭据加载示例,并在登录期间对凭据进行了更好的存储和处理。希望这会有所帮助
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多