Rumah >pembangunan bahagian belakang >Golang >Apakah cara yang paling berkesan untuk membaca fail bait ke dalam kepingan int64?

Apakah cara yang paling berkesan untuk membaca fail bait ke dalam kepingan int64?

PHPz
PHPzke hadapan
2024-02-09 11:36:09970semak imbas

将字节文件读入 int64 切片的最有效方法是什么?

php小编子墨在这里为大家解答一个常见的问题:“将字节文件读入 int64 切片的最有效方法是什么?”当我们需要将字节文件读入 int64 切片时,可以采用以下方法:首先,使用 file_get_contents 函数读取字节文件,然后使用 unpack 函数将字节文件解包为 int64 切片。这样的方法简单高效,能够快速地将字节文件转换为 int64 切片,满足我们的需求。希望这个方法能够帮助到大家!

问题内容

我有几个打包的 int64 文件。我需要它们在内存中作为 int64 切片。问题是文件加在一起超过了机器内存大小的一半,因此空间有限。 go 中的标准选项类似于:

a := make([]int64, f.Size()/8)
binary.Read(f, binary.LittleEndian, a)

不幸的是,binary 包将立即分配一个大小为 f.size()*8[]byte,并耗尽内存。

如果我一次读取每个字节并将其复制到切片中,它确实可以工作,但这速度太慢了。

理想的情况是将 []byte 直接转换为 []int64,只是告诉编译器“好吧,这些现在是整数”,但显然这是行不通的。有什么方法可以完成类似的东西?可能使用不安全的包或在绝对需要时放入 c 中?

解决方法

我有几个打包的 int64 文件。我需要它们在内存中作为 int64 切片。问题是文件加在一起超过了机器内存大小的一半,因此空间有限。

go 中的标准选项类似于:

a := make([]int64, f.Size()/8)
binary.Read(f, binary.LittleEndian, a)

不幸的是,二进制包将立即分配一个大小为 f.size()*8 的 []byte,并耗尽内存。

所有函数都使用最少的内存。

// same endian architecture and data
// most efficient (no data conversion).
func readfileint64se(filename string) ([]int64, error) {
    b, err := os.readfile(filename)
    if err != nil {
        return nil, err
    }

    const i64size = int(unsafe.sizeof(int64(0)))
    i64ptr := (*int64)(unsafe.pointer(unsafe.slicedata(b)))
    i64len := len(b) / i64size
    i64 := unsafe.slice(i64ptr, i64len)

    return i64, nil
}

例如,为了amd64(littleendian)架构和littleendian数据最大效率(无需数据转换),请使用readfileint64se

字节顺序谬误 - rob pike
https://commandcenter.blogspot.com/2012/04/byte- order-fallacy.html

// littleendian in-place data conversion for any architecture
func readfileint64le(filename string) ([]int64, error) {
    b, err := os.readfile(filename)
    if err != nil {
        return nil, err
    }

    const i64size = int(unsafe.sizeof(int64(0)))
    i64ptr := (*int64)(unsafe.pointer(unsafe.slicedata(b)))
    i64len := len(b) / i64size
    i64 := unsafe.slice(i64ptr, i64len)

    for i, j := i64size, 0; i <= len(b); i, j = i+i64size, j+1 {
        i64[j] = int64(binary.littleendian.uint64(b[i-i64size : i]))
    }

    return i64, nil
}
// BigEndian in-place data conversion for any architecture
func readFileInt64BE(filename string) ([]int64, error) {
    b, err := os.ReadFile(filename)
    if err != nil {
        return nil, err
    }

    const i64Size = int(unsafe.Sizeof(int64(0)))
    i64Ptr := (*int64)(unsafe.Pointer(unsafe.SliceData(b)))
    i64Len := len(b) / i64Size
    i64 := unsafe.Slice(i64Ptr, i64Len)

    for i, j := i64Size, 0; i <= len(b); i, j = i+i64Size, j+1 {
        i64[j] = int64(binary.BigEndian.Uint64(b[i-i64Size : i]))
    }

    return i64, nil
}

Atas ialah kandungan terperinci Apakah cara yang paling berkesan untuk membaca fail bait ke dalam kepingan int64?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:stackoverflow.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam