C# 从下到上读取控制台输出,直到空行

C# Read console output from bottom to top, until empty line

我正在构建 C# 控制台应用程序以从串行端口读取设备名称。我设法将所有连接的设备名称打印到控制台。控制台输出如下所示:

Scanning...
---------------------------------
Connected devices:

1. DeviceName1
2. DeviceName2
3. DeviceName3

现在,如何从下到上读取输出,直到第一个空行?比 Console.ReadLine() 让用户可以通过在设备名称前键入数字来选择设备。

这是我使用的代码:

var serialPort = new System.IO.Ports.SerialPort()
// Read the data that's in the serial buffer.
var deviceName = serialPort.ReadExisting();

// Write to debug output.
Console.WriteLine($"\n---------------------------------");
Console.WriteLine($"\nConnected devices:\n");
Console.WriteLine(deviceName);

string input;
do
{
    // Here I need posibility for user
    // to type number infront deviceName

} while (deviceName.ToUpper() != null);

当你从串口读取时,你可以将它存储在一个字符串变量中。

然后根据换行符将字符串变量拆分成一个数组来处理它。

遍历数组项,只取那些以数字开头、用句号分隔的项。

那些你想要的行,将它存储到字典中,使用ReadExisting()方法提供的索引作为你的字典索引。 这是为了让你给设备分配一个ID,这样当用户select这个ID时,你可以通过它的ID反向查找设备。

然后,循环字典以将设备显示到控制台。

抓取用户select输入的ID,然后根据ID使用字典反向查找设备。

我假设您有办法访问可枚举列表中的设备列表。

    public static void Main(string[] args)
    {
        // Can't simulate the output. So, I assume there is an output from ReadExisting(), and I capture the output to a string variable.
        // var serialPort =  new System.IO.Ports.SerialPort();
        // var outputReadExisting = serialPort.ReadExisting();
        var outputReadExisting = @"Scanning...
-------------------------------- -
Connected devices:

1.DeviceName1
2.DeviceName2
3.DeviceName3";

        var deviceDict = LoadDevicesToDictionary(outputReadExisting);
        DisplayDevices(deviceDict);
        var selectedDevice = PromptUserToSelectDevice(deviceDict);

    }

    private static Dictionary<int, string> LoadDevicesToDictionary(string output)
    {
        var outputLines = output.Split(new[] { Environment.NewLine, "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries);

        var deviceDict = new Dictionary<int, string>();
        foreach (var line in outputLines)
        {
            // Skip line if null/whitespace or if it does not contains "." (the index)
            if (string.IsNullOrWhiteSpace(line) || !line.Contains("."))
            {
                continue;
            }

            var splitLine = line.Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries);
            // Skip line if after splitting by number and first part is not an integer (not device index)
            if (splitLine.Length < 2 || !int.TryParse(splitLine[0], out var deviceIndex))
            {
                continue;
            }

            // Add device index as dictionary index, then take remainder string minus the device index and the "."
            deviceDict.Add(deviceIndex, line.Substring(deviceIndex.ToString().Length + 1));
        }
        return deviceDict;
    }

    private static void DisplayDevices(Dictionary<int, string> deviceDict)
    {
        foreach (var device in deviceDict)
        {
            Console.WriteLine($"{device.Key}. {device.Value}");
        }
    }

    private static string PromptUserToSelectDevice(Dictionary<int, string> deviceDict)
    {
        Console.WriteLine("Please select your device (ID): ");
        var selectedId = Console.ReadLine();
        if (!int.TryParse(selectedId, out var idVal)
            || !deviceDict.ContainsKey(idVal))
        {
            Console.WriteLine("Invalid input. Please input device ID listed above.");
            return PromptUserToSelectDevice(deviceDict);
        }

        return deviceDict[idVal];
    }