L'éditeur PHP Zimo est là pour répondre à une question courante : "Quel est le moyen le plus efficace de lire des fichiers d'octets dans des tranches int64 ?" Lorsque nous avons besoin de lire des fichiers d'octets dans des tranches int64, nous pouvons utiliser l'approche suivante : Tout d'abord, utilisez la fonction file_get_contents pour lire le fichier d'octets, puis utilisez la fonction unpack pour décompresser le fichier d'octets en tranches int64. Cette méthode est simple et efficace, et peut rapidement convertir des fichiers d'octets en tranches int64 pour répondre à nos besoins. J'espère que cette méthode pourra aider tout le monde !
J'ai plusieurs fichiers int64 compressés. J'en ai besoin en mémoire sous forme de tranches int64. Le problème est que les fichiers combinés dépassent la moitié de la taille de la mémoire de la machine, l'espace est donc limité. Les options standard en go ressemblent à :
a := make([]int64, f.Size()/8) binary.Read(f, binary.LittleEndian, a)
Malheureusement, binary
包将立即分配一个大小为 f.size()*8
的 []byte
, et manque de mémoire.
Cela fonctionne si je lis chaque octet un par un et que je le copie dans la tranche, mais c'est trop lent.
La situation idéale serait d'utiliser []byte
直接转换为 []int64
et de dire simplement au compilateur "ok, ce sont des entiers maintenant", mais évidemment cela ne fonctionne pas. Existe-t-il un moyen de réaliser quelque chose de similaire ? Peut-être utiliser un package dangereux ou le mettre en c lorsque cela est absolument nécessaire ?
J'ai plusieurs fichiers int64 compressés. J'en ai besoin en mémoire sous forme de tranches int64. Le problème est que les fichiers combinés dépassent la moitié de la taille de la mémoire de la machine, l'espace est donc limité.
Les options standard de Go ressemblent à :
a := make([]int64, f.size()/8) binary.read(f, binary.littleendian, a)
Malheureusement, le package binaire allouera immédiatement un []octet de taille f.size()*8 et manquera de mémoire.
Toutes les fonctions utilisent un minimum de mémoire.
// 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 }
Par exemple, pour une architecture amd64 (littleendian) et une efficacité maximale avec les données littleendian (aucune conversion de données requise), utilisez readfileint64se
.
Erreur d'ordre des octets - 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 }
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!