MST

星途 面试题库

面试题:Go字符串编码转换中如何高效处理大量数据

假设你有一个包含大量UTF - 16编码数据的文件,需要将其转换为UTF - 8编码并输出到另一个文件。在Go语言中,如何设计一个高效的程序来完成这个任务,要考虑内存管理、I/O操作的优化以及可能出现的编码错误处理。
39.1万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试
package main

import (
    "bufio"
    "bytes"
    "encoding/unicode"
    "fmt"
    "io"
    "os"
)

func main() {
    inputFile, err := os.Open("input.txt")
    if err != nil {
        fmt.Println("Failed to open input file:", err)
        return
    }
    defer inputFile.Close()

    outputFile, err := os.Create("output.txt")
    if err != nil {
        fmt.Println("Failed to create output file:", err)
        return
    }
    defer outputFile.Close()

    reader := bufio.NewReader(inputFile)
    writer := bufio.NewWriter(outputFile)

    for {
        data, err := reader.Peek(2)
        if err != nil && err != io.EOF {
            fmt.Println("Error peeking data:", err)
            return
        }
        if len(data) < 2 {
            break
        }
        // 读取UTF - 16编码的一个代码单元
        r := unicode.ReplacementChar
        if data[0]&0xfc == 0xd8 && len(data) >= 4 {
            // 处理代理对
            lead := uint16(data[0])<<8 | uint16(data[1])
            trail := uint16(data[2])<<8 | uint16(data[3])
            if unicode.IsSurrogate(lead) && unicode.IsSurrogate(trail) {
                r = unicode.DecodeRune(lead, trail)
                _, err = reader.Discard(4)
            } else {
                r = unicode.ReplacementChar
                _, err = reader.Discard(2)
            }
        } else {
            r = rune(uint16(data[0])<<8 | uint16(data[1]))
            _, err = reader.Discard(2)
        }
        if err != nil && err != io.EOF {
            fmt.Println("Error discarding data:", err)
            return
        }
        var buf bytes.Buffer
        n, err := buf.WriteRune(r)
        if err != nil {
            fmt.Println("Error writing rune to buffer:", err)
            return
        }
        utf8Data := buf.Bytes()
        _, err = writer.Write(utf8Data[:n])
        if err != nil {
            fmt.Println("Error writing data to output file:", err)
            return
        }
    }

    err = writer.Flush()
    if err != nil {
        fmt.Println("Error flushing writer:", err)
        return
    }
}
  1. 文件打开与关闭
    • 使用os.Open打开输入文件,使用os.Create创建输出文件,并通过defer语句确保文件在函数结束时正确关闭,避免资源泄漏。
  2. 读写器选择
    • 使用bufio.NewReaderbufio.NewWriter分别创建带缓冲区的读取器和写入器,以减少I/O操作次数,提高效率。
  3. UTF - 16解码
    • 每次从输入文件中窥视(Peek)2个字节,因为UTF - 16编码每个代码单元是2个字节。
    • 检查是否为代理对,如果是则读取接下来2个字节并使用unicode.DecodeRune解码。如果不是代理对,直接将2个字节转换为rune
    • 使用reader.Discard丢弃已读取的数据。
  4. UTF - 8编码
    • 使用buf.WriteRune将解码后的rune写入bytes.BufferWriteRune会将rune编码为UTF - 8格式。
    • bytes.Buffer获取UTF - 8编码的数据并写入输出文件。
  5. 错误处理
    • 对文件打开、窥视数据、丢弃数据、写入数据和刷新写入器等操作都进行了错误处理,确保程序在遇到错误时能给出相应提示并安全退出。