将 C# ReadLine() 前进到函数调用中的下一行

发布于 2024-08-06 10:16:15 字数 628 浏览 6 评论 0 原文

在我的 C# 应用程序中,我尝试向 ReadLine() 提供一个简单的文本文档,其中包含逐行分隔的 7 个数字字符串。我试图做的是每次调用该函数时获取接下来的 7 位数字字符串。这是我到目前为止所得到的:

string invoiceNumberFunc()
    {
        string path = @"C:\Users\sam\Documents\GCProg\testReadFile.txt";
        try
        {
            using (StreamReader sr = new StreamReader(path))
            {
                invoiceNumber = sr.ReadLine();

            }

        }
        catch (Exception exp)
        {
            Console.WriteLine("The process failed: {0}", exp.ToString());
        }
       return invoiceNumber;
    }

每次调用invoiceNumberFunc() 时如何前进到下一行?

提前致谢。

In my C# app I'm trying to feed into ReadLine() a simple text document with 7 digit strings separated line by line. What I'm attempting to do is grab the next 7 digit string each time the function is called. Here's what I have so far:

string invoiceNumberFunc()
    {
        string path = @"C:\Users\sam\Documents\GCProg\testReadFile.txt";
        try
        {
            using (StreamReader sr = new StreamReader(path))
            {
                invoiceNumber = sr.ReadLine();

            }

        }
        catch (Exception exp)
        {
            Console.WriteLine("The process failed: {0}", exp.ToString());
        }
       return invoiceNumber;
    }

How do I advance to the next line each time the invoiceNumberFunc() is called?

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

只有一腔孤勇 2024-08-13 10:16:15

您需要在调用之间保留 StreamReader,要么将其作为新参数传递到方法中,要么将其作为类的成员变量。

就我个人而言,我更喜欢它成为一个参数的想法,这样它就永远不会成为一个成员变量——这使得生命周期更容易管理:

void DoStuff()
{
    string path = @"C:\Users\sam\Documents\GCProg\testReadFile.txt";
    using (StreamReader sr = new StreamReader(path))
    {
        while (keepGoing) // Whatever logic you have
        {
            string invoice = InvoiceNumberFunc(sr);
            // Use invoice
        }
    }
}

string InvoiceNumberFunc(TextReader reader)
{
    string invoiceNumber;
    try
    {
        invoiceNumber = reader.ReadLine();
    }
    catch (Exception exp)
    {
        Console.WriteLine("The process failed: {0}", exp.ToString());
    }
    return invoiceNumber;
}

You'd need to keep hold of the StreamReader between calls, either passing it into the method as a new parameter or making it a member variable of the class.

Personally I prefer the idea of it becoming a parameter, so that it never ends up as a member variable - that makes the life-time easier to manage:

void DoStuff()
{
    string path = @"C:\Users\sam\Documents\GCProg\testReadFile.txt";
    using (StreamReader sr = new StreamReader(path))
    {
        while (keepGoing) // Whatever logic you have
        {
            string invoice = InvoiceNumberFunc(sr);
            // Use invoice
        }
    }
}

string InvoiceNumberFunc(TextReader reader)
{
    string invoiceNumber;
    try
    {
        invoiceNumber = reader.ReadLine();
    }
    catch (Exception exp)
    {
        Console.WriteLine("The process failed: {0}", exp.ToString());
    }
    return invoiceNumber;
}
如何视而不见 2024-08-13 10:16:15

您不能,因为您在函数中创建并处置了流读取器。我想到了两种方法:

您可以将流读取器存储在成员变量中,或者一次读取所有内容并将数组存储在成员变量中。

或者,您可以通过将返回类型更改为 IEnumerable 并将 using 块中的部分更改为:

while ((invoiceNumber = sr.ReadLine()) != null) {
    yield return invoiceNumber;
}

这样,您可以调用 invoiceNumberFunc 上的 >foreach。

You can't, since you create and dispose the stream reader in the function. Two ways come to mind:

You could store the stream reader in a member variable, or read all at once and store an array in a member variable.

Or you make it an iterator method by changing the return type to IEnumerable<string>, and changing the part in the using block to:

while ((invoiceNumber = sr.ReadLine()) != null) {
    yield return invoiceNumber;
}

This way, you can call foreach on your invoiceNumberFunc.

爱给你人给你 2024-08-13 10:16:15

您需要使用相同的 StreamReader,而不是创建一个新的 StreamReader。每次创建新文件并处理旧文件时,您都会从文件的开头开始。

