输入输出流

在本章中,我们将探讨输入输出流(IO流)的基本概念。IO流是进行数据传输的基础,广泛应用于文件读写、网络通信等场景。我们将介绍字符流与字节流、缓冲流与非缓冲流、数据流与对象流的区别和用法。

5.1 IO 流的基本概念

IO流是数据在程序与外部设备(如文件、网络)之间传输的通道。根据数据类型和处理方式,IO流可以分为字符流和字节流。

5.1.1 字符流与字节流

字符流:处理文本数据,适用于处理字符、字符串。 字节流:处理二进制数据,适用于处理图片、音频、视频等。

5.1.2 缓冲流与非缓冲流

缓冲流:通过缓冲区减少直接读写次数,提高性能。 非缓冲流:直接进行读写操作,适用于实时性要求高的场景。

5.1.3 数据流与对象流

数据流:处理基本数据类型的数据。 对象流:处理对象序列化和反序列化。

5.2 字符流与字节流

字符流和字节流是最基础的IO流,分别适用于处理文本和二进制数据。

5.2.1 字符流

Go 示例代码

package main

import (
    "bufio"
    "fmt"
    "os"
)

func readFileByLine(filePath string) {
    file, err := os.Open(filePath)
    if err != nil {
        fmt.Println("Error opening file:", err)
        return
    }
    defer file.Close()

    scanner := bufio.NewScanner(file)
    for scanner.Scan() {
        fmt.Println(scanner.Text())
    }

    if err := scanner.Err(); err != nil {
        fmt.Println("Error reading file:", err)
    }
}

func writeFileByLine(filePath, content string) {
    file, err := os.Create(filePath)
    if err != nil {
        fmt.Println("Error creating file:", err)
        return
    }
    defer file.Close()

    writer := bufio.NewWriter(file)
    _, err = writer.WriteString(content)
    if err != nil {
        fmt.Println("Error writing to file:", err)
        return
    }

    writer.Flush()
}

func main() {
    writeFileByLine("example.txt", "Hello, World!\nThis is a test.")
    readFileByLine("example.txt")
}
5.2.2 字节流

Go 示例代码

package main

import (
    "fmt"
    "io"
    "os"
)

func readBinaryFile(filePath string) {
    file, err := os.Open(filePath)
    if err != nil {
        fmt.Println("Error opening file:", err)
        return
    }
    defer file.Close()

    buffer := make([]byte, 1024)
    for {
        bytesRead, err := file.Read(buffer)
        if err != nil && err != io.EOF {
            fmt.Println("Error reading file:", err)
            return
        }
        if bytesRead == 0 {
            break
        }
        fmt.Printf("Read %d bytes: %v\n", bytesRead, buffer[:bytesRead])
    }
}

func writeBinaryFile(filePath string, data []byte) {
    file, err := os.Create(filePath)
    if err != nil {
        fmt.Println("Error creating file:", err)
        return
    }
    defer file.Close()

    _, err = file.Write(data)
    if err != nil {
        fmt.Println("Error writing to file:", err)
        return
    }
}

func main() {
    data := []byte{0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x2C, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x21}
    writeBinaryFile("example.bin", data)
    readBinaryFile("example.bin")
}

5.3 缓冲流与非缓冲流

缓冲流通过使用缓冲区来减少读写次数,提高IO操作的性能。

5.3.1 缓冲流

Go 示例代码

package main

import (
    "bufio"
    "fmt"
    "os"
)

func bufferedWrite(filePath string, content string) {
    file, err := os.Create(filePath)
    if err != nil {
        fmt.Println("Error creating file:", err)
        return
    }
    defer file.Close()

    writer := bufio.NewWriter(file)
    _, err = writer.WriteString(content)
    if err != nil {
        fmt.Println("Error writing to file:", err)
        return
    }
    writer.Flush()
}

func bufferedRead(filePath string) {
    file, err := os.Open(filePath)
    if err != nil {
        fmt.Println("Error opening file:", err)
        return
    }
    defer file.Close()

    reader := bufio.NewReader(file)
    for {
        line, err := reader.ReadString('\n')
        if err != nil {
            if err != io.EOF {
                fmt.Println("Error reading file:", err)
            }
            break
        }
        fmt.Print(line)
    }
}

