Maison > développement back-end > Golang > le corps du texte

Quel est le moyen le plus efficace de lire un fichier d'octets dans une tranche int64 ?

PHPz
Libérer: 2024-02-09 11:36:09
avant
941 Les gens l'ont consulté

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

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 !

Contenu de la question

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)
Copier après la connexion

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 ?

Solution de contournement

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)
Copier après la connexion

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
}
Copier après la connexion

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
}
Copier après la connexion
// 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
}
Copier après la connexion

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!

source:stackoverflow.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!