【问题标题】:StreamReader ReadLine() returns empty string, nothing added to listStreamReader ReadLine() 返回空字符串,没有添加到列表中
【发布时间】:2016-10-11 22:05:08
【问题描述】:

我在从文件读取到列表时遇到了一些问题。 文件内容是这样的:

[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

【问题讨论】:

  • 因为您阅读的最后一件事是],而不是换行符。为什么不读取这些行,只检查该行是否以[ 开头并以] 结尾,或者它是否是“[END]”而不是尝试一次读取一个字符?
  • 代码向后看。你怎么知道还有没有读档的房间?通常你会在 StreamReader 上循环直到你到达 null (End Of File)。
  • 我建议将新行读入一个变量,然后在该行上执行您的逻辑,因为流阅读器将从您之前的读取读取到下一个新行字符

标签: c# list file streamreader


【解决方案1】:

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

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;
}

我列出了一些您需要决定如何处理的潜在错误情况。

【讨论】:

  • 谢谢。我已经根据您的回答修复了我的代码,并且它有效,我明白为什么。谢谢!
【解决方案2】:

阅读] 字符后,您假设阅读该行已完成,并认为directions = reader.ReadLine(); 会得到您这种方式不会一直这样

但是,您还没有读完这一行,因为] 后面有一个“换行符”字符,而您的阅读器确实读取了该字符并返回一个空字符串。

【讨论】:

    【解决方案3】:

    我已将您的方法重构为

    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 等。

    【讨论】:

      【解决方案4】:

      如果 with in While 得到满足,则在读取下一个不满足 if 条件的字符之后

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-05-11
        • 2014-10-08
        • 2018-11-27
        • 1970-01-01
        • 1970-01-01
        • 2021-06-08
        相关资源
        最近更新 更多