func main() {
    bufferedWrite("example.txt", "Hello, buffered world!\nThis is a test.")
    bufferedRead("example.txt")
}
5.3.2 非缓冲流

Go 示例代码

package main

import (
    "fmt"
    "io"
    "os"
)

func nonBufferedWrite(filePath string, content string) {
    file, err := os.Create(filePath)
    if err != nil {
        fmt.Println("Error creating file:", err)
        return
    }
    defer file.Close()

    _, err = file.Write([]byte(content))
    if err != nil {
        fmt.Println("Error writing to file:", err)
        return
    }
}

func nonBufferedRead(filePath string) {
    file, err := os.Open(filePath)
    if err != nil {
        fmt.Println("Error opening file:", err)
        return
    }
    defer file.Close()

    buffer := make([]byte, 1024)
    for {
        bytesRead, err := file.Read(buffer)
        if err != nil && err != io.EOF {
            fmt.Println("Error reading file:", err)
            return
        }
        if bytesRead == 0 {
            break
        }
        fmt.Print(string(buffer[:bytesRead]))
    }
}

func main() {
    nonBufferedWrite("example.txt", "Hello, non-buffered world!\nThis is a test.")
    nonBufferedRead("example.txt")
}

5.4 数据流与对象流

数据流处理基本数据类型的数据,而对象流处理对象的序列化和反序列化。

5.4.1 数据流

Go 示例代码

package main

import (
    "encoding/binary"
    "fmt"
    "os"
)

func writeData(filePath string, data []int32) {
    file, err := os.Create(filePath)
    if err != nil {
        fmt.Println("Error creating file:", err)
        return
    }
    defer file.Close()

    for _, value := range data {
        err := binary.Write(file, binary.LittleEndian, value)
        if err != nil {
            fmt.Println("Error writing data:", err)
            return
        }
    }
}

func readData(filePath string) {
    file, err := os.Open(filePath)
    if err != nil {
        fmt.Println("Error opening file:", err)
        return
    }
    defer file.Close()

    var value int32
    for {
        err := binary.Read(file, binary.LittleEndian, &value)
        if err != nil {
            if err != io.EOF {
                fmt.Println("Error reading data:", err)
            }
            break
        }
        fmt.Println("Read value:", value)
    }
}

func main() {
    data := []int32{1, 2, 3, 4, 5}
    writeData("data.bin", data)
    readData("data.bin")
}
5.4.2 对象流

Go 中没有直接的对象流支持,但我们可以通过编码和解码来实现对象的序列化和反序列化。

Go 示例代码

package main

import (
    "encoding/gob"
    "fmt"
    "os"
)

type Person struct {
    Name string
    Age  int
}

func writeObject(filePath string, obj interface{}) {
    file, err := os.Create(filePath)
    if err != nil {
        fmt.Println("Error creating file:", err)
        return
    }
    defer file.Close()

    encoder := gob.NewEncoder(file)
    err = encoder.Encode(obj)
    if err != nil {
        fmt.Println("Error encoding object:", err)
    }
}

func readObject(filePath string, obj interface{}) {
    file, err := os.Open(filePath)
    if err != nil {
        fmt.Println("Error opening file:", err)
        return


    }
    defer file.Close()

    decoder := gob.NewDecoder(file)
    err = decoder.Decode(obj)
    if err != nil {
        fmt.Println("Error decoding object:", err)
    }
}

func main() {
    person := Person{Name: "Alice", Age: 30}
    writeObject("person.gob", person)

    var readPerson Person
    readObject("person.gob", &readPerson)
    fmt.Printf("Read object: %+v\n", readPerson)
}

通过学习本章内容,读者将能够掌握IO流的基本概念和应用,理解字符流、字节流、缓冲流、非缓冲流、数据流和对象流的区别和用法,从而在实际开发中灵活应用这些知识。