StreamReader ReadLine()返回空字符串,没有添加到列表

时间:2016-10-11 13:00:27

标签: c# list file streamreader

从文件到列表时,我遇到了一些问题。 文件内容如下:

[ROOM101]
that way this way no way all the way
[END]
[ROOM102]
all the way that way this way no way
[END]
[ROOM103]
no way all the way that way this way
[END]

方法如下:

public static List<Room> ReadRooms(string path)
{
    List<Room> rooms = new List<Room>();
    StreamReader reader = new StreamReader(path);
    bool roomsLeft = true;
    char currentChar;
    string directions;
    StringBuilder builder = new StringBuilder();

    while (roomsLeft) {
        currentChar = (char)reader.Read();
        if (currentChar == '[') {
            currentChar = (char)reader.Read();
            while (currentChar != ']') {
                builder.Append(currentChar);
                currentChar = (char)reader.Read();
            }
            if (builder.ToString() != "END") {
                directions = reader.ReadLine();
                rooms.Add(new Room(builder.ToString(), directions));
            }
        }
        if (reader.EndOfStream) {
            roomsLeft = false;
        }
    }
    reader.Close();

    return rooms;
}

它读取第一行很好,但directions = ReadLine()绝对没有返回任何内容,并且没有任何内容添加到列表中 - 不应该跳转到下一行并分配给directions?整件事导致StackOverflowException

4 个答案:

答案 0 :(得分:1)

在阅读]字符后,您认为阅读该行已完成,并认为directions = reader.ReadLine();将以某种方式让您以这种方式

但是,您还没有读完该行,因为]后面有“换行符”字符,而您的读者读取该字符并返回空字符串。

答案 1 :(得分:1)

我已将您的方法重构为

public static List<Room> ReadRooms(string path)
{
    List<Room> rooms = new List<Room>();
    string roomName=String.Empty;
    StringBuilder directionsBuilder= new StringBuilder();

    using (StreamReader reader = new StreamReader(path))
    { 
        while (!reader.EndOfStream)
        {
            string line = reader.ReadLine();
            if (line != null && line.StartsWith("[END]"))
            {
                rooms.Add(new Room(roomName, directionsBuilder.ToString()));
                directionsBuilder.Clear();
            }
            else if (line != null && line.StartsWith("["))
                roomName = line.Substring(1, line.Length - 2);
            else
                directionsBuilder.AppendLine(line);
        }
    }
    return rooms;
}

它应该处理多个线路方向以及ROOM102或APARTMENT201等房间名称。

答案 2 :(得分:1)

您所指的具体问题是因为您在某个时间阅读了一个字符,当您看到]时,您会执行ReadLine,但这只会读到之后的换行符]而不是您想要的下一行。但即使您修复了代码中存在其他问题(例如不清除StringBuilder),最好只处理行而不是一次读取一个字符。此外,您可以使用方便的StreamReader方法,而不是使用需要清理的File.ReadLine

public static List<Room> ReadRooms(string path)
{
    List<Room> rooms = new List<Room>();
    bool inRoom = false;
    StringBuilder directions = new StringBuilder();
    string name = null;
    foreach (var line in File.ReadLines(path))
    {
        if (inRoom)
        {
            if(line == "[END]")
            {
                rooms.Add(new Room(name, directions.ToString()));
                inRoom = false;
                directions.Clear();
            }
            else if (line.StartsWith("[") && line.EndsWith("]"))
            {
                // Found a start before the end, condiser throwing an 
                // exception, ignoring, or keep it as part of the directions.
            }
            else
            {
                directions.AppendLine(line);
            }
        }
        else
        { 
            if(line == "[END]")
            {
                // Found an end before a start either throw an exception or
                // just ignore this.
            }
            else if (line.StartsWith("[") && line.EndsWith("]"))
            {
                inRoom = true;
                name = line.Trim('[', ']');
            }
            else
            {
                // Consider throwing an exception here or just ignoring lines 
                // between [END] and the next room.
            }
        }
    }

    if (inRoom)
    {
        // Determine what to do if you had a room start, but no [END]
    }

    return rooms;
}

我已经包含了一些您可能需要决定如何处理的潜在错误案例。

答案 3 :(得分:0)

如果in in得到满足,那么在读取下一个字符之后,如果条件

则不满足