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类型的变量**
尽管这还可以防止出现您遇到的问题,但这更多的是样式说明而不是答案。
首先,使用“ StreamReader当您致电时”,ReadLine您只会null在到达文件末尾时收到结果。您也不必关心行首和结尾处的空格,并且大概也不必关心完全是空格的行。因此,您可以通过以下方式使用它来测试文件结尾和空行:
string line;
while ((line = file.ReadLine()) != null)
{
line = line.Trim();
if (line == "")
continue;
}
Run Code Online (Sandbox Code Playgroud)
接下来,您将对开始/结束字符进行一些测试,这些测试在某些情况下仍然会引起问题。具体来说,在只有一个字符的行中读取第二个字符将导致异常。
可以使用StartsWith和EndsWith方法来进行测试,而不是对未经测试的长度的字符串使用索引:
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参数将结果写入其中。在这种情况下,我更喜欢例外。