【问题标题】:While loop only iterates twice through an array with 4 elementsWhile 循环仅在具有 4 个元素的数组中迭代两次
【发布时间】:2015-05-19 05:16:11
【问题描述】:
        StreamReader sr = new StreamReader(path);
        String contents = "LINE";

        while (!string.IsNullOrWhiteSpace(contents)) 
        {
            contents = sr.ReadLine();

            foreach (TSPlayer plr in newPlayers.Keys) 
            {
                if (plr.Name.ToLower() == contents.ToLower() || plr.UserAccountName.ToLower() == contents.ToLower())
                {
                    TShock.Utils.ForceKick(plr, "Bad name. GO AWAY!");
                    newPlayers.Remove(plr);
                }
            }
        }

        sr.Close();      

我正在从一个包含 4 行的文本文件中读取所有值(没有空行)。上面的 while 循环只从文件中读取前 2 个值,然后停止。

在将文件内容拆分为“\n”后,我尝试使用常规 For 循环和 Foreach 循环,但发生了同样的事情。

我不知道为什么会这样。我确定该数组有 4 个元素,因为我在索引处手动显示了值(例如,内容 [2])。所以它是从文件中正确读取的。

只是每当我尝试访问它停止的第三个值时。

感谢您的帮助,非常感谢。

【问题讨论】:

  • 您的文件中可能有一个空行,或者一行仅包含空格或制表符。试试:var lines = File.ReadLines(path).Where(l => !string.IsNullOrWhiteSpace(l)).ToArray(); 看看你有多少行。

标签: c# file logic


【解决方案1】:

MSDN 这么说

返回值
类型:System.String
输入流的下一行,如果到达输入流的末尾,则为 null。

https://msdn.microsoft.com/en-us/library/system.io.streamreader.readline(v=vs.110).aspx

你拥有的是

while (!string.IsNullOrWhiteSpace(contents)) 
{
    contents = sr.ReadLine();

如果文件的第三行只是空格,那么你的循环将退出,它应该是什么可能只是

while (contents != null)

【讨论】:

  • 我明白你的意思。文本文件不包含任何空白行,但我已合并您的建议。它仍然不起作用。 :(
  • 如果不是空格,那么我会在调试器中运行程序(或使用下面的 linq)。如果 TShock.Utils.ForceKick 执行 Environment.Exit() 之类的操作或抛出异常,也可以简单地停止执行。调试该方法并查看它在哪一行停止。
  • 我在while循环的顶部放了一个debug来测试它。在第三次迭代时它没有达到调试。我认为 TShock.Utils.ForceKick() 不会停止代码,因为第一次和第二次迭代在测试时工作得很好。 TShock.Utils.ForceKick() 虽然已经过时了。它说“TShockAPI.Utils.ForceKick(TShockAPI.TSPlayer, string)”已过时:“此方法仅用于外部代码的签名兼容性”。我不知道这是什么意思:/
  • 进入循环体并找出它在哪一行停止。调试器应该允许你调试第二次迭代应该让你看到你停止在循环体中的哪一行。我不确定 TShock API 是什么,但您应该查看文档以查看替换它的方法。过时的 API 意味着您应该停止使用它们,因为它们不再受支持。
【解决方案2】:

while (!string.IsNullOrWhiteSpace(contents)) 行可能存在逻辑问题。我怀疑你有空格。

您的代码中还有一个逻辑问题,当您有 null 或空格时,它必须运行一次才能退出。

最好避免这种循环并使用 LINQ 编写代码。

试试这个:

var lines = new HashSet<string>(
    File
        .ReadAllLines(path)
        .Select(line => line.Trim().ToLower())
        .Where(line => !string.IsNullOrWhiteSpace(line)));

var matches =
    from plr in newPlayers
    let name = plr.Key.Name.ToLower()
    let userAccountName = plr.Key.UserAccountName.ToLower()
    where lines.Contains(name) || lines.Contains(userAccountName)
    select plr.Key;

foreach (var plr in matches.ToArray())
{
    TShock.Utils.ForceKick(plr, "Bad name. GO AWAY!");
    newPlayers.Remove(plr);
}

【讨论】:

  • 我使用了您的代码,但没有任何改变。我的 sn-p 代码也在一个每 2.5 秒运行一次的计时器中。这有关系吗?还是无关紧要?
  • @Davinatoratoe - 它应该可以正常工作。计时器无关紧要。当你说什么都没有改变时,你的意思是它在两行之后也停止了吗?
  • @Davinatoratoe - 那么我认为您需要发布文件的内容。我的代码应该返回所有有效的行。当你运行它时,你能检查一下我的代码中的lines 哈希集中有多少元素吗?
猜你喜欢
  • 2020-07-19
  • 1970-01-01
  • 2015-02-24
  • 2020-06-08
  • 2013-10-07
  • 2015-09-20
  • 2016-06-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多