git lfs指针文件是纯文本,格式为固定键值对,含version、oid和size行;c#需按行解析并校验version合法性,用trimstart()处理bom与空格,避免split(':')误切。

Git LFS指针文件长什么样
Git LFS不真正存储大文件,而是用纯文本指针文件代替——你看到的 .gitattributes 里匹配的文件(比如 *.psd),在工作区实际是小文本,内容类似:
version https://www.php.cn/link/34390147aa604589f654dca78ae78da3 oid sha256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08 size 23
这不是 YAML 或 JSON,就是固定格式的键值对。C# 解析它不需要第三方库,File.ReadAllLines + 简单分割就能搞定。
用C#安全读取并提取oid和size
别直接 Split(':') 全局切分——字段值本身可能含冒号(比如未来扩展协议),必须按行解析、识别前缀。关键点:
-
oid行格式严格为"oid sha256:<hex>"</hex>,空格后才是哈希值,不能跳过空格直接取第二段 -
size是十进制整数,但 Git LFS 规范允许带空格,建议用int.TryParse(..., NumberStyles.Integer) - 文件可能损坏或非LFS指针(比如被误提交的普通文本),必须检查
version行是否存在且匹配"version https://www.php.cn/link/34390147aa604589f654dca78ae78da3"
示例片段:
var lines = File.ReadAllLines(pointerPath);
string oid = null;
int size = -1;
<p>foreach (var line in lines)
{
if (line.StartsWith("version ") && !line.Contains("<a href="https://www.php.cn/link/34390147aa604589f654dca78ae78da3">https://www.php.cn/link/34390147aa604589f654dca78ae78da3</a>"))
throw new InvalidOperationException("Not a valid LFS pointer");</p><pre class='brush:php;toolbar:false;'>if (line.StartsWith("oid "))
{
oid = line.Substring(4).Trim().Split(' ', 2)[1]; // 取"sha256:..."部分
}
else if (line.StartsWith("size "))
{
if (!int.TryParse(line.Substring(5).Trim(), out size))
size = -1;
}}
为什么不能用JsonConvert.DeserializeObject
网上有人试过把指针当 JSON 解——会失败。因为:
- 指针文件不是 JSON:没花括号、没引号、键名无引号、值含空格不转义
- 用
JsonConvert强转只会抛JsonReaderException,错误信息像"After parsing a value an unexpected character was encountered" - 即使加了自定义
JsonTextReader试图跳过格式校验,也绕不过语法层面的不兼容
硬套 JSON 库既没收益又埋异常风险,纯文本解析更轻、更稳、更可控。
注意跨平台换行和BOM
Windows 写的指针文件用 \r\n,Linux/macOS 是 \n;有些编辑器(尤其 VS)保存时可能加 UTF-8 BOM。这些都会影响 StartsWith 判断:
- 用
File.ReadAllLines自动处理换行,不用自己Split('\n') - 读取前先用
File.ReadAllBytes检查前3字节是否为0xEF, 0xBB, 0xBF,若是 BOM,用Encoding.UTF8显式解码并跳过 - 所有
StartsWith调用前,确保字符串已.TrimStart()—— BOM 或缩进空格会让匹配失败
指针文件看着简单,但生产环境里混着不同编辑器、CI 系统、Git 客户端版本,空白字符和编码才是最常翻车的地方。










