【问题标题】:randomly select a line in a textfile c# streamreader随机选择文本文件中的一行c#streamreader
【发布时间】:2011-02-08 18:09:56
【问题描述】:

您好,我正在从文本文件中读取数据,并希望将每一行放入一个单独的变量中。从我的编程课程中我记得,数组不能是动态的。因此,如果我设置了 15 个数组,并且文本文件有 1000 行,我能做什么以及如何实现它。

问题是只需要一行,但我希望随机选择该行。 linetext 是在每个请求的末尾附加了 \r\n 的整个文本文件。

也许随机选择 \r\n 然后计数 4 并在其后添加字符串直到下一个 \r\n。这个想法的问题是被调用的字符串也会包含 \ 所以有什么想法吗?

if (crawler == true)
   {
            TextReader tr = new StreamReader("textfile.txt");
            while (tr.Peek() != -1)
            {
                linktext = linktext + tr.ReadLine() + "\r\n";
            }

            //link = linktext;

            hi.Text = linktext.ToString();

            timer1.Interval = 7000; //1000ms = 1sec 7 seconds per cycle
            timer1.Tick += new EventHandler(randomLink); //every cycle randomURL is called.
            timer1.Start(); // start timer.
        }

【问题讨论】:

  • 听起来您正在寻找List<String>
  • 我不太明白该代码示例与问题有何关联。
  • 对于另一种方法,您可以读取一个字符串并存储一个字符串。读取第 n 行时,以 1/n 的概率将其放入存储字符串中。当您读取文件时,存储字符串将包含一个随机行,每行具有相同的概率(随机数生成器的模均匀性问题)。

标签: c# .net streamreader inputstreamreader


【解决方案1】:

File.ReadAllLines(...) 会将给定文件的每一行读入字符串数组。我认为这应该是您想要的,但您的问题有点难以理解。

【讨论】:

    【解决方案2】:

    您不需要一次在内存中保留超过两行...您可以使用一个偷偷摸摸的技巧:

    • 创建一个 Random 实例,或将一个实例作为参数
    • 阅读第一行。这会自动成为要返回的“当前”行
    • 阅读第二行,然后拨打Random.Next(2)。如果结果为 0,则将第二行设为“当前”行
    • 阅读第三行,然后拨打Random.Next(3)。如果结果为 0,则将第三行设为“当前”行
    • ...等
    • 当您到达文件末尾时(reader.ReadLine 返回 null)返回“当前”行。

    这是IEnumerable<T> 的一般实现 - 如果您使用的是 .NET 4,则可以使用 File.ReadLines() 获取 IEnumerable<string> 以传递给它。 (这个实现比实际需要的要多一些 - 它针对IList<T> 等进行了优化。)

    public static T RandomElement<T>(this IEnumerable<T> source,
                                     Random random)
    {
        if (source == null)
        {
            throw new ArgumentNullException("source");
        }
        if (random == null)
        {
            throw new ArgumentNullException("random");
        }
        ICollection collection = source as ICollection;
        if (collection != null)
        {
            int count = collection.Count;
            if (count == 0)
            {
                throw new InvalidOperationException("Sequence was empty.");
            }
            int index = random.Next(count);
            return source.ElementAt(index);
        }
        ICollection<T> genericCollection = source as ICollection<T>;
        if (genericCollection != null)
        {
            int count = genericCollection.Count;
            if (count == 0)
            {
                throw new InvalidOperationException("Sequence was empty.");
            }
            int index = random.Next(count);
            return source.ElementAt(index);
        }
        using (IEnumerator<T> iterator = source.GetEnumerator())
        {
            if (!iterator.MoveNext())
            {
                throw new InvalidOperationException("Sequence was empty.");
            }
            int countSoFar = 1;
            T current = iterator.Current;
            while (iterator.MoveNext())
            {
                countSoFar++;
                if (random.Next(countSoFar) == 0)
                {
                    current = iterator.Current;
                }
            }
            return current;
        }
    }
    

    【讨论】:

    • 这是我最喜欢的技巧之一。当我在内存很少的机器上处理非常大的文件时,经常使用它。
    【解决方案3】:

    List&lt;T&gt; 是一个动态扩展的列表。您可能想使用它而不是数组。

    如果只有 1000 个元素,只需将它们读入列表并随机选择一个元素即可。

    【讨论】:

      【解决方案4】:

      关于数组的事情.. 你可以使用 List 代替,它是动态的

      这是一个如何实现的示例:

      public static string GetRandomLine(ref string file) {
          List<string> lines = new List<string>();
          Random rnd = new Random();
          int i = 0;
      
          try {
              if (File.Exists(file)) {
                  StreamReader reader = new StreamReader(file);
                  while (!(reader.Peek() == -1))
                      lines.Add(reader.ReadLine());
                  i = rnd.Next(lines.Count);
                  reader.Close();
                  reader.Dispose();
                  return lines[i].Trim();
              }
              else {
                  return string.Empty;
              }
          }
          catch (IOException ex) {
              MessageBox.Show("Error: " + ex.Message);
              return string.Empty;
          }
      }
      

      【讨论】:

        【解决方案5】:

        如果您创建文件,那么理想的方法是预先存储有关文件的元数据,例如行数,然后决定选择哪个“随机”行。

        否则,您无法通过不使用它们来解决“数组”问题。而是使用存储任意数量字符串的列表。之后选择一个随机数就像生成一个介于 0 和列表大小之间的随机数一样简单。

        您的问题之前已经解决过,我建议您在谷歌上搜索“C# read random line from file”。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-01-10
          • 1970-01-01
          • 1970-01-01
          • 2012-08-15
          • 2012-03-03
          相关资源
          最近更新 更多