簡體   English   中英

從 C# 中的文本文件一次讀取 10 行

[英]Read 10 lines at a time from text file in C#

我正在尋找一種解決方案,從文本文件中讀取 10 行,然后再讀取 10 行,直到文件末尾。 這是我開始的,當然它顯示了前 10 行,但是我怎樣才能在接下來的 10 行中重復這個過程等等,直到文件結束?

private void openFile_Click(object sender, EventArgs e)
{
    int counter = 0;
    string line;

    using (var file =
       new System.IO.StreamReader(@"C:\\Users\\LJ_TEX\\Desktop\\Book1.txt"))
    {
        while ((line = file.ReadLine()) != null)
        {
            counter++;
            if (counter <= 10)
            {
                tboxreadData.AppendText(line + '\r' + '\n');
            }
            if (counter == 10)
            {
                tboxreadData.AppendText("NEXT");
            }
        }
    }
}

編輯

所以我設法做了一點改變,點擊按鈕顯示一行

 System.IO.StreamReader file = null;

 private void openFile_Click(object sender, EventArgs e)
    {
        string line;

        if (file == null)
            file = new System.IO.StreamReader(@"C:\\Users\\LJ_TEX\\Desktop\\Book1.txt");

        if (!file.EndOfStream)
        {
            line = file.ReadLine();
            tboxreadData.AppendText(line + '\r' + '\n');
        }
        else
        {
            tboxreadData.AppendText("End");
        }
       
    }

當然,它一次只顯示一條線。 如果有人知道如何顯示更多行(5 或 10 行),請隨時分享。

謝謝,喬納森

您可以通過使用模運算符 (%) 來實現。 所以你檢查你的counter%10=0是否打印出“NEXT”-Line。

您的示例可能如下所示:

private void openFile_Click(object sender, EventArgs e)
    {
        int counter = 0;
        string line;

        System.IO.StreamReader file = new System.IO.StreamReader(@"C:\\Users\\LJ_TEX\\Desktop\\Book1.txt");

        while ((line = file.ReadLine()) != null)
        {
            counter++;               
            tboxreadData.AppendText(line + '\r' + '\n');
            if(counter%10 == 0){
                tboxreadData.AppendText("NEXT");
            }
        }
    }

編輯:

對於每次讀取 10 行(如果存在),您可以使用以下代碼段。 它不是高性能的,因為您每次都會從頭開始閱讀:

int _lineCounter = 0;

private void openFile_Click(object sender, EventArgs e)
    {
        int counter = 0;
        string line;

        System.IO.StreamReader file = new System.IO.StreamReader(@"C:\\Users\\LJ_TEX\\Desktop\\Book1.txt");

        while ((line = file.ReadLine()) != null)
        {
            counter++;
            if(counter < _linecounter)
                continue;
            tboxreadData.AppendText(line + '\r' + '\n');
            if(counter%10 == 0){
                tboxreadData.AppendText("NEXT");
                break;
            }
        }
        _lineCounter = counter;
    }

您可以創建自己的擴展方法,該方法采用IEnumerbale<T>並將其划分為塊。 從那里您可以使用foreach或任何標准 linq 樣式鏈方法對其進行迭代

給定

// updated, this is completely lazy loaded
public static class Extensions
{
   public static IEnumerable<IEnumerable<TValue>> Partition<TValue>(this IEnumerable<TValue> source, int size)
   {
      using var enumerator = source.GetEnumerator();
      static IEnumerable<T> GetChunk<T>(IEnumerator<T> enumerator, int chunkSize)
      {
         for (var i = 0; i < chunkSize && enumerator.MoveNext(); i++)
            yield return enumerator.Current;
      }

      while (enumerator.MoveNext())
         yield return GetChunk(enumerator, size);
   }
}

用法

var partitions = File
     .ReadLines(@"D:\ids.txt")
     .Partition(10);

foreach (var partition in partitions)
{
   Console.WriteLine("Start partition");
   foreach (var line in partition )
      Console.WriteLine(line);
}

Output

Start partition
1516556 E763794 1773595 33EBM5015703
1516556 E763794 1773657 33EBM5015703
1518933 E764710 1776347 33EBM5015705
1519147 H182989 1776617 33EBM5015702
1519264 H183025 1776745 33EBM5015686
1519310 X186946 1776805 33EBM5015695
1519622 X186992 1777159 33EBM5015704
1519623 E765015 1777160 33EBM5015716
1519818 H183205 1777375 33EBM5015681
1519932 E765141 1777546 33EBM5015700
Start partition
1520345 E765295 1778070 33EBM5015715
1520366 E765303 1778097 33EBM5015684
1520385 X187075 1778117 33EBM5015675
1520420 H183413 1778157 33EBM5015662
1520429 H183418 1778166 33EBM5015654
1520466 X187085 1778203 33EBM5015663
1520468 E765345 1778205 33EBM5015658
1520476 E765349 1778214 33EBM5015677
1520486 H183441 1778224 33EBM5015664
1520496 H183444 1778234 33EBM5015671
Start partition
1520506 E765361 1778244 33EBM5015666
1520510 E765364 1778248 33EBM5015670
1520528 H183462 1778270 33EBM5015680
1520550 H183474 1778292 33EBM5015653
1520553 X187092 1778295 33EBM5015706
1520558 E765382 1778300 33EBM5015650
1520574 E765389 1778316 33EBM5015656
1520585 E765396 1778327 33EBM5015669
1520618 X187102 1778360 33EBM5015682
1520621 E765408 1778363 33EBM5015667

