Golang中是否可以实现ByteArrayInString编码?

Golang中是否可以实现ByteArrayInString编码? 我正在尝试将一个名为 ByteArrayInString 的替代 Base64 编码移植到 Go 语言中。

我已经找到了 Java 版本和原始的 C# 代码,将逻辑转换为 Go 是相当容易的。

我遇到的问题是编写一个等效的 单元测试

问题似乎在于将 []byte 转换为 string 时,它没有将每个字节渲染为一个字符,而是试图将它们转换为 Unicode,从而跳过了编码的字符。

这个练习的全部目的是获得一个仅包含 ASCII 的字符串。如果必须将每个 byte 转换为多字节的 rune 来组成 string,那就有点偏离初衷了。

我遗漏了什么?

以下是我尝试移植代码的 Gist 链接:ByteArrayInString

以及 测试工具


更多关于Golang中是否可以实现ByteArrayInString编码?的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

(帖子已被作者撤回,除非被标记,否则将在24小时后自动删除)

更多关于Golang中是否可以实现ByteArrayInString编码?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在 Go 中实现 ByteArrayInString 编码的关键在于正确处理 ASCII 字符集。你遇到的问题是将 []byte 直接转换为 string 时,Go 会将其解释为 UTF-8 编码的字节序列,而不是原始的字节值。以下是解决方案和示例代码:

// 编码函数
func EncodeToString(data []byte) string {
    var buf strings.Builder
    buf.Grow(len(data))
    
    for _, b := range data {
        // 将字节转换为对应的 ASCII 字符
        if b >= 32 && b <= 126 && b != '\\' && b != '\'' && b != '"' {
            buf.WriteByte(b)
        } else {
            // 转义非打印字符
            buf.WriteByte('\\')
            buf.WriteByte(hexDigit(b >> 4))
            buf.WriteByte(hexDigit(b & 0x0F))
        }
    }
    return buf.String()
}

func hexDigit(b byte) byte {
    if b < 10 {
        return '0' + b
    }
    return 'A' + (b - 10)
}

// 解码函数
func DecodeString(s string) ([]byte, error) {
    result := make([]byte, 0, len(s))
    
    for i := 0; i < len(s); i++ {
        c := s[i]
        if c == '\\' && i+2 < len(s) {
            // 处理转义序列
            hi := hexValue(s[i+1])
            lo := hexValue(s[i+2])
            if hi < 0 || lo < 0 {
                return nil, fmt.Errorf("invalid hex escape at position %d", i)
            }
            result = append(result, byte(hi<<4|lo))
            i += 2
        } else {
            result = append(result, c)
        }
    }
    return result, nil
}

func hexValue(c byte) int {
    switch {
    case '0' <= c && c <= '9':
        return int(c - '0')
    case 'A' <= c && c <= 'F':
        return int(c - 'A' + 10)
    case 'a' <= c && c <= 'f':
        return int(c - 'a' + 10)
    }
    return -1
}

单元测试示例:

func TestByteArrayInString(t *testing.T) {
    testCases := []struct {
        name     string
        input    []byte
        expected string
    }{
        {
            name:     "ASCII printable",
            input:    []byte("Hello World"),
            expected: "Hello World",
        },
        {
            name:     "With null byte",
            input:    []byte{0, 1, 2, 'A', 'B', 'C'},
            expected: "\\00\\01\\02ABC",
        },
        {
            name:     "Mixed characters",
            input:    []byte("Test\x07\x08\x09"),
            expected: "Test\\07\\08\\09",
        },
    }
    
    for _, tc := range testCases {
        t.Run(tc.name, func(t *testing.T) {
            // 测试编码
            encoded := EncodeToString(tc.input)
            if encoded != tc.expected {
                t.Errorf("EncodeToString() = %q, want %q", encoded, tc.expected)
            }
            
            // 测试解码
            decoded, err := DecodeString(encoded)
            if err != nil {
                t.Errorf("DecodeString() error = %v", err)
            }
            if !bytes.Equal(decoded, tc.input) {
                t.Errorf("DecodeString() = %v, want %v", decoded, tc.input)
            }
        })
    }
}

关键点说明:

  1. Go 的 string 是 UTF-8 编码的,直接转换 []byte 会进行 UTF-8 解释
  2. 需要手动处理每个字节,将可打印 ASCII 字符直接写入,非打印字符使用转义序列
  3. 使用 strings.Builder 高效构建结果字符串
  4. 解码时需要正确处理转义序列 \XX(十六进制表示)

这种实现确保了输出字符串只包含 ASCII 字符,符合 ByteArrayInString 编码的设计目标。

回到顶部