如何在Java SE 1.6中从文本文件提取数据构建图?
解决方案:从文本文件构建加权图(Java 1.6)
问题背景
需要读取格式如下的文本文件(可忽略空格),用自定义的StdGraph<String>实现构建图,同时验证文件格式正确性,要求兼容Java SE 1.6:
A: (B, 4.5), (C, 5.8) B: (A, 3) C:
原实现中已能手动构建图,但在文件读取、格式验证和数据提取部分存在问题,需要完善。
第一步:修正文件读取方法fileToString
原方法存在字符串处理错误、资源未关闭等问题,修正后代码:
private String fileToString(File f) { StringBuilder str = new StringBuilder(); Scanner s = null; try { s = new Scanner(f); while (s.hasNextLine()) { // 直接去除每行空格,保留换行符用于后续按行解析 str.append(s.nextLine().replaceAll("\\s", "")); str.append("\n"); } } catch (FileNotFoundException e) { System.err.println("ERREUR => FileNotFoundException"); e.printStackTrace(); return null; } finally { if (s != null) { s.close(); } } return str.toString(); }
第二步:调整正则表达式(适配Java 1.6)
原正则存在转义错误和匹配逻辑漏洞,调整后确保严格验证格式:
// 顶点名称:允许字母、数字、-、_、/,至少一个字符 private static final String SOMMETREGEX = "[a-zA-Z0-9\\-_/]+"; // 权重:允许正负整数或小数 private static final String POIDSREGEX = "[\\-+]?\\d+(\\.\\d+)?"; // 单条边格式:(顶点,权重) private static final String ARETEREGEX = "\\(" + SOMMETREGEX + "," + POIDSREGEX + "\\)"; // 单行格式:顶点: [边,边...](边可选) private static final String LIGNEREGEX = "^" + SOMMETREGEX + ":(" + ARETEREGEX + ",)*(" + ARETEREGEX + ")?$"; // 整个文件格式:多行单行格式,无空行 private static final String GRAPHREGEX = "^(" + LIGNEREGEX + "\\n)*" + LIGNEREGEX + "$";
第三步:补全buildGraphFromFile方法
分两步处理:先添加所有顶点,再解析添加边,确保添加边时顶点已存在:
private StdGraph<String> buildGraphFromFile(File f) { StdGraph<String> res = new StdGraph<String>(); String stringOfFile = fileToString(f); // 文件读取失败或格式不合法返回null if (stringOfFile == null || !Pattern.matches(GRAPHREGEX, stringOfFile)) { return null; } // 第一步:提取所有顶点并添加 Pattern vertexPattern = Pattern.compile("^" + SOMMETREGEX + ":", Pattern.MULTILINE); Matcher vertexMatcher = vertexPattern.matcher(stringOfFile); while (vertexMatcher.find()) { String vertex = vertexMatcher.group().replace(":", ""); res.addSommet(vertex); } // 第二步:按行解析每条边 String[] lines = stringOfFile.split("\\n"); Pattern edgePattern = Pattern.compile("\\(" + SOMMETREGEX + "," + POIDSREGEX + "\\)"); for (String line : lines) { String[] parts = line.split(":", 2); String sourceVertex = parts[0]; // 处理该行的所有边 if (parts.length > 1 && !parts[1].isEmpty()) { Matcher edgeMatcher = edgePattern.matcher(parts[1]); while (edgeMatcher.find()) { String edgeStr = edgeMatcher.group().substring(1, edgeMatcher.group().length() - 1); String[] edgeParts = edgeStr.split(","); String targetVertex = edgeParts[0]; double weight = Double.parseDouble(edgeParts[1]); res.addArete(sourceVertex, targetVertex, weight); } } } return res; }
额外注意事项
- 若需允许文件包含空行,需调整
GRAPHREGEX并在解析时跳过空行; - 可添加
NumberFormatException捕获逻辑,避免非法权重导致崩溃; - 若顶点名称需支持更多特殊字符,修改
SOMMETREGEX即可。
内容的提问来源于stack exchange,提问作者Mimixte
相关产品推荐
相关产品推荐