你想要的很常見:你想“每頁”閱讀你的輸入。

換句話說:你有一系列相似的項目,你想把它分成大小相等的子組。

如果您將定期使用它,請考慮為其創建一些類。 這樣,您可以將它用於需要“每頁”獲取項目的幾個問題。

我經常使用它從每頁的數據庫中獲取項目。 由於通用類,我可以將 IQueryable / IEnumerable 放入 PageCollection class 並詢問頁數和 Page[3]。

如果你做的很聰明,你就不必獲取你不使用的項目,也不需要重新獲取你已經獲取的項目。

我們隱藏頁面的內部。 因此我們創建了一個接口:

interface IPage<T> : IReadOnlyCollection<T>, IEnumerable<T>
{
    int PageNr {get; }             // the zero based number of the page
    int PageCount {get; }          // the total number of available pages
    int PageLength {get; }         // The number of items on this page

我選擇實現IReadOnlyCollection<T>而不是IReadOnlyList<T> ,因為索引通常給人的印象不正確。

例如,如果您有一個ProductPages集合,那么每個ProductPage都有零個或多個Products 但是,如果您在ProductPage[10]上並要求Product[3] ,您會期待什么? 有些人可能會將其與具有主鍵 3 的Product混淆。

也許以下方法也可能很方便:

    IPage<T> PreviousPage {get;}
    IPage<T> NextPage {get;}
    IPage<T> GetPage(int pageNr);
    IReadOnlyList<T> PageCollection {get;}
}

首先讓我們創建 PageCollection。 PageCollection 將創建頁面:

class PageCollection<T> : IReadOnlyList<T>
{
    private readonly IDictionary<int, IPage<T>> fetchedPages
        = new Dictionary<int, IPage<T>();

    private int pageCount = -1; // not known yet

    public PageCollection<IEnumerable<T> query, pageSize)
    {
        // TODO: check input parameters for incorrect values
        this.Query = query;
        this.PageSize = pageSize;
    }

    public IEnumerable<T> Query {get;} 
    // TODO: consider IQueryable if you use databases / entity framework

    public int PageSize {get;}
    ...
}

我們需要一些方法來獲取頁面的數量,並通過索引來獲取頁面:

public int Count
{
    get
    {
        if (this.pageCount < 0)
           this.pageCount = this.Query.Count();
        return this.pageCount;
    }
}

public IPage this[int pageIndex] => this.GetPage(pageIndex);

最后我們來到創建頁面的部分:

public IPage<T> GetPage(int pageIndex)
{
    if (0 < pageIndex || pageIndex >= this.Count)
    {
        // pageIndex out of range.
        // TODO: decide whether to return null or throw exception
    }

    if (!this.fetchedPages.TryGetValue(pageIndex, out Page<T> fetchedPage)
    {
        // page never fetched before, fetch it now
        fetchedPage = this.FetchPage(pageIndex);
        this.FetchedPages.Add(pageIndex, fetchedPage);
    }
    return fetchedPage;
}

我決定將獲取的頁面保存在字典中,而不是列表中。 這樣,您可以在獲取頁面 0 到 4 之前請求 Page[5]。

private Page<T> FetchPage(int pageIndex)
{
    return new Page(this, pageIndex);
}

好吧,這並沒有多大作用:顯然它是完成所有工作的頁面。 是時候創建頁面了。

您必須自己決定是立即閱讀完整頁面,還是僅在您要求時閱讀

class Page<T> : IPage<T>, IReadOnlyCollection<T>, IEnumerable<T>
{
    public Page(PageCollection<T> pageCollection, int pageNr)
    {
         this.PageCollection = pageCollection;
         this.PageNr = pageNr;

         // if you want to fetch the data immediately:
         this.PageContent = this.Query.ToList();
    }

    public PageCollection<T> PageCollection {get;}
    public int PageNr {get;}
    public int PageCount => this.PageCollection.Count;
    public IReadOnlyCollection<T> PageContent {get;}

    public IEnumerable<T> Query => this.PageCollection.Query
        .Skip(this.PageNr * this.PageSize)
        .Take(this.PageSize);
}

IReadOnlyCollection<T>IEnumerable<T>的實現相當簡單,方法都調用this.PageContent

IEnumerator<T> GetEnumerator() {return this.PageContent.GetEnumerator();}
int Count => this.PageContent.Count;

等等

像 PreviousPage / NextPage / GetPage 這樣的“很高興”過程是單行的,因為它們可以通過詢問 PageCollection 來處理:

IPage<T> PreviousPage => this.PageCollection.GetPage(this.PageNr-1);

當然,您必須決定如果 Page 超出范圍該怎么辦:異常還是返回 null?

最后使用:

const int pageSize = 25;
IEnumerable<Product> queryProducts = ...
PageCollection<Product> productPages =
   new PageCollection<Product>(queryProducts, pageSize);

Page<Product> productPage = productPages.FirstOrDefault();
// this page can be used as a collection of Products
DisplayProducts(productPage);

// get the next page:
Page<Product> nextPage = productPage.NextPage;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM