如何在 C# 中正确处理空白行、空行或空行 [英] How to properly handle blank, null, or empty lines in C#

查看:284
本文介绍了如何在 C# 中正确处理空白行、空行或空行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些处理文本文件的 C# 代码,但我似乎无法让它与空白或空(空白)行一起正常工作.

I have some C# code that is working with a text file, and i can not seem to get it to work properly with blank or null (whitespace) lines.

我的代码:

        while (!file.EndOfStream)
        {
            line = file.ReadLine();

            bool isComment = (line[0] == '/') && (line[1] == '/');
            bool isPoint = (line[0] == '(') && (line[line.Length - 1] == ')');
            bool isWhiteSpace = string.IsNullOrEmpty(line);

            Debug.Log("Comment: " + isComment + ", Point: " + isPoint + ", WhiteSpace: " + isWhiteSpace + "Value: '" + line + "'");

            if (!isComment && !isPoint && !isWhiteSpace) { Application.Quit(); }
            else if (isPoint)
            {
                //Strip parenthesis
                line = line.Remove(line.Length - 1, 1).Remove(0, 1);

                //break into float array
                string[] arr = line.Split(',');

                float xVal = float.Parse(arr[0]);
                float yVal = float.Parse(arr[1]);
                float zVal = float.Parse(arr[2]);

                Vector3 currentVector = new Vector3(xVal, yVal, zVal);
                results.Add(currentVector);
            }
        }

你可以看到我碰巧在用 Vector3 做事.如果该行是注释行或空白行,我希望它什么都不做.如果它注意到括号,我希望它假设它是一个 Vector3 并解析它.最后,如果它不是这些线,我希望它完全停止.这是我仅使用记事本创建的示例文本文件:

You can see that i happen to be doing things with Vector3. If the line is a comment line or a whitespace line, i want it to do nothing. If it notices parentheses, i want it to assume it is a Vector3 and parse it. Finally, if it is a line that is none of these, i want it to stop entirely. Here is a sample text file that i have created just with Notepad:

//This is a comment
// ... and so is this!
(0, -1.5, 3)
(1, 4, 1.23)

(3, 5, 2)

请注意,第二个和第三个 Vector3 之间存在间隙.在这种特殊情况下,该行完全是空的,它不包含空格或任何内容,我只是在记事本中按了 [Enter][Enter].当我的脚本到达这一行时,它似乎触发了 file.EndOfStream 布尔值......但它不是文件的结尾!我怎样才能解决这个问题?我的 while 循环有更合适的条件吗?我也试过读入该行并检查它是否为空作为 while 条件,这是一种更流行的方法来解决这个问题,但这种做事方式也不适用于我的情况.

Notice that there is a gap between the second and third Vector3. In this particular case, the line is completely empty, it does not contain spaces or anything, i simply pressed [Enter][Enter] in Notepad. When my script reaches this line, it seems to trigger the file.EndOfStream boolean.... but its NOT the end of the file! How can i fix this? Is there a more appropriate condition for my while loop? I have also tried reading the line in and checking if it is null as the while condition, which is a more popular way to approach this, but this way of doing things also does not work for my case.

** 注意:"file" 是 StreamReader 类型的变量 **

** Note: "file" is a variable of type StreamReader **

推荐答案

这与其说是答案,不如说是一种风格注释,尽管这也可以避免您遇到的问题.

This is more of a style note than an answer, although this also will prevent the issues you were seeing.

首先,使用 StreamReader 当您调用 ReadLine 时,您只会在到达文件末尾时收到 null 结果.您也不关心行首和行尾的空格,并且大概也不关心完全是空格的行.所以你可以用它来测试文件结尾和空行:

First, with a StreamReader when you call ReadLine you will only receive a null result when you reach the end of the file. You also don't care about whitespace at the start and end of your lines, and presumably don't care about lines that are entirely whitespace either. So you can use that to test for end of file and empty lines this way:

string line;
while ((line = file.ReadLine()) != null)
{
    line = line.Trim();
    if (line == "")
        continue;
}

接下来,您将对开始/结束字符进行一些测试,这些测试在某些情况下仍会导致问题.具体来说,读取只有一个字符的行中的第二个字符将导致异常.

Next you have some tests for start/end characters that is still going to cause problems in some situations. Specifically, reading the second character in a line that has only one character is going to cause an exception.

您可以使用 StartsWithEndsWith 方法来进行测试,而不是对未测试长度的字符串使用索引:

Instead of using indexing on a string of untested length you can use the StartsWith and EndsWith methods to do your tests:

bool isComment = line.StartsWith("//");
bool isPoint = line.StartsWith("(") && line.EndsWith(")");

最后,在解析点值的代码中,您假设任何以 ( 开头并以 ) 结尾的行都至少包含 2 个逗号,并且文本将正确解析.这是一个糟糕的假设.

Finally, in your code that parses the point value you assume that any line that starts with ( and ends with ) will have at least 2 commas in it, and that the text will correctly parse. This is a bad assumption.

处理所有这些问题的更好方法是随时检测和处理每种情况,将解析功能分解为可以重用的方法

The better way to handle all of this is to detect and deal with each case as you go, with the parse functionality broken out to a method you can reuse

这是我的版本:

public class Program
{
    public static void Main()
    {
        List<Vector3> results = new List<Vector3>();
        using (var file = System.IO.File.OpenText(@"C:\temp\test.txt"))
        {
            string line;
            while ((line = file.ReadLine()?.Trim()) != null)
            {
                // skip empty lines and comments
                if (line == string.Empty || line.StartsWith("//"))
                    continue;
                // parse all other lines as vectors, exit program on error
                try
                {
                    Vector3 vector = ParseVector(line);
                    results.Add(vector);
                }
                catch (FormatException e)
                {
                    Console.WriteLine("Parse error on line: {0}", line);
                    throw;
                }
            }
        }

        foreach (var v in results)
            Console.WriteLine("({0},{1},{2})", v.X, v.Y, v.Z);
    }

    // parse string in format '(x,y,z)', all as floats
    // throws FormatException on any error
    public static Vector3 ParseVector(string text)
    {
        if (!text.StartsWith("(") || !text.EndsWith(")"))
            throw new FormatException();
        string[] parts = text.Substring(1, text.Length - 1).Split(',');
        if (parts.Length != 3)
            throw new FormatException();
        float x = float.Parse(parts[0]);
        float y = float.Parse(parts[1]);
        float z = float.Parse(parts[2]);
        return new Vector3(x, y, z);
    }
}

如果您不想使用异常,您可以返回 null 或使用 TryParse 方法使用的模式,返回布尔成功/失败指示器并使用 out 参数将结果写入.在这种情况下,我更喜欢例外.

If you prefer not to use exceptions you could return null or use the pattern used by the TryParse methods, returning a boolean success/failure indicator and using an out parameter to write the results to. I prefer exceptions in this case.

这篇关于如何在 C# 中正确处理空白行、空行或空行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