
简介面向光纤通信运维与工程调试人员的 OTDR 测试曲线查看工具支持直接打开 .sor 格式文件并还原链路测试曲线可自由调整横纵轴比例便于定位事件点与损耗细节解决通用看图软件无法解析该格式的问题。压缩包共 30 个文件约 6.32MB其中包含安装主程序及 cab/bin 组件、多组 .001.006 示例曲线数据、trl/pmt 辅助数据文件另有 PDF 版操作手册与英文快速参考指南适合初次接触 Anritsu TraceView 的读者边装边学。配套示例文件可用来反复练习缩放、平移等曲线操作对照手册理解 OTDR 测量结果已有 758 人浏览学习对于需要分析历史测试曲线的现场人员较实用。1. 先把 .sor 文件讲明白什么在阻挠你打开它一条刚验收的主干光缆最后几芯的测试曲线存在 OTDR 里导出来是标准的 .sor 文件。拿到自己电脑上双击系统提示没有关联程序用记事本打开满屏乱码去网上搜「OTDR 测试曲线的 .sor 文件打开软件」下载装了一堆有的要授权有的直接报错。这篇文就是冲着这个痛点来的.sor 到底是什么哪些软件能真正打开它原厂、第三方、自研三条路各自的落地步骤和边界在哪最后把那些最容易让新手翻车的细节一次性排掉。看完你至少能把手头的 .sor 文件稳定打开、正确读数也能判断值不值得专门写个解析工具。2. .sor 的二进制底细乱码背后是曲线、参数和事件表在选软件之前得先弄明白 .sor 为什么这么难伺候。它不像 CSV 或 PDF没有统一的公开标准它是 OTDR 仪器厂商自己定义的一种私有二进制格式用来把一次完整的链路测试打包成一个文件。之所以用二进制而不是文本是因为曲线数据量大、浮点精度要求高用文本存体积会膨胀好几倍解析也慢。2.1 用记事本打开全是乱码这不是文件坏了很多刚上手的人第一反应是文件损坏或者拷贝出错其实绝大多数情况不是。.sor 文件头通常是一段 ASCII 字符后面跟着一堆二进制块记事本按文本解析把 0x00 当成特殊字符、把高位字节当成乱码于是满屏「NUL」和怪符号。判断文件到底是不是正常的 .sor最稳的办法是用十六进制查看而不是用记事本。Linux 和 macOS 下开箱即用file fiber_test_01.sor xxd -l 128 fiber_test_01.sorfile命令会根据文件头特征字节给出类型猜测xxd -l 128只看前 128 字节。第一个命令用于快速确认文件不是空文件或纯文本伪装第二个命令能直接看到头部有没有 ASCII 厂商标识和版本号。如果头部出现可读的厂商缩写和类似2.0.1的版本字符串这个文件基本是健康的。Windows 下没有自带 xxd可以用 Notepad 的十六进制插件或者装一个轻量的十六进制编辑器。看头部而不是看全文件是为了一眼判断「这是哪个厂商、哪个格式版本的文件」这决定了后面用哪个解析规则。很多第三方软件打不开问题恰恰出在这一步它只支持某几家厂商的某一版本。2.2 .sor 里到底存了什么测量参数、采样点与事件表从结构上看一个完整的 .sor 文件至少包含四块内容文件头、测量参数区、采样数据区、事件表区部分格式结尾还有校验区。文件头存厂商标识、格式版本测量参数区存波长、脉冲宽度、测量距离范围、平均时间、群折射率等采样数据区是整条曲线每个采样点对应一个距离和该距离上的回波损耗值事件表区存放自动分析出的接头、断点、熔接损耗等事件。四个数据块并不总是按固定偏移排列不少厂商在文件尾留了索引区指向各个数据块的实际位置固件升级后内部字段也可能增加。所以对 .sor 的解析没有一份权威的公开文档社区做法基本是「用新固件导出一份、旧固件导出一份对比字段找出规律」。这也是为什么原厂软件能开、第三方工具偶尔失手、自研脚本需要不断校对的根本原因。下表是测量参数区里最常见、也最影响读数正确性的几个字段参数类型对曲线的影响波长整数决定损耗基数1550nm 和 1310nm 不能混用脉冲宽度整数ns影响盲区大小和曲线噪点测量范围浮点km决定横轴总长度平均时间整数秒越长信噪比越好群折射率浮点直接决定距离读数偏差 1% 就是每公里 10 米误差采样间隔浮点m决定曲线点数密度其中群折射率是最容易翻车的一项。测试时仪器里设的折射率和打开软件里默认的折射率如果不一致整条曲线的距离轴就会整体偏移断点定位差几十米属于正常现象。后面避坑章会专门再讲。事件表区则直接关系着出验收报告验收时甲方要看的断点位置、熔接损耗值很多就来自事件表而不是人工在曲线上取点。理解了这些再看软件选型就有判断力了所谓「能打开 .sor」不是把曲线画出来就完事而是能把这一整套参数正确还原。3. 打开 .sor 的软件选型原厂工具、第三方查看器与自研脚本面对一个打不开的 .sor有三条路装原厂配套软件、用第三方查看器、自己写解析。三条路各有适用场景下面从安装成本、格式兼容、报表能力和长期维护四个维度展开。3.1 原厂配套软件最省事但版本匹配是玄学最常见做法是装仪器厂商随附的 PC 端软件。买 OTDR 时一般会附带一张光盘或一个下载入口装上之后能打开本厂所有格式的曲线文件也能导出 PDF 报告。到仪器厂商官网的支持与下载区搜产品型号一般能找到对应 PC 查看软件下载时要留意版本说明选与固件匹配的版本而不是无脑追新。走这条路的核心问题是版本匹配仪器固件升级后导出的 .sor旧版 PC 软件经常报「文件版本不支持」反过来新版软件对老仪器的兼容性倒是好一些。我见过不止一次仪器是新款电脑上装的软件比固件老了两代打开曲线后事件表直接消失折腾一晚上发现只是版本问题。我的建议是装两个版本一个与仪器固件同期的最新版一个能打开老旧文件的历史版。如果装了最新版仍打不开老文件就去官网找该仪器固件发布当月的软件包。另一个高频坑是授权有些厂商的 PC 软件是免费的但要在线激活离线环境下装完没法登录功能会锁住。现场施工的笔记本往往不上网所以提前准备一个已激活的安装包或者干脆用第三方离线查看器能少踩很多坑。3.2 第三方查看器跨格式方便但要小心单位换算第三方查看器的价值在于「跨厂商」。一个运维手里往往同时有不同品牌的 OTDR曲线格式有 .sor、.trc、.sdr 等一堆后缀原厂软件各自为政第三方工具则试图统一打开。这类工具通常界面更轻打开速度快适合现场快速看图、确认断点位置。但第三方工具有几个边界要注意。第一格式覆盖率不等于版本覆盖率新版固件如果改了内部结构第三方工具会晚几个月甚至不更新。第二部分工具会把数据换算成自己的单位比如把 mW 显示成 dBm、把群折射率按默认值重算导致同一段落损耗读数对不上。第三免费工具往往不带批量导出 PDF 的功能出正式验收报告仍要回到原厂软件。我的选型原则是现场应急用第三方正式出报告回原厂。判断一个第三方工具能不能用按四步走先看它声明支持的格式列表和版本范围再用一个已知测试结果的 .sor 试开对照原厂软件里的断点距离和段落损耗读数一致才纳入工具链最后确认它是否保存折射率等原始参数。3.3 选型判断什么时候值得自己动手解析自己动手写解析器不是炫技而是被需求逼出来的。以下几种情况我会建议直接走自研这条路需要批量处理几百个 .sor 文件并入库需要把曲线叠加比对比如同一根纤芯一年前的曲线和今天的曲线叠在一起看损耗变化需要把数据接到自己的报表系统里原厂软件导出的 PDF 没法二次加工。成本上算一笔账手动打开一个 .sor 再截图导出大约两分钟批量处理 300 个文件就是十个小时。而逆向一个最基本的参数区加采样数据区动手快的话半天能跑通跑完这十个小时就省下来了。自研的成本主要在格式逆向而不是画图。文件头、参数区相对好找采样数据区多数是定长浮点数组麻烦的是事件表的位置和字段含义这个没有文档只能靠对比。好在大多数场景根本用不到事件表——看曲线、取断点距离、算段落损耗只需要参数区和采样数据区就够了。下一章给出一个能跑通的最小解析器把这两块数据吃下来覆盖绝大多数日常需求。4. 用 Python 写一个 .sor 查看器解析、画曲线、出事件表这一章动手做最小可用的解析器。环境是 Python 3依赖只有标准库和 matplotlib不需要任何第三方 OTDR 库。这里的解析策略是「先探测、再按规则取」因为 .sor 没有公开统一的偏移表死记偏移十有八九在下一个固件版本翻车。4.1 第一步用十六进制嗅探出文件头里的厂商线索拿到一个 .sor 之后不要立刻跳进解析先让脚本把文件头里可读的 ASCII 字符串全部提出来确认厂商标识和版本号。这一步是整个解析的地基决定后面走哪套字段规则。import re def probe_sor(path, max_bytes512): with open(path, rb) as fh: raw fh.read(max_bytes) # 提取 4 个及以上连续可打印 ASCII 字符视为候选标签 tags re.findall(rb[A-Za-z0-9_\.]{4,}, raw) printable [t.decode(ascii, errorsignore) for t in tags] # 顺带打印前 64 字节的十六进制方便人工核对 hex_head raw[:64].hex( ) return printable, hex_head path fiber_test_01.sor print(probe_sor(path))逻辑说明re.findall用连续 ASCII 片段把厂商标识、固件版本这类可读字符串从二进制里捞出来hex_head是给人工看的第一手资料。运行后如果 printable 里能看到类似厂商缩写和版本号说明文件头结构正常可以进入下一步如果全是随机字节就要怀疑文件是不是拷坏了或者根本不是 .sor。参数说明max_bytes512只扫描头部因为文件头和参数区通常集中在前几百字节全文件扫描不仅慢还会捞出一堆采样数据里的伪标签。采样数据区是浮点数组某些浮点字节也可能恰好组成可打印字符干扰判断。实际使用中可以把范围改成 256速度快且足够用。4.2 第二步写一个通用的参数与采样点解析器明确一点不同厂商、不同固件版本偏移值不同。这里给的是通用框架核心是把「定位数据块」和「解析字段」两件事拆开。import struct class SorTrace: def __init__(self, raw): self.raw raw self.sample_count 0 self.sampling_interval 0.0 self.wavelength 0 self.pulse_ns 0 self.trace [] # 每个元素是 (距离_m, 回波_dB) def parse_params(self, offset_map): # offset_map 是一个 dict键是字段名值是 (I 或 f, 偏移量) for name, (fmt, off) in offset_map.items(): val struct.unpack_from(fmt, self.raw, off)[0] setattr(self, name, val) def parse_samples(self, data_offset, count, step8): # 常见布局每个采样点 8 字节前 4 字节距离(float)后 4 字节回波(float) for i in range(count): base data_offset i * step dist, level struct.unpack_from(ff, self.raw, base) self.trace.append((dist, level)) raw open(fiber_test_01.sor, rb).read() tr SorTrace(raw) # offset_map 需要通过 probe 和对照实验确定示例只演示调用方式 tr.parse_params({ wavelength: (I, 0x30), pulse_ns: (I, 0x34), sample_count: (I, 0x40), })逻辑说明parse_params接收一个 offset_map把「字段格式 偏移量」从业务逻辑里解耦。以后遇到新的固件版本只需要换一组 offset_map不用改解析主体。parse_samples按定长步长读取采样点假设每个点 8 字节、前 4 字节距离、后 4 字节回波损耗。这是最经典的布局但不是唯一布局有的固件会把距离改成整数采样序号需要用sample_count和sampling_interval换算成米。参数说明step8是步长改成 16 或其它值时要注意距离、回波、甚至波长字段也可能同时变化。ff表示小端两个单精度浮点如果解析结果出现明显错位先试II两个整数再试大端ff。这个「换格式试错」的过程不是玄学是逆向二进制文件的常态对照已知文件里的断点距离就能反向确认哪组参数正确。提示上面 offset_map 里的 0x30、0x34 等偏移只用于演示真实值必须用自己手里的文件校准。直接套用网上搜到的偏移用在不同固件上是解析脚本最常见的翻车原因。4.3 第三步matplotlib 把曲线画出来顺带导出 CSV拿到采样点数组之后出图就是套模板的事。曲线图的横轴是距离纵轴是回波损耗dB断点和接头处会表现为明显的台阶或反射尖峰。import matplotlib matplotlib.use(Agg) import matplotlib.pyplot as plt def plot_trace(tr, output_png): xs [p[0] for p in tr.trace] ys [p[1] for p in tr.trace] plt.figure(figsize(10, 4)) plt.plot(xs, ys, linewidth0.8) plt.xlabel(Distance (m)) plt.ylabel(Return Loss (dB)) plt.title(fOTDR Trace ({tr.wavelength}nm, {tr.pulse_ns}ns)) plt.grid(True, alpha0.3) plt.savefig(output_png, dpi150) plt.close() def export_csv(tr, output_csv): with open(output_csv, w, newline) as f: for dist, level in tr.trace: f.write(f{dist:.2f},{level:.3f}\n) plot_trace(tr, trace.png) export_csv(tr, trace.csv)逻辑说明plot_trace把解析结果画成 PNG不弹 GUI适合批量处理export_csv把曲线数据落成文本方便后续进 Excel 或数据库。这两件事放在同一个脚本里日常批量处理 100 条曲线也就是一个 for 循环的事。参数说明dpi150适合屏幕查看印刷报告建议 300。linewidth0.8是经验值太粗会盖住反射尖峰的细节太细在 10 公里长度上又看不见。agg后端保证在没有显示器的服务器上也能出图这是跑批的常用做法。如果第 4.2 节的偏移是错的曲线会是噪声或者整体偏移这时候回到 4.1 的 probe 结果对照已知断点距离反推采样步长两个来回基本能校准到位。5. .sor 打开避坑手册5 个真实翻车现场与排查思路这一章把 .sor 从拿到手到出报告过程中最容易踩的坑列成排查清单每条按「现象 → 原因 → 解决」展开都是实操里反复出现的问题。5.1 现象用记事本打开全是乱码以为文件坏了原因.sor 是厂商自定义的私有二进制格式记事本默认按文本解码把字节流里的控制字符和浮点数据当成文本字符渲染自然满屏乱码。这恰恰说明文件里是有内容的跟文件损坏没有必然关系。解决先不要急着删文件或重新测试。用十六进制编辑器打开头部如果能找到 ASCII 厂商标识和版本字符串说明文件是完整的再用 2.2 节的方法判断是哪家厂商的格式决定用哪套软件打开。判断健康与否要看头部可读字符串和文件大小是否合理而不是看乱码多少。5.2 现象装了最新版原厂软件反而打不开老仪器导出的 .sor原因新软件默认支持新固件的文件结构对老旧格式的兼容往往不是重点某些字段在新版里被废弃后解析器直接跳过了整个数据块。这种「新版不认老文件」的情况在固件迭代快的仪器上尤其常见。解决不要死磕最新版。找到与仪器固件同年发布的软件版本装上老文件一般就能打开。手头如果有多台不同年代的仪器建议保留一旧一新两个软件单独建两个快捷方式别让它们互相覆盖。装完后用一台最老的仪器导出文件做回归测试确认两个版本都能正常打开再收工。5.3 现象第三方工具打开后断点距离比实测多了 40 多米原因距离计算依赖群折射率。第三方的折射率默认值和测试时仪器里的设置不一致偏差哪怕只有 0.5%在 10 公里级别就是 50 米的差距。这是所有跨软件查看场景里最隐蔽的问题读数差了还不容易察觉。解决打开文件后先看测量参数区里的折射率字段再把软件设置里的折射率改成一致。如果第三方软件不显示折射率就用 2.2 节的方法从原始字节里读出来或者回原厂软件核对测试信息。这个参数是软件切换里最容易忽略、也是影响读数最大的一个也是我踩过最多次的血泪经验。5.4 现象第三方工具打开后曲线正常但事件表是空的原因事件表是 OTDR 自动分析的结果很多 .sor 把它放在文件尾部且带独立的校验字段。如果用 U 盘反复拷贝或通过聊天软件传输文件尾可能被截断或改写导致事件表解析失败。曲线数据区在文件前部所以看起来正常事件表却在尾部悄悄丢了。解决重新从仪器导出并完整拷贝文件用file命令或十六进制工具确认文件大小与导出时一致。如果文件完整但事件表还是空的再检查仪器端是否关闭了自动事件分析部分仪器在测试时关了自动分析原厂软件打开也是空的这属于测试设置问题不是查看工具故障。5.5 现象文件名是 .sor但原厂软件和第三方工具都不认原因不同厂商都会把自己的私有格式命名为 .sor后缀相同不代表格式相同。把 A 厂商的文件拖进 B 厂商的软件报错是完全正常的。做代维的人尤其容易遇到一个现场收了一堆其他单位移交的曲线文件后缀全是 .sor来源五花八门。解决用 4.1 节的 probe 方法看文件头的 ASCII 标识确认厂商或者问清楚导出的仪器型号和固件版本。跨厂商场景优先用第三方查看器原厂软件之间没有互通的义务。验收交接时收到别人发来的 .sor先问一句哪台仪器测的能省不少事。6. 进阶把 .sor 批量转 CSV建自己的曲线对比台账看完上面的方案还有一个高频需求处理不了批量。几百条曲线一条条打开再截图既慢又没法横向对比。我的做法是把解析脚本包成一个批处理入口一次扫目录把所有 .sor 转成统一命名的 CSV 和一个总索引表后续所有分析都在这三个东西上做原始 .sor、对应 CSV、叠加对比图。import glob, csv, os def batch_export(folder): rows [] for path in glob.glob(os.path.join(folder, *.sor)): raw open(path, rb).read() tr SorTrace(raw) # 偏移规则从 4.2 节的校准结果来这里省略具体 offset_map tr.parse_params(offset_map) tr.parse_samples(data_offset, tr.sample_count) base os.path.splitext(os.path.basename(path))[0] csv_path os.path.join(folder, base .csv) with open(csv_path, w, newline) as fh: for dist, level in tr.trace: fh.write(f{dist:.2f},{level:.3f}\n) rows.append([base, tr.wavelength, tr.pulse_ns, len(tr.trace)]) with open(os.path.join(folder, index.csv), w, newline) as fh: wr csv.writer(fh) wr.writerow([file, wavelength, pulse_ns, points]) wr.writerows(rows)逻辑说明batch_export扫目录里所有 .sor逐个解析并落 CSV最后生成一个 index.csv 记录每条曲线的元信息作为台账入口。配合 4.3 节的plot_trace再把同纤芯的历史曲线叠画就能直观看到损耗劣化趋势。这一步的价值在于把 OTDR 数据从「看一次扔一次」变成可长期积累的资产。我自己的教训是第一次批量转换时没校验折射率整批 CSV 的距离都是偏的后面所有对比全部返工。从那以后脚本一开头就先输出每条文件的折射率和脉冲宽度和测试原始记录逐条核对再入库。数据进了台账错误会放大十倍。工具能跑通只是第一步参数校验才是批量处理里真正要花时间的地方。希望帮到你。本文还有配套的精品资源点击获取