在这里插入图片描述

前两篇文章里,我用 Java Swing 和大模型手搓了一个文件对比工具。

第一版先把目录对比、文件对比、Hash 校验、左右同步和内容编辑做出来;第二版连续改了 6 轮 UI,把默认 Swing 界面改成了更紧凑的左右双栏,还解决了按钮显示三个点、路径区域太占空间、操作步骤过多等问题。

工具看起来已经越来越像样,但真正拿一个层级稍深的目录测试后,新问题马上出现了。

所有文件都被平铺在列表里。子目录一多,界面就会出现几十甚至几百行;目录嵌套越深,相对路径越长,真正有差异的文件反而更难找。除此之外,如果对比完成后又在目录中新增了文件,页面没有刷新入口,只能退出当前任务再重新选择左右目录。

所以今天继续做第 3 期:把平铺列表改成可展开的目录树,再补上一键刷新。

为什么平铺列表不够用了

最初使用平铺列表,是因为它实现简单,也很直观。递归扫描左右目录后,只要把所有文件按相对路径排序,再逐行显示即可。

当目录只有一两层时,这种方式没有明显问题。但目录一旦复杂起来,缺点就会被放大:

  • 子目录里的所有文件一次性铺开,列表很快被占满。
  • 嵌套层级越深,文件路径越长,名称列很难快速阅读。
  • 同一个目录下几十个相同文件会淹没真正需要处理的差异。
  • 左右某一侧缺少整个目录时,要逐个查看缺失文件才能理解问题。
  • 滚动很远之后,用户容易失去自己当前所在目录的上下文。

文件对比工具的重点不是“把扫描到的内容全部展示出来”,而是让人尽快定位差异。

更合适的方式应该是:首次只显示顶层文件和目录;目录本身先汇总内部状态;需要检查时再逐级展开。这样即使对比一个嵌套很深的项目,也能先看到哪几个目录存在问题,再继续往下定位。

第二个问题:目录变了,结果却不会变

另一个问题来自实际操作。

目录对比完成后,我可能会继续在资源管理器或编辑器中新增、删除、修改文件。这时工具里的结果已经过期,但页面没有“重新加载”功能。

原来的操作流程是:返回首页,重新进入目录对比,再选择一次左侧目录和右侧目录。路径明明没有变化,却要把整个流程再走一遍。

这类操作不会让功能失效,但会持续打断使用节奏。对一个需要边修改、边验证、边同步的工具来说,刷新应该是随手就能完成的基础能力。

这次没有直接改代码

和上一篇优化 UI 时一样,这次我仍然没有让大模型收到需求后马上修改程序。

我先把真实问题、期望交互和开发顺序一次说清楚:

今天有两个问题要求修改:

  1. 当有子文件夹时,当前会把所有文件都列出来。如果子文件夹很多、嵌套也很深,就会列出很多文件,文件路径也很长。建议有子文件夹时先折叠,点击时再展开,请先进行设计并提出意见。
  2. 当前页面没有重新加载功能。如果我在对比目录中新增了一些文件,需要重新打开,很麻烦。
  3. 针对这些意见给出修改方案,如有不足也提出来。
  4. 先给执行计划、实现方案和对应的 UI 页面,我确认后再修改。

这段提示词里最重要的不是“目录折叠”和“刷新”两个功能,而是最后一句:先给方案和效果图,确认后再修改。

目录树会改变列表结构、点击行为、左右联动和同步逻辑。如果一开始就改代码,后面发现目录状态、缺失占位或展开方式不合理,返工范围会很大。先看静态效果,可以用更低的成本确认信息层级和交互方向。

第一轮方案:默认折叠,只展示需要的信息

大模型先给出了一张目录折叠状态的效果图:

在这里插入图片描述

这版设计延续了上一期的扁平风格,没有把整个界面推倒重做,而是在原有表格中增加目录层级:

  • 文件夹使用文件夹图标和展开箭头。
  • 首次对比时目录默认折叠。
  • “大小”列在目录行改为显示包含的文件数量。
  • 相同目录继续使用浅绿色。
  • 内部存在差异的目录直接显示浅红色。
  • 仅存在于一侧的目录,在另一侧保留对应占位行。
  • 顶部增加刷新图标,不再额外占用一整行工具栏。

