diff --git a/src/main/java/org/example/ImageDotMarker.java b/src/main/java/org/example/ImageDotMarker.java index 193e995..e864ff4 100644 --- a/src/main/java/org/example/ImageDotMarker.java +++ b/src/main/java/org/example/ImageDotMarker.java @@ -453,38 +453,57 @@ public class ImageDotMarker extends JFrame { } JFileChooser fileChooser = new JFileChooser(); - fileChooser.setSelectedFile(new File("mark_points.txt")); - fileChooser.setFileFilter(new FileNameExtensionFilter("文本文件 (*.txt)", "txt")); + + // 设置默认文件名,使用当前图片文件名作为基础 + String defaultFilename = "mark_points.csv"; + if (currentImagePath != null) { + File imageFile = new File(currentImagePath); + String imageName = imageFile.getName(); + // 移除图片扩展名 + int lastDotIndex = imageName.lastIndexOf('.'); + if (lastDotIndex > 0) { + imageName = imageName.substring(0, lastDotIndex); + } + defaultFilename = imageName + "_mark_points.csv"; + } + + fileChooser.setSelectedFile(new File(defaultFilename)); + fileChooser.setFileFilter(new FileNameExtensionFilter("CSV文件 (*.csv)", "csv")); int result = fileChooser.showSaveDialog(this); if (result == JFileChooser.APPROVE_OPTION) { try { File file = fileChooser.getSelectedFile(); - if (!file.getName().toLowerCase().endsWith(".txt")) { - file = new File(file.getAbsolutePath() + ".txt"); + if (!file.getName().toLowerCase().endsWith(".csv")) { + file = new File(file.getAbsolutePath() + ".csv"); } StringBuilder sb = new StringBuilder(); - // 添加头部信息 - sb.append("# 图片标记点坐标导出\n"); - if (currentImagePath != null) { - sb.append(String.format("# 来源图片: %s\n", new File(currentImagePath).getName())); - } - sb.append(String.format("# 导出时间: %s\n", new java.util.Date())); - sb.append("# ======================================\n\n"); - - // 添加标记点数据 + // CSV列标题 sb.append("序号,名称,X坐标,Y坐标\n"); + + // 添加标记点数据,确保CSV格式正确处理包含逗号或引号的名称 for (int i = 0; i < points.size(); i++) { MarkPoint p = points.get(i); - sb.append(String.format("%d,%s,%d,%d\n", i + 1, p.name, p.x, p.y)); + String quotedName = p.name; + // CSV格式要求:如果字段包含逗号、双引号或换行符,需要用双引号包围,且内部的双引号用两个双引号表示 + if (quotedName.contains(",") || quotedName.contains("\"") || quotedName.contains("\n")) { + quotedName = "\"" + quotedName.replace("\"", "\"\"") + "\""; + } + sb.append(String.format("%d,%s,%d,%d\n", i + 1, quotedName, p.x, p.y)); } - // 写入文件 - java.nio.file.Files.write(file.toPath(), sb.toString().getBytes("UTF-8")); + // 写入文件,使用UTF-8编码并添加BOM以支持Excel正确识别中文 + try (java.io.FileOutputStream fos = new java.io.FileOutputStream(file)) { + // 写入UTF-8 BOM + byte[] bom = {(byte)0xEF, (byte)0xBB, (byte)0xBF}; // UTF-8 BOM + fos.write(bom); + // 写入CSV内容 + fos.write(sb.toString().getBytes("UTF-8")); + } JOptionPane.showMessageDialog(this, "标记点坐标导出成功!\n保存位置: " + file.getAbsolutePath()); - updateStatusBar("已导出标记点坐标到文件"); + updateStatusBar("已导出标记点坐标到CSV文件"); } catch (IOException ex) { JOptionPane.showMessageDialog(this, "导出失败: " + ex.getMessage()); }