如何正确处理C#中的空行,空行或空行

Dri*_*r64 2 c# streamreader unexpectendoffile

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

我的代码:

        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);
            }
        }
Run Code Online (Sandbox Code Playgroud)

您可以看到,我恰巧是使用Vector3做事的。如果该行是注释行或空白行,我希望它什么也不做。如果注意到括号,我希望它假定它是一个Vector3并对其进行解析。最后,如果这不是一条线,我希望它完全停止。这是我仅使用记事本创建的示例文本文件:

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

(3, 5, 2)
Run Code Online (Sandbox Code Playgroud)

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

**注意:“文件”是StreamReader类型的变量**

Cor*_*rey 5

尽管这还可以防止出现您遇到的问题,但这更多的是样式说明而不是答案。

首先,使用“ StreamReader当您致电时”,ReadLine您只会null在到达文件末尾时收到结果。您也不必关心行首和结尾处的空格,并且大概也不必关心完全是空格的行。因此,您可以通过以下方式使用它来测试文件结尾和空行:

string line;
while ((line = file.ReadLine()) != null)
{
    line = line.Trim();
    if (line == "")
        continue;
}
Run Code Online (Sandbox Code Playgroud)

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

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

bool isComment = line.StartsWith("//");
bool isPoint = line.StartsWith("(") && line.EndsWith(")");
Run Code Online (Sandbox Code Playgroud)

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

处理所有这些问题的更好方法是在进行过程中检测并处理每种情况,将解析功能分解为可重用的方法

这是我的版本:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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