首页  >  文章  >  后端开发  >  将字节文件读入 int64 切片的最有效方法是什么?

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

PHPz
PHPz转载
2024-02-09 11:36:09959浏览

将字节文件读入 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
}

以上是将字节文件读入 int64 切片的最有效方法是什么?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文转载于:stackoverflow.com。如有侵权,请联系admin@php.cn删除