Go语言中替换字节数组CR/LF换行符及还原的实现问题
解决Go语言中二进制数据CR/LF替换与还原问题
问题分析
你需要处理加密压缩后的二进制数据,将其中的\r(0x0D)替换为\u00A0(UTF-8编码为0xC2 0xA0)、\n(0x0A)替换为\u00A1(UTF-8编码为0xC2 0xA1),同时实现反向还原。之前的方案存在两个核心问题:
- 方案一将二进制数据转成
string操作:加密压缩后的二进制数据并非UTF-8编码,转字符串会破坏原始字节,导致strings.Replace无法精准匹配所有换行符。 - 方案二错误处理Unicode字符:
\u00A0和\u00A1是双字节UTF-8字符,直接以单字节byte类型追加会丢失编码信息,替换结果无效。
正确实现代码
替换换行符函数
func replaceLineBreaks(input []byte) []byte { output := make([]byte, 0, len(input)*2) // 预分配足够空间,避免频繁扩容 for _, b := range input { switch b { case '\r': // CR 0x0D output = append(output, 0xC2, 0xA0) // \u00A0的UTF-8编码 case '\n': // LF 0x0A output = append(output, 0xC2, 0xA1) // \u00A1的UTF-8编码 default: output = append(output, b) } } return output }
还原换行符函数
func restoreLineBreaks(input []byte) []byte { output := make([]byte, 0, len(input)) for i := 0; i < len(input); i++ { // 检查是否是\u00A0的UTF-8序列 if i+1 < len(input) && input[i] == 0xC2 && input[i+1] == 0xA0 { output = append(output, '\r') i++ // 跳过下一个字节 } else if i+1 < len(input) && input[i] == 0xC2 && input[i+1] == 0xA1 { // 检查是否是\u00A1的UTF-8序列 output = append(output, '\n') i++ // 跳过下一个字节 } else { output = append(output, input[i]) } } return output }
关键说明
- 直接操作二进制字节:避免将非UTF-8的二进制数据转为
string,确保原始数据的完整性,精准匹配\r和\n字节。 - 正确处理UTF-8编码:
\u00A0和\u00A1是双字节UTF-8字符,替换时直接写入对应的字节序列;还原时检查连续两个字节的组合,避免误替换。 - 预分配内存:替换函数中预分配
len(input)*2的空间,因为每个换行符会被替换为两个字节,减少内存扩容的性能开销。
验证方式
可以通过以下代码验证替换和还原的正确性:
func main() { testData := []byte("hello\r\nworld\rtest\nend") replaced := replaceLineBreaks(testData) fmt.Println("替换后数据(无换行):", string(replaced)) restored := restoreLineBreaks(replaced) fmt.Println("还原后数据:", string(restored)) fmt.Println("还原后与原数据是否一致:", bytes.Equal(testData, restored)) }
内容的提问来源于stack exchange,提问作者hackall360
相关产品推荐
相关产品推荐

