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

时间:2015-11-29 22:53:28

标签: 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);
            }
        }

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

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

(3, 5, 2)

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

**注意:"文件"是StreamReader **

类型的变量

2 个答案:

答案 0 :(得分:3)

这更像是一种风格音符,而不是一种答案,尽管这也可以防止你遇到的问题。

首先,当您致电StreamReaderReadLine,当您到达文件末尾时,您只会收到null结果。你也不关心你的行的开头和结尾的空格,并且可能不关心完全是空白的行。所以你可以用它来测试文件结尾和空行:

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

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

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

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

最后,在解析点值的代码中,您假设任何以(开头并以)结尾的行中至少包含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);
    }
}

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

答案 1 :(得分:0)

大卫是对的。我正在达到一个超出范围的索引例外。以下是我更正并正常工作的代码:

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

            bool isWhiteSpace = false;
            bool isComment = false;
            bool isPoint = false;

            isWhiteSpace = string.IsNullOrEmpty(line);

            if (!isWhiteSpace)
            {
                isComment = (line[0] == '/') && (line[1] == '/');
                isPoint = (line[0] == '(') && (line[line.Length - 1] == ')');
            }
            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);
            }
        }