Golang初级项目:自动重命名相册工具_根据EXIF信息重命名

1次阅读

go标准库不支持jpeg exif读取,需用第三方包;常见错误包括未校验文件有效性、误处理无exif的图片(如手机直出、微信图),应先检查jpeg头、文件大小,再按datetimeoriginal等优先级解析时间,并安全重命名与并发控制。

Golang初级项目:自动重命名相册工具_根据EXIF信息重命名

Go 读取 JPEG EXIF 信息为什么总返回空?

因为 Go 标准库不支持 EXIF,必须用第三方包,且常见错误是没检查文件是否真有 EXIF 数据或误读了缩略图段。很多照片(尤其是手机直出、微信转发、截图)压根没嵌入完整 EXIF,exif.Read 会静默返回 nil 或部分字段为空,不是代码写错了。

  • github.com/rwcarlsen/goexif/exif(注意是旧版,兼容性好)或更现代的 github.com/xor-gate/goexif2/exif,后者支持更多字段但要求 Go 1.16+
  • 务必在调用 exif.Decode 前用 os.Stat 确认文件存在且非零大小,再用 bytes.HasPrefix 检查前几个字节是否为 JPEG0xFF 0xD8),避免对 PNG/HEIC 文件硬解
  • exif.DateTime 字段最常用,但它可能不存在;实际应 fallback 到 exif.DateTimeOriginalexif.DateTimeDigitized,三者语义不同:原拍摄时间 > 数码化时间 > 文件修改时间

重命名时怎么安全生成新文件名?

直接拼接字符串 + os.Rename 极易出错——路径含中文、冒号、斜杠,或目标名已存在,或跨磁盘移动失败。golang 不自动处理这些边界,得自己兜底。

  • filepath.Basefilepath.Dir 拆分路径,新文件名只操作 basename,保留原目录结构
  • 时间格式建议用 time.format("20060102_150405")(Go 唯一固定 layout),避免 : 和空格;中文系统下还要用 strings.map 过滤掉 windows 不允许的字符( : " / | ? *
  • 重命名前必须检查目标路径是否存在:os.Stat(newPath),若存在则加序号后缀(如 _1),而不是覆盖——相册文件一旦覆盖就不可逆

批量处理大量照片时卡住或崩溃?

默认串行读取+解析+重命名,1000 张照片可能耗时数分钟,且内存暴涨(每张图加载进内存解 EXIF)。问题不在逻辑,而在 IO 和并发控制没做。

  • 不要一次性 filepath.Glob("*.jpg") 后全塞进内存;改用 filepath.WalkDir 流式遍历,边发现边处理
  • 用带缓冲的 channel 控制并发数(比如 sem := make(chan Struct{}, 4)),每次 goroutine 启动前 sem ,结束时 <code>,避免打开太多文件句柄触发 <code>too many open files
  • EXIF 解析是 CPU 密集型,但 I/O 更慢,所以并发 4–8 即可,再多无收益,反而增加调度开销

Windows 下中文路径乱码或权限拒绝?

Go 1.16+ 在 Windows 上默认用 UTF-16 调用系统 API,但某些老旧文件系统(如 FAT32 U 盘)或杀毒软件会拦截重命名操作,报错 Access is denied 或返回乱码路径。

立即学习go语言免费学习笔记(深入)”;

  • 路径一律用 filepath.ToSlash 统一为正斜杠,避免反斜杠转义问题;打印调试时用 fmt.Printf("%q", path) 查看真实字节
  • 遇到 permission denied,先检查文件是否被资源管理器预览窗格锁定(关掉「预览窗格」再试),或用 lsof(WSL)或 Process Explorer 查进程占用
  • 别依赖 os.Getwd() 当基准路径——它可能返回短路径名(C:USERSADMINI~1...),导致后续 filepath.Join 拼错;显式用 os.Executable() 或传入绝对路径参数更稳

EXIF 时间字段缺失、跨文件系统移动、中文符号过滤、并发锁粒度——这些不是“功能做完就完事”的点,而是每次运行都可能突然冒出来的具体阻力。绕不开,只能一个个钉死。

text=ZqhQzanResources