如何读取CSV文件并存入HashMap<String, LatLon>?遇异常求解
问题分析与解决思路
你的代码抛出InputMismatchException及无法正确存储数据的原因主要有以下几点:
核心问题
字段读取顺序完全错误
CSV格式是Location#, Latitude, Longitude,但你的代码先尝试读取纬度/经度(double类型),最后读取Location#(字符串)。当Scanner遇到第一个字段(字符串类型的位置编号或表头)时,用nextDouble()读取必然会抛出类型不匹配异常。分隔符设置不严谨
仅设置逗号为分隔符会忽略换行符的存在,导致Scanner跨行读取内容,同时无法处理CSV中常见的“逗号+空格”格式(比如Loc1, 39.9, 116.3)。LatLon对象重复引用
你只创建了一个LatLon对象,循环中仅修改其lat/lon值,最终HashMap中所有键都会指向同一个对象,所有条目都会覆盖为最后一次的坐标值。未处理表头(若存在)
如果CSV第一行是表头(如Location#,Latitude,Longitude),直接读取会导致字符串被当作double解析,触发异常。
修正后的代码
推荐采用按行读取+拆分字段的方式,这种方式更稳定,也更容易处理CSV的格式细节:
import java.io.File; import java.io.FileNotFoundException; import java.util.HashMap; import java.util.Scanner; public class LocationReader { public static void main(String[] args) { String path = "fileName.csv"; HashMap<String, LatLon> maps = new HashMap<>(); try (Scanner s = new Scanner(new File(path))) { // 跳过表头(如果CSV有表头的话,没有则删除这行) if (s.hasNextLine()) { s.nextLine(); } while (s.hasNextLine()) { String line = s.nextLine().trim(); // 拆分字段:匹配逗号及后面可能的空格 String[] fields = line.split(",\\s*"); // 确保每行有3个有效字段 if (fields.length == 3) { String locationId = fields[0]; double lat = Double.parseDouble(fields[1]); double lon = Double.parseDouble(fields[2]); // 每次循环创建新的LatLon对象,避免引用重复 maps.put(locationId, new LatLon(lat, lon)); } } } catch (FileNotFoundException e) { System.err.println("文件未找到:" + path); e.printStackTrace(); } catch (NumberFormatException e) { System.err.println("坐标格式错误,请检查CSV内容"); e.printStackTrace(); } } // 假设你的LatLon类是这样的 static class LatLon { private double latitude; private double longitude; public LatLon(double latitude, double longitude) { this.latitude = latitude; this.longitude = longitude; } // 可选:添加getter方法 public double getLatitude() { return latitude; } public double getLongitude() { return longitude; } } }
额外优化建议
- 使用try-with-resources语法(如上代码),无需手动关闭Scanner,确保资源自动释放。
- 添加字段长度校验和异常捕获,避免因CSV格式错误导致程序崩溃。
- 如果CSV内容包含带逗号的字符串(比如
"New York, NY",40.7,-74.0),手动拆分的方式会失效,此时建议使用成熟的CSV解析库(如OpenCSV)来处理复杂场景。
内容的提问来源于stack exchange,提问作者Roaming
相关产品推荐
相关产品推荐