这样打开一个大目录时,用户第一眼看到的是目录结构和问题分布,而不是一整屏长路径。

第二轮方案:展开后左右仍然对齐

只有折叠还不够。文件对比工具是左右两侧同时查看,如果左边展开了目录,右边没有展开,两边的行很快就会错位。

因此第二张效果图重点确认展开后的行为:

在这里插入图片描述

最终确定的交互规则是:

  1. 点击任意一侧的目录,左右两侧同时展开或折叠。
  2. 两侧使用同一份相对路径树,保证同一行始终表达同一个文件或目录。
  3. 某个目录只存在于一侧时,另一侧仍显示对应的缺失节点。
  4. 展开目录后,文件继续支持双击进入内容对比。
  5. 菜单中提供“全部展开”和“全部折叠”,方便一次查看完整结构。

确认两张效果图后,我给出的回复只有一句:

可以的,开始修改吧。

到这一步,才正式开始改 Java Swing 代码。

技术上怎么实现目录折叠

看起来只是给目录前面加一个小三角,实际改动并不只是界面渲染。

原来的数据模型是一组按相对路径排序的文件记录。每条记录只关心左侧文件、右侧文件以及对比状态。要支持折叠,程序必须先把这些记录重新组织成树。

1. 左右两边共用一棵目录树

程序扫描完左右目录后,会先收集两侧出现过的所有相对目录,再把文件挂到对应父目录下,最终形成一棵合并目录树。

这样做有两个好处。

第一,同一个相对路径在左右两侧天然位于同一行,不需要分别维护两棵树再尝试对齐。

第二,即使某个目录只存在于左侧,右侧也能从共享节点中得到一个占位项,用户可以直接看出缺失发生在哪一层,而不是看到一片错位的空白。

2. 目录颜色由子节点汇总

文件仍然使用 SHA-256 判断内容是否相同,但目录本身没有一个可以直接比较的 Hash。

因此目录状态从最深层开始向上汇总:

  • 所有子文件和子目录都相同,父目录标绿。
  • 任意一个子节点不同,父目录标红并显示“有差异”。
  • 目录只存在于左侧,显示“仅左侧”。
  • 目录只存在于右侧,左侧显示“缺失”。

这种汇总很关键。目录折叠后,用户不必展开每一个文件夹,也能知道里面是否存在差异。

3. 折叠只影响显示,不减少扫描

这里有一个容易误解的地方:目录折叠只解决显示密度,不代表程序只扫描已经展开的目录。

每次对比仍然会递归读取左右目录,并计算所有普通文件的 SHA-256。只有完整扫描后,程序才能准确判断一个折叠目录应该显示绿色还是红色。

如果为了“懒加载”而只扫描用户展开的目录,首页看到的目录状态就不可信,同步时也可能漏掉未展开的内容。

所以当前方案的取舍是:完整扫描保证结果正确,目录折叠负责让结果更容易阅读。 大目录扫描速度属于另一个性能问题,后面需要用并行 Hash、进度展示和过滤规则来解决。

4. 只渲染当前可见节点

程序使用一个展开路径集合保存哪些目录处于打开状态。刷新表格时,只把顶层节点和已展开目录的子节点加入可见行。

点击左侧或右侧目录时,修改的是同一个展开路径集合,然后同时重建两边表格,所以左右展开状态始终一致,原有的选中行和滚动联动也能继续工作。

一键刷新不只是再调用一次对比

刷新入口最终放在了三个位置:

  • 页面右上角的刷新图标。
  • “工具”菜单中的“重新加载”。
  • 键盘快捷键 F5

刷新时会重新扫描当前左右路径,并重新计算文件 Hash。用户不需要返回首页,也不用再次选择目录。

为了避免刷新后视图突然跳回初始状态,程序还会尽量保留已有操作上下文:

  • 仍然存在的展开目录继续保持展开。
  • 原来选中的文件仍然存在时,恢复选中并滚动到可见位置。
  • 已经被删除的目录会自动从展开状态中移除。
  • 刷新过程中禁用重复操作,完成后更新文件数量和状态统计。

