如何从Telnet接收的含乱码字符串中提取数字?附Socket服务器代码
解决Telnet输入乱码与数字提取失败问题
看起来你遇到的核心问题有两个:一是Telnet客户端(Putty)收到/发送的字符串包含乱码,二是无法正确提取输入中的数字。让我们一步步解决这些问题:
1. 字符编码一致性问题(乱码根源)
你的代码中输入输出流明确指定了UTF-8,但创建STZ_DAVOR和STZ_DANACH这两个控制字符字符串时,使用了系统默认编码(没有指定编码参数),这会导致这些字节被错误解码,发送到客户端后显示为乱码,甚至客户端回显时带回这些乱码字符。
修复方法:创建字符串时指定UTF-8编码,和输入输出流保持一致:
private static final String STZ_DAVOR = new String( new byte[]{0x0b, 0x1b, '[', '1', 'A', 0x1b, '7', 0x1b, '[', '1', 'L', '\r'}, Charset.forName("utf-8") ); private static final String STZ_DANACH = new String( new byte[]{0x1b, '8', 0x1b, '[', '1', 'B'}, Charset.forName("utf-8") );
2. 输入读取逻辑的致命bug
在桌号验证的代码中,你连续调用了三次in.readLine():
table = in.readLine(); // ... else if (in.readLine().equals("") || in.readLine().contains(" ")) {
这会导致你跳过用户的输入行!第一次读取的table是用户输入的内容,但后面两次in.readLine()会直接读取下一行输入,完全偏离了你的逻辑。这也是你无法正确获取用户输入数字的重要原因。
3. 鲁棒的数字提取方案
不要用substring(table.length()-1)这种脆弱的方式提取数字——当输入包含乱码或多余字符时,这种方法很容易失效。改用正则表达式提取输入中的所有数字序列,确保能准确获取用户输入的数字:
修改桌号读取的逻辑:
sendMessageToMe("Please insert your table number:"); while (true) { String inputLine = in.readLine(); if (inputLine == null) { // 用户断开连接 break; } // 提取输入中的所有数字 Pattern digitPattern = Pattern.compile("\\d+"); Matcher matcher = digitPattern.matcher(inputLine); if (matcher.find()) { String numStr = matcher.group(); int tableNumber; try { tableNumber = Integer.parseInt(numStr); // 验证桌号是否在有效范围(你的tables数组长度为5,索引0-4) if (tableNumber >= 0 && tableNumber < RestaurantTrekNation.tables.length) { if (RestaurantTrekNation.summmonCustomer(tableNumber)) { sendMessageToMe("Your Table is ready prepare to order "); this.table = numStr; // 保存正确的桌号 break; } else { sendMessageToMe("Table is full please choose another table"); } } else { sendMessageToMe(String.format("Please enter a valid table number (0-%d)", RestaurantTrekNation.tables.length - 1)); } } catch (NumberFormatException e) { sendMessageToMe("Please enter a valid number for your table"); } } else { sendMessageToMe("Please enter a valid table number (only digits allowed)"); } }
4. 额外的小问题修复
你的menu静态初始化中,08.00和09.99是无效的Java语法(以0开头的数字会被解析为八进制,但8和9不是八进制合法数字),需要修改为:
menu.add(new Dish(6, 8.00, "hello" , 5)); menu.add(new Dish(7, 9.99, "hello" , 5));
可选:过滤Telnet控制字符
如果Putty发送了Telnet协议的控制字符(比如IAC字节0xFF),这些会被当成普通字符混入输入流导致乱码。你可以在读取后过滤掉非打印字符:
// 过滤掉所有非数字、非换行的非打印字符 inputLine = inputLine.replaceAll("[^\\d\\n\\r]", "");
这些修改应该能解决你遇到的乱码和数字提取问题,同时让输入逻辑更健壮。
内容的提问来源于stack exchange,提问作者Lukas
相关产品推荐
相关产品推荐