尝试传递相同的 StreamReader 引用或记录您在流中所处的位置,并在必要时在基本流上使用 Seek() 。我个人推荐第一个。

You need to use the same StreamReader rather than creating a new one. Each time you create a new one and dispose of the old one you're starting right back at the start of the file.

Try passing the same StreamReader reference in or keeping a record of the position you are at in the stream and using Seek() on the base stream if necessary. I'd recommend the first of these personally.

爱冒险 2024-08-13 10:16:15

您需要重新处理它,以便您不在方法内创建流读取器,而是在类级别创建它,并仅在方法中使用它,然后在完成后处置/关闭读取器。类似于:

class MyClass
{
    private StreamReader sr;

    string invoiceNumberFunc()
    {
        if (sr == null) 
            sr = new StreamReader(path);

        if (sr.EndOfStream)  {
            sr.Close();
            sr = null;
            return string.Empty;
        }

        try {
            return sr.ReadLine();
        }
        catch(Exception exp) {
            Console.WriteLine("Process failed {0}",exp.ToString());
            return string.Empty;
        }
    }
}

在这种情况下,将您的类设置为 IDisposable 也可能是一个好主意,这样您就可以验证 StreamReader 是否已被释放,并且还可能创建“初始化”/“关闭”例程我在这里所做的初始化和关闭。

You need to rework this, so that you're not creating the streamreader inside the method, but rather creating it at the class level, and just using it in the method, then disposing/closing the reader when you are done. Something like:

class MyClass
{
    private StreamReader sr;

    string invoiceNumberFunc()
    {
        if (sr == null) 
            sr = new StreamReader(path);

        if (sr.EndOfStream)  {
            sr.Close();
            sr = null;
            return string.Empty;
        }

        try {
            return sr.ReadLine();
        }
        catch(Exception exp) {
            Console.WriteLine("Process failed {0}",exp.ToString());
            return string.Empty;
        }
    }
}

In this case, it might also be a good idea to make your class IDisposable so you can verify that the StreamReader gets disposed, and also potentially make "initialize"/"close" routines, instead of doing the initialize and shutdown how I did here.

野侃 2024-08-13 10:16:15

您正在寻找的是 yield 命令:-

IEnumerable<string> GetInvoiceNumbers()
{
    string path = @"C:\Users\sam\Documents\GCProg\testReadFile.txt";
    using (StreamReader sr = new StreamReader(path))
    {
        while (!sr.EndOfStream)
        {
           yield return sr.ReadLine();
        }
    }
}

现在您可以通过简单的 foreach 来使用此函数的返回值:-

foreach(string invoiceNumber in GetInvoiceNumbers())
{
   //Do Stuff with invoice number
}

或者使用 LINQ 发挥创意。

What you are looking for is the yield command:-

IEnumerable<string> GetInvoiceNumbers()
{
    string path = @"C:\Users\sam\Documents\GCProg\testReadFile.txt";
    using (StreamReader sr = new StreamReader(path))
    {
        while (!sr.EndOfStream)
        {
           yield return sr.ReadLine();
        }
    }
}

Now you can consume the return of this function with a simple for each:-

foreach(string invoiceNumber in GetInvoiceNumbers())
{
   //Do Stuff with invoice number
}

Or get creative with LINQ.

深海少女心 2024-08-13 10:16:15

另一种方法是使用 yield 在迭代器块中转换函数return 语句

唯一的事情是确保在 try 中添加一个finaly 子句并删除catch,因为yield return 不能在裸try / catch 中使用。所以你的代码将变成:

    IEnumerable<String> invoiceNumberFunc()
    {
        string path = @"C:\Users\sam\Documents\GCProg\testReadFile.txt";
        try
        {
            using ( System.IO.StreamReader sr = new System.IO.StreamReader( path ) )
            {
                String invoiceNumber;
                while ( ( invoiceNumber = sr.ReadLine() ) != null )
                {
                    yield return sr.ReadLine();
                }
            }
        }
        finally
        {
        }
    }

An other way of doing this is to transform your function in an iterator block using the yield return statement

The only thing is to make sure you add a finaly clause to your try and remove the catch as the yield return cannot be used in a naked try / catch. So your code would become:

    IEnumerable<String> invoiceNumberFunc()
    {
        string path = @"C:\Users\sam\Documents\GCProg\testReadFile.txt";
        try
        {
            using ( System.IO.StreamReader sr = new System.IO.StreamReader( path ) )
            {
                String invoiceNumber;
                while ( ( invoiceNumber = sr.ReadLine() ) != null )
                {
                    yield return sr.ReadLine();
                }
            }
        }
        finally
        {
        }
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文