fix: BIP→BSQ 转换数据丢失修复 + 只读文件处理
- 延迟删除原始文件:先验证临时 BSQ 文件存在且非空,再删原始数据 - 异常处理不再删除临时 BSQ:保留完好副本供手动恢复 - 新增 _make_writable() 移除只读属性,避免 Windows PermissionError - 清理孤儿 .aux.xml 临时文件 - 路径变量提前声明,保证异常处理块可访问
This commit is contained in:
@ -98,6 +98,23 @@ def _ensure_bsq(img_path):
|
||||
f"({_src_size/1024**3:.1f}GB, 写入临时文件后原地替换)")
|
||||
import time as _t
|
||||
_t0 = _t.time()
|
||||
|
||||
# 路径变量提前声明,确保异常处理中可以访问
|
||||
_tmp_data = str(_tmp_bsq)
|
||||
_tmp_hdr = _tmp_data + '.hdr'
|
||||
_tmp_aux = _tmp_data + '.aux.xml'
|
||||
_bip_hdr = img_path + '.hdr'
|
||||
if not os.path.exists(_bip_hdr):
|
||||
_bip_hdr = os.path.splitext(img_path)[0] + '.hdr'
|
||||
|
||||
def _make_writable(filepath):
|
||||
"""去掉只读属性,避免 Windows 下 unlink/rename 拒绝访问"""
|
||||
if os.path.exists(filepath):
|
||||
try:
|
||||
os.chmod(filepath, 0o666)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
try:
|
||||
from osgeo import gdal
|
||||
gdal.UseExceptions()
|
||||
@ -108,14 +125,11 @@ def _ensure_bsq(img_path):
|
||||
)
|
||||
_elapsed = _t.time() - _t0
|
||||
|
||||
# 记录临时文件路径(后续重命名时用到)
|
||||
_tmp_data = str(_tmp_bsq)
|
||||
_tmp_hdr = _tmp_data + '.hdr'
|
||||
# ★ 验证临时 BSQ 文件是否成功生成
|
||||
if not os.path.exists(_tmp_data) or os.path.getsize(_tmp_data) == 0:
|
||||
raise RuntimeError(f"gdal.Translate 未生成有效的临时 BSQ 文件: {_tmp_data}")
|
||||
|
||||
# ★ 保存原始 HDR 中的波长/元数据(gdal.Translate 不保留)
|
||||
_bip_hdr = img_path + '.hdr'
|
||||
if not os.path.exists(_bip_hdr):
|
||||
_bip_hdr = os.path.splitext(img_path)[0] + '.hdr'
|
||||
_hdr_extras = {} # 需要保留的元数据
|
||||
if os.path.exists(_bip_hdr):
|
||||
try:
|
||||
@ -142,22 +156,36 @@ def _ensure_bsq(img_path):
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# 删除原始 BIP 及其 HDR
|
||||
if not os.path.exists(_bip_hdr):
|
||||
_bip_hdr = os.path.splitext(img_path)[0] + '.hdr'
|
||||
# ★ 先处理只读属性,再删除原始 BIP 及其 HDR
|
||||
_make_writable(str(_src))
|
||||
_make_writable(_bip_hdr)
|
||||
_src.unlink()
|
||||
if os.path.exists(_bip_hdr):
|
||||
os.unlink(_bip_hdr)
|
||||
|
||||
# 将 BSQ 临时文件重命名为原始文件名(所有下游步骤零改动)
|
||||
_final = str(_src)
|
||||
os.rename(_tmp_data, _final)
|
||||
_final_hdr = _final + '.hdr'
|
||||
|
||||
# 如果目标 HDR 残留(只读等情况),先处理再删除
|
||||
_make_writable(_final_hdr)
|
||||
if os.path.exists(_final_hdr):
|
||||
os.unlink(_final_hdr)
|
||||
|
||||
os.rename(_tmp_data, _final)
|
||||
if os.path.exists(_tmp_hdr):
|
||||
if os.path.exists(_final_hdr):
|
||||
os.unlink(_final_hdr)
|
||||
os.rename(_tmp_hdr, _final_hdr)
|
||||
|
||||
# ★ 清理孤儿 aux.xml(临时文件和可能残留的目标 aux.xml)
|
||||
_final_aux = _final + '.aux.xml'
|
||||
for _orphan_aux in [_tmp_aux, _final_aux]:
|
||||
if os.path.exists(_orphan_aux):
|
||||
try:
|
||||
_make_writable(_orphan_aux)
|
||||
os.unlink(_orphan_aux)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# ★ 将波长等元数据写回新 HDR
|
||||
if _hdr_extras and os.path.exists(_final_hdr):
|
||||
try:
|
||||
@ -179,14 +207,20 @@ def _ensure_bsq(img_path):
|
||||
f"BIP → BSQ 原地替换,所有路径无需修改")
|
||||
return str(_final)
|
||||
except Exception as e:
|
||||
# 清理失败的临时文件
|
||||
if os.path.exists(_tmp_data):
|
||||
try:
|
||||
os.unlink(_tmp_data)
|
||||
if os.path.exists(_tmp_hdr):
|
||||
os.unlink(_tmp_hdr)
|
||||
except Exception:
|
||||
pass
|
||||
# ★ 异常处理:绝不删除临时 BSQ 文件(它可能是唯一完好的数据副本)
|
||||
# 如果 gdal.Translate 成功生成了临时文件,保留它供手动恢复
|
||||
if os.path.exists(_tmp_data) and os.path.getsize(_tmp_data) > 0:
|
||||
print(f"[BIP→BSQ] ⚠ 转换中途失败,但临时 BSQ 文件已保留: {_tmp_data}")
|
||||
print(f"[BIP→BSQ] 请手动检查该文件,确认无误后可重命名为 {img_path}")
|
||||
else:
|
||||
# 只有转换根本没产出时才清理(可能是磁盘满等)
|
||||
for _f in [_tmp_data, _tmp_hdr, _tmp_aux]:
|
||||
if os.path.exists(_f):
|
||||
try:
|
||||
_make_writable(_f)
|
||||
os.unlink(_f)
|
||||
except Exception:
|
||||
pass
|
||||
print(f"[BIP→BSQ] 转换失败: {e},继续使用 BIP")
|
||||
return img_path
|
||||
|
||||
|
||||
Reference in New Issue
Block a user