fix(io/gpr): readIprb 以文件大小为权威推导道数
真实明星路数据规律为「道数 == LAST TRACE」(非 lastTrace+1),旧实现硬假设 traces=lastTrace+1 并严格校验文件字节相等,导致真实 .iprb 装配抛错。 改为 traces = fileBytes / (samples*2),要求字节数为 samples*2 整数倍(否则抛), lastTrace 仅作 header 提示不再决定道数。更新单测:新增 FileSizeIsAuthoritativeNotLastTracePlusOne(lastTrace=N 但文件含 N 道 → traces==N), ReadsInt16AndLayout/ThrowsOnSizeMismatch 语义不变仍通过。
This commit is contained in:
parent
bfd7d4aafd
commit
d75a52e519
|
|
@ -12,21 +12,28 @@ BScan readIprb(const std::string& path, const IprHeader& h) {
|
|||
throw std::runtime_error("readIprb: 无法打开文件: " + path);
|
||||
}
|
||||
|
||||
const std::streamsize fileSize = f.tellg();
|
||||
const std::int64_t traces = static_cast<std::int64_t>(h.lastTrace) + 1;
|
||||
const std::int64_t count = static_cast<std::int64_t>(h.samples) * traces;
|
||||
const std::int64_t expected = count * 2;
|
||||
if (fileSize != expected) {
|
||||
throw std::runtime_error("readIprb: 文件大小与 samples*traces*2 不符: " + path);
|
||||
// 文件大小为权威:道数由实测字节数推导,而非 header 的 LAST TRACE。
|
||||
// 真实数据规律:实际道数 = LAST TRACE(非 LAST TRACE+1),故不能硬假设 +1。
|
||||
const std::int64_t fileBytes = static_cast<std::int64_t>(f.tellg());
|
||||
const std::int64_t samples = static_cast<std::int64_t>(h.samples);
|
||||
if (samples <= 0) {
|
||||
throw std::runtime_error("readIprb: samples 非法(<=0): " + path);
|
||||
}
|
||||
const std::int64_t bytesPerTrace = samples * 2; // int16
|
||||
if (fileBytes % bytesPerTrace != 0) {
|
||||
throw std::runtime_error(
|
||||
"readIprb: 文件大小不是 samples*2 的整数倍: " + path);
|
||||
}
|
||||
const std::int64_t traces = fileBytes / bytesPerTrace;
|
||||
|
||||
BScan b;
|
||||
b.samples = h.samples;
|
||||
b.traces = traces;
|
||||
b.data.resize(static_cast<std::size_t>(h.samples) * traces);
|
||||
b.data.resize(static_cast<std::size_t>(samples * traces));
|
||||
|
||||
f.seekg(0, std::ios::beg);
|
||||
f.read(reinterpret_cast<char*>(b.data.data()), static_cast<std::streamsize>(expected));
|
||||
f.read(reinterpret_cast<char*>(b.data.data()),
|
||||
static_cast<std::streamsize>(fileBytes));
|
||||
if (!f) {
|
||||
throw std::runtime_error("readIprb: 读取数据失败: " + path);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,8 +16,9 @@ struct BScan {
|
|||
std::vector<int16_t> data; // 大小 = samples*traces
|
||||
};
|
||||
|
||||
// 读取 .iprb 二进制 B-scan:traces = h.lastTrace+1;
|
||||
// 校验 samples*traces*2 == 文件字节数,不符抛 std::runtime_error;文件打不开抛 std::runtime_error。
|
||||
// 读取 .iprb 二进制 B-scan:以文件大小为权威,traces = fileBytes / (samples*2)。
|
||||
// 要求 fileBytes 是 samples*2 的整数倍,否则抛 std::runtime_error;文件打不开抛 std::runtime_error。
|
||||
// 注意:h.lastTrace 仅作 header 提示,不决定道数(真实数据规律为道数==lastTrace,非 +1)。
|
||||
BScan readIprb(const std::string& path, const IprHeader& h);
|
||||
|
||||
} // namespace geopro::io::gpr
|
||||
|
|
|
|||
|
|
@ -25,12 +25,24 @@ TEST(IprbReader, ReadsInt16AndLayout) {
|
|||
std::remove(path.c_str());
|
||||
}
|
||||
TEST(IprbReader, ThrowsOnSizeMismatch) {
|
||||
std::vector<int16_t> raw{0,1,2,3,4}; // 5 个,与 samples*traces 不符
|
||||
std::vector<int16_t> raw{0,1,2,3,4}; // 5 个,非 samples 整数倍 → 抛
|
||||
auto path = writeTmp(raw);
|
||||
IprHeader h{}; h.samples = 3; h.lastTrace = 3; // 期望 12
|
||||
IprHeader h{}; h.samples = 3; h.lastTrace = 3; // 5*2=10, 10%6!=0
|
||||
EXPECT_THROW(readIprb(path, h), std::runtime_error);
|
||||
std::remove(path.c_str());
|
||||
}
|
||||
// 真实数据规律:LAST TRACE=N 但文件恰含 N 道(非 N+1)。
|
||||
// 文件大小为权威 → traces 应等于文件实含道数 N,而非 N+1。
|
||||
TEST(IprbReader, FileSizeIsAuthoritativeNotLastTracePlusOne) {
|
||||
// 4 道×3 采样 = 12 个 int16,文件恰含 4 道。
|
||||
std::vector<int16_t> raw{0,1,2, 10,11,12, 20,21,22, 30,31,32};
|
||||
auto path = writeTmp(raw);
|
||||
IprHeader h{}; h.samples = 3; h.lastTrace = 4; // 假设 +1 会得 5 道(错)
|
||||
auto b = readIprb(path, h);
|
||||
EXPECT_EQ(b.traces, 4); // 以文件大小为准 → 4,复刻真实数据 traces==lastTrace 规律
|
||||
EXPECT_EQ(b.data.size(), 12u);
|
||||
std::remove(path.c_str());
|
||||
}
|
||||
TEST(IprbReader, ThrowsOnMissingFile) {
|
||||
IprHeader h{}; h.samples = 3; h.lastTrace = 3;
|
||||
EXPECT_THROW(readIprb("____no_such_file____.iprb", h), std::runtime_error);
|
||||
|
|
|
|||
Loading…
Reference in New Issue