C#中如何通过FileStream.Position和指定长度获取字符串
实现二进制文件中指定位置的子串读取功能(类似String.Substring)
首先,你的现有代码已经能成功定位到目标字节序列在文件中的起始偏移位置(也就是fs.Position - matchBytes.Length),接下来要实现类似Substring的功能,核心就是从这个偏移位置开始读取指定长度的字节,再转换成你需要的格式(比如十六进制字符串或者普通文本)。
解决方案步骤
- 定位文件流到目标起始偏移:使用
FileStream.Seek()方法将文件指针移动到你要读取的起始位置。 - 读取指定长度的字节:根据需求读取对应长度的字节数组,注意处理文件末尾的边界情况(比如剩余字节不足指定长度时,只读取剩余部分)。
- 转换为目标格式:将读取到的字节数组转换成十六进制字符串(和你搜索的格式一致),或者根据实际编码转换成普通文本字符串。
完整代码实现
首先,添加一个专门的函数来读取指定位置的子内容,再修改你现有的example函数来调用它:
public void example() { string match = "400000002532"; // 12字符的十六进制搜索串 byte[] matchBytes = StringToByteArray(match); int substringLength = 32; // 示例:读取匹配位置开始的32字节(对应64字符的十六进制串) foreach (var jsFile in jsscan) { using (var fs = new FileStream(jsFile, FileMode.Open)) { int i = 0; int readByte; while ((readByte = fs.ReadByte()) != -1) { if (matchBytes[i] == readByte) { i++; } else { i = 0; } if (i == matchBytes.Length) { long startOffset = fs.Position - matchBytes.Length; Console.WriteLine("找到匹配,位置范围:{0} 到 {1}.", startOffset, fs.Position); // 调用读取子串的函数 string resultHex = ReadHexSubstringFromBinaryFile(fs, startOffset, substringLength); Console.WriteLine("从匹配位置开始的{0}字节十六进制内容:{1}", substringLength, resultHex); // 如果需要转换成普通文本(比如UTF8编码),可以用这个: // string resultText = ReadTextSubstringFromBinaryFile(fs, startOffset, substringLength, Encoding.UTF8); // Console.WriteLine("转换为UTF8文本:{0}", resultText); break; } } } } } // 将十六进制字符串转字节数组(你的现有函数,保留) public static byte[] StringToByteArray(String hex) { int NumberChars = hex.Length; byte[] bytes = new byte[NumberChars / 2]; for (int i = 0; i < NumberChars; i += 2) bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16); return bytes; } // 从二进制文件指定位置读取字节,返回十六进制字符串(类似Substring的十六进制版本) public static string ReadHexSubstringFromBinaryFile(FileStream fs, long startOffset, int byteLength) { // 验证偏移和长度的合法性 if (startOffset < 0 || byteLength <= 0 || startOffset >= fs.Length) { return string.Empty; } // 处理超出文件末尾的情况 int actualLength = (int)Math.Min(byteLength, fs.Length - startOffset); // 定位到起始偏移 fs.Seek(startOffset, SeekOrigin.Begin); byte[] buffer = new byte[actualLength]; int bytesRead = fs.Read(buffer, 0, actualLength); // 将字节数组转成十六进制字符串 return BitConverter.ToString(buffer).Replace("-", string.Empty); } // 可选:读取指定位置的字节并转换为指定编码的文本字符串 public static string ReadTextSubstringFromBinaryFile(FileStream fs, long startOffset, int byteLength, Encoding encoding) { if (startOffset < 0 || byteLength <= 0 || startOffset >= fs.Length) { return string.Empty; } int actualLength = (int)Math.Min(byteLength, fs.Length - startOffset); fs.Seek(startOffset, SeekOrigin.Begin); byte[] buffer = new byte[actualLength]; fs.Read(buffer, 0, actualLength); return encoding.GetString(buffer); }
代码说明
ReadHexSubstringFromBinaryFile函数:这是核心函数,接收文件流、起始偏移和要读取的字节长度,返回对应的十六进制字符串。它会自动处理文件边界,避免读取超出文件范围的内容。- 边界处理:当指定的起始偏移超出文件长度,或者要读取的长度超过剩余字节数时,会返回空字符串或者截断后的内容。
- 文本转换选项:如果你的二进制文件中包含的是文本内容,可以使用
ReadTextSubstringFromBinaryFile函数,指定对应的编码(比如UTF8、ASCII等)来转换成普通字符串。
测试你的示例数据
用你提供的十六进制示例数据,当匹配到400000002532后,调用ReadHexSubstringFromBinaryFile读取32字节,会返回后续的010953667A51E44BE5B6A59417B71F4B91BBE590B6AF6E84EF57(对应32字节的十六进制串),和你提供的示例内容一致。
内容的提问来源于stack exchange,提问作者Aman Ali
相关产品推荐
相关产品推荐

