VBScript 的 ADODB.Stream 如何截断覆盖后残留的旧内容?
解决方法:写入后调用 SetEOS
在 stream.WriteText strContent 之后、stream.SaveToFile p, 2 之前调用 stream.SetEOS,截断新内容后面残留的旧数据:
stream.Position = 0
stream.WriteText strContent
stream.SetEOS
stream.SaveToFile p, 2
SetEOS 会把流的结束位置设为当前 Position。完整写入新内容后,当前位置就在新内容末尾。此时截断并保存,文件就不会带上旧内容的尾部。
为什么覆盖保存仍然会留下旧字符?
stream.Position = 0 只会把读写位置移到开头,不会清空流。
从开头调用 WriteText 时,新内容会覆盖已有数据。如果新内容较短,未被覆盖的旧数据仍会留在流中。SaveToFile p, 2 虽然会覆盖目标文件,保存的却是整个流,因此残留数据也会被写入文件。
例如,原内容是 abcdef,从开头写入 xyz 后,流中仍可能是 xyzdef。写入后调用 SetEOS,才会将其截断为 xyz。
修改后的完整代码
以下代码沿用问题中的前提:p 已经是文件完整路径,re 已经是创建好的 VBScript.RegExp 对象。
Set stream = CreateObject("ADODB.Stream")
stream.Mode = 3
stream.Type = 2
stream.Charset = "UTF-8"
stream.Open
stream.LoadFromFile p
stream.Position = 0
strContent = stream.ReadText
re.IgnoreCase = False
re.Global = False
re.Pattern = ",""beautifybuttonstate"":""[^""]+"""
strContent = re.Replace(strContent, ",""beautifybuttonstate"":""USER_HIDE""")
stream.Position = 0
stream.WriteText strContent
stream.SetEOS
stream.SaveToFile p, 2
stream.Close
Set stream = Nothing
如果需要先清空整个流,也可以把写入部分改成:
stream.Position = 0
stream.SetEOS
stream.WriteText strContent
stream.SaveToFile p, 2
两种方式选择一种即可。前者在写入后截断,后者在写入前清空流。
不要用 Len(strContent) 推算流的截断位置:Position 按字节计量,UTF-8 文本的字符数不一定等于字节数。让 WriteText 自动推进位置,再调用 SetEOS 即可。
修改 JSON 时,正则表达式有哪些限制?
现有正则表达式只适合格式受到严格控制的文件,有以下限制:
- 要求字段前面紧接逗号,无法匹配对象中的第一个字段。
- 要求冒号附近没有空格或换行。
- 使用
+,无法匹配空字符串值。 - 没有处理 JSON 字符串中的转义引号。
re.Global = False只替换第一个匹配项;改成True后,也无法区分不同嵌套对象中的同名字段。
如果 JSON 的结构或格式可能变化,更合适的做法是使用适用于运行环境的 JSON 解析库解析文本,按目标对象的路径修改 beautifybuttonstate,再序列化并写回文件。VBScript 本身没有内置的 JSON.parse 或 JSON.stringify;具体调用代码取决于所选解析库,不能直接套用 JavaScript 的 API。
如果暂时继续使用现有正则表达式,添加 SetEOS 可以解决文件尾部残留问题,但仍需单独确认目标字段是否被正确匹配。
备注:内容仅供参考。