这几个细节不会出现在功能清单里,但会直接影响工具是否顺手。

顺手补上的两个边界问题

在实现目录树时,还暴露了两个容易被忽略的边界情况。

空目录也应该被看见

原来的平铺模型只保存文件。一个目录如果是空的,扫描结果中就没有任何文件能代表它,因此左右目录结构不同也不会显示出来。

新的目录快照会单独记录目录集合,所以空目录也能进入合并树。执行左右同步时,源目录中的空目录会在目标侧创建,不再因为“里面没有文件”而被忽略。

缺失目录不能让两边错行

如果整个子目录只存在于一侧,另一侧不能简单少显示一行。否则后面的文件会整体上移,左右对应关系被破坏。

现在两侧都从共享目录树生成可见行,缺失的一侧显示占位状态。无论目录展开多少层,同一个相对路径始终保持在同一行。

最终运行效果

修改完成后,重新使用 Java 8 编译并启动程序,再用包含多级目录、相同文件、不同文件和单侧目录的测试数据进行检查。

最终实际运行截图如下:

在这里插入图片描述

从截图可以看到:

  • 顶层目录默认折叠,列表不再被所有子文件一次占满。
  • 展开的目录使用缩进展示层级。
  • 左右两侧目录结构和展开状态保持同步。
  • 父目录会根据内部文件状态显示“相同”“有差异”或“仅左侧”。
  • 缺失目录和文件仍然保留对应行。
  • 右上角增加了轻量的刷新入口。
  • 展开后仍可双击具体文件进入左右内容编辑器。

这次没有大幅改变配色或整体布局,但在真实目录较多时,信息密度和定位效率比平铺列表明显更合理。

今天实际修改了哪些内容

1. 对比结果模型

  • 将平铺文件列表升级为文件与目录组成的层级树。
  • 合并左右目录结构,使用统一相对路径保持行对齐。
  • 目录状态根据所有子节点递归汇总。
  • 单独记录空目录和仅单侧存在的目录。

2. 目录交互

  • 目录默认折叠,单击名称即可展开或收起。
  • 左右目录同步展开和折叠。
  • 目录行显示内部文件数量。
  • “查看”菜单增加“全部展开”和“全部折叠”。
  • 文件行继续支持双击打开内容对比。

3. 重新加载

  • 页面右上角增加刷新图标。
  • “工具”菜单增加“重新加载”。
  • 支持按 F5 重新扫描当前路径。
  • 刷新后尽量保留展开目录和选中文件。
  • 更新顶部状态统计和底部结果数量。

4. 同步与兼容性

  • 同步目录时补充创建空目录。
  • 保持现有 SHA-256 文件内容对比逻辑不变。
  • 保持双向同步、双击编辑和左右滚动联动不变。
  • 继续兼容 Java 8,不引入第三方依赖。

今天的提示词复盘

这一轮提示词比直接说“做一个目录树”更有效,因为它同时交代了场景、问题和验收流程。

几个值得保留的写法是:

  1. 先描述真实数据规模:子文件夹多、嵌套深、路径长,而不只是说“界面不好看”。
  2. 说清目标行为:默认折叠,点击后再展开。
  3. 补充操作链路:目录新增文件后,希望不退出当前页面就能刷新。
  4. 要求模型提出不足:不仅照着需求实现,还要检查空目录、缺失目录和左右错位等边界问题。
  5. 把确认放在开发之前:先看计划和 UI 图,确认方向后再修改正式代码。

如果希望大模型一次完成同类改造,可以直接使用下面这份最终版提示词:

请继续优化一个现有的 Java 8 Swing 文件对比工具。工具已经支持目录对比、
文件对比、SHA-256 内容校验、左右同步、双击编辑、差异复制,以及左右列表
联动滚动。请保持现有功能和扁平化 UI 风格,不引入第三方依赖。

当前有两个问题:

1. 目录对比结果使用平铺列表。子目录多、嵌套深时会一次展示大量文件,
   相对路径也很长,难以快速定位差异。
