新聞中心
雖然Go語言的 encoding/gob 包非常易用,而且使用時(shí)所需代碼量也非常少,但是我們?nèi)杂锌赡苄枰獎?chuàng)建自定義的二進(jìn)制格式。自定義的二進(jìn)制格式有可能做到最緊湊的數(shù)據(jù)表示,并且讀寫速度可以非???。

創(chuàng)新互聯(lián)長期為1000+客戶提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊(duì)從業(yè)經(jīng)驗(yàn)10年,關(guān)注不同地域、不同群體,并針對不同對象提供差異化的產(chǎn)品和服務(wù);打造開放共贏平臺,與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為曲麻萊企業(yè)提供專業(yè)的成都網(wǎng)站制作、成都網(wǎng)站建設(shè),曲麻萊網(wǎng)站改版等技術(shù)服務(wù)。擁有十年豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制開發(fā)。
不過,在實(shí)際使用中,我們發(fā)現(xiàn)以Go語言二進(jìn)制格式的讀寫通常比自定義格式要快非常多,而且創(chuàng)建的文件也不會大很多。但如果我們必須通過滿足 gob.GobEncoder 和 gob.GobDecoder 接口來處理一些不可被 gob 編碼的數(shù)據(jù),這些優(yōu)勢就有可能會失去。
在有些情況下我們可能需要與一些使用自定義二進(jìn)制格式的軟件交互,因此了解如何處理二進(jìn)制文件就非常有用。
寫自定義二進(jìn)制文件
Go語言的 encoding/binary 包中的 binary.Write() 函數(shù)使得以二進(jìn)制格式寫數(shù)據(jù)非常簡單,函數(shù)原型如下:
func Write(w io.Writer, order ByteOrder, data interface{}) error
Write 函數(shù)可以將參數(shù) data 的 binary 編碼格式寫入?yún)?shù) w 中,參數(shù) data 必須是定長值、定長值的切片、定長值的指針。參數(shù) order 指定寫入數(shù)據(jù)的字節(jié)序,寫入結(jié)構(gòu)體時(shí),名字中有
_的字段會置為 0。
下面通過一個簡單的示例程序來演示一下 Write 函數(shù)的使用,示例代碼如下:
package main
import (
"bytes"
"encoding/binary"
"fmt"
"os"
)
type Website struct {
Url int32
}
func main() {
file, err := os.Create("output.bin")
for i := 1; i <= 10; i++ {
info := Website{
int32(i),
}
if err != nil {
fmt.Println("文件創(chuàng)建失敗 ", err.Error())
return
}
defer file.Close()
var bin_buf bytes.Buffer
binary.Write(&bin_buf, binary.LittleEndian, info)
b := bin_buf.Bytes()
_, err = file.Write(b)
if err != nil {
fmt.Println("編碼失敗", err.Error())
return
}
}
fmt.Println("編碼成功")
}運(yùn)行上面的程序會在當(dāng)前目錄下生成 output.bin 文件,文件內(nèi)容如下:
0100 0000 0200 0000 0300 0000 0400 0000
0500 0000 0600 0000 0700 0000 0800 0000
0900 0000 0a00 0000
讀自定義二進(jìn)制文件
讀取自定義的二進(jìn)制數(shù)據(jù)與寫自定義二進(jìn)制數(shù)據(jù)一樣簡單。我們無需解析這類數(shù)據(jù),只需使用與寫數(shù)據(jù)時(shí)相同的字節(jié)順序?qū)?shù)據(jù)讀進(jìn)相同類型的值中。
示例代碼如下:
package main
import (
"bytes"
"encoding/binary"
"fmt"
"os"
)
type Website struct {
Url int32
}
func main() {
file, err := os.Open("output.bin")
defer file.Close()
if err != nil {
fmt.Println("文件打開失敗", err.Error())
return
}
m := Website{}
for i := 1; i <= 10; i++ {
data := readNextBytes(file, 4)
buffer := bytes.NewBuffer(data)
err = binary.Read(buffer, binary.LittleEndian, &m)
if err != nil {
fmt.Println("二進(jìn)制文件讀取失敗", err)
return
}
fmt.Println("第", i, "個值為:", m)
}
}
func readNextBytes(file *os.File, number int) []byte {
bytes := make([]byte, number)
_, err := file.Read(bytes)
if err != nil {
fmt.Println("解碼失敗", err)
}
return bytes
}運(yùn)行結(jié)果如下:
go run main.go
第 1 個值為: {1}
第 2 個值為: {2}
第 3 個值為: {3}
第 4 個值為: {4}
第 5 個值為: {5}
第 6 個值為: {6}
第 7 個值為: {7}
第 8 個值為: {8}
第 9 個值為: {9}
第 10 個值為: {10}
至此,我們完成了對自定義二進(jìn)制數(shù)據(jù)的讀和寫操作。只要小心選擇表示長度的整數(shù)符號和大小,并將該長度值寫在變長值(如切片)的內(nèi)容之前,那么使用二進(jìn)制數(shù)據(jù)進(jìn)行工作并不難。
Go語言對二進(jìn)制文件的支持還包括隨機(jī)訪問。這種情況下,我們必須使用 os.OpenFile() 函數(shù)來打開文件(而非 os.Open()),并給它傳入合理的權(quán)限標(biāo)志和模式(例如 os.O_RDWR 表示可讀寫)參數(shù)。
然后,就可以使用 os.File.Seek() 方法來在文件中定位并讀寫,或者使用 os.File.ReadAt() 和 os.File.WriteAt() 方法來從特定的字節(jié)偏移中讀取或者寫入數(shù)據(jù)。
Go語言還提供了其他常用的方法,包括 os.File.Stat() 方法,它返回的 os.FileInfo 包含了文件大小、權(quán)限以及日期時(shí)間等細(xì)節(jié)信息。
分享名稱:創(chuàng)新互聯(lián)GO教程:Go語言自定義二進(jìn)制文件的讀寫操作
分享路徑:http://m.fisionsoft.com.cn/article/copgjgd.html


咨詢
建站咨詢