2. 对比完成后,如果外部新增、删除或修改文件,页面没有重新加载入口,
   必须重新选择左右目录。

请按以下要求设计和实现:

1. 将目录对比结果改成可折叠的层级目录树,首次只展示顶层目录和文件。
2. 目录使用展开/折叠箭头和文件夹图标,单击目录名称切换状态。
3. 左右两侧必须共用同一份相对路径树;在任意一侧展开目录时,另一侧同步展开,
   始终保证相同文件和目录位于同一行。
4. 某个文件或目录只存在于一侧时,另一侧保留缺失占位节点,不能导致后续行错位。
5. 目录状态由子节点递归汇总:全部相同显示绿色,任一子节点不同显示红色,
   单侧目录显示“仅左侧”“仅右侧”或“缺失”。
6. 目录行显示其包含的文件数量;文件行继续显示格式化后的文件大小。
7. 文件仍然使用 SHA-256 对比。折叠仅影响显示,后台必须完整递归扫描,
   保证目录汇总状态和同步结果准确。
8. 单独记录空目录,使左右结构差异可见;执行同步时也要创建源侧空目录。
9. 保留文件双击编辑、左右选择联动和滚动联动。
10. 在“查看”菜单增加“全部展开”和“全部折叠”。
11. 在页面右上角增加刷新图标,在“工具”菜单增加“重新加载”,并支持 F5。
12. 重新加载时重新扫描当前左右路径并计算 Hash,不要求用户重新选择目录。
13. 刷新后尽量保留仍然有效的目录展开状态和选中文件;删除无效状态并更新统计。
14. 刷新和对比过程继续放在后台线程中,执行期间禁用可能重复触发的操作。
15. 继续兼容 Java 8,只使用 JDK 和 Swing。

修改前先分析现有代码,给出执行计划、数据结构方案、交互细节和 UI 效果图。
我确认后再修改代码。完成后使用 Java 8 编译并启动程序,用深层目录、空目录、
同名不同内容文件和单侧目录进行验证,并说明测试结果与仍存在的不足。

下一步计划

目录树解决了“结果太多看不清”的问题,但它没有解决大目录扫描本身的性能,也没有让文本差异算法变得更准确。下一步准备继续处理下面几项。

1. 增加过滤和排除规则

实际项目中经常包含 .gitnode_modulestarget、日志和临时文件。后续会支持按目录名、扩展名和通配符排除内容,减少无效扫描和 Hash 计算。

2. 优化大目录扫描

增加更明确的扫描进度、取消操作和并行 Hash,并考虑增量展示结果。目录折叠解决的是“看得清”,性能优化解决的是“等得少”。

3. 改进文本差异算法

当前内容编辑器仍以同一行号为主要比较依据。文件中间插入一行后,后续内容可能大面积标红。后面需要引入更合理的行对齐算法,准确区分新增、删除和修改。

4. 完善编码识别

当前默认按 UTF-8 读取文本。后续需要识别 GBK、GB2312 等常见编码,并允许手动切换,保存时保持原文件编码。

5. 提高同步安全性

同步前增加变更预览,明确展示将新增和覆盖的文件;必要时增加自动备份和撤销能力,避免误操作直接覆盖重要内容。

最后

这一轮让我更确定一件事:用大模型写出“有功能的软件”并不难,真正耗时间的是把真实使用中的不顺手一项项找出来,再把它们变成明确、可验证的修改要求。

从平铺列表到可折叠目录树,看起来只是多了几个文件夹图标和展开箭头,背后却涉及共享数据模型、目录状态汇总、缺失占位、空目录同步、左右联动和刷新状态恢复。

这也是我继续记录这个系列的原因。不是展示一句提示词生成了多少代码,而是完整记录:问题怎样在使用中暴露,需求怎样变得具体,方案怎样先通过效果图确认,最后又怎样落到一个能运行的 Java 工具里。

目前的使用体验依然算不上专业。大目录扫描速度、文本差异准确度、编码识别和同步安全还有不少需要优化的地方。后面我会继续迭代,也会继续把每一次真实修改、提示词和最终效果记录下来。

更多推荐