0

0

Go语言实现文件分块:避免末尾填充的正确姿势

DDD

DDD

发布时间:2025-11-09 23:03:06

|

305人浏览过

|

来源于php中文网

原创

Go语言实现文件分块:避免末尾填充的正确姿势

本文详细介绍了在go语言中实现二进制文件分块的正确方法,特别关注如何避免在文件末尾出现不必要的填充。通过分析`os.file.read`方法的特性,我们展示了如何利用实际读取的字节数对切片进行重新切片(re-slice),从而确保每个数据块,特别是最后一个不完整的数据块,都精确地匹配其内容大小,提高内存效率和数据处理的准确性。

在Go语言中处理大文件时,将其分割成固定大小的数据块(chunk)是一种常见的策略,尤其适用于文件上传、下载、分布式存储或并行处理等场景。这种“文件分块”技术要求我们能精确地从文件中读取指定大小的数据片段。然而,在实现过程中,一个常见的挑战是如何妥善处理文件末尾可能存在的不足一个完整块大小的“剩余部分”,避免产生不必要的内存填充。

文件分块基础实现

首先,我们定义一些基本的数据结构和辅助函数来管理文件块。fileChunk 类型表示一个文件数据块,fileChunks 则是文件块的集合。NumChunks 函数用于计算给定文件需要分成多少个数据块。

package main

import (
    "fmt"
    "io"
    "os"
)

// fileChunk 表示一个文件数据块,本质是字节切片
type fileChunk []byte

// fileChunks 是文件块的集合
type fileChunks []fileChunk

// NumChunks 计算文件需要分成多少个数据块
// fi: 文件信息
// chunkSize: 每个数据块的预期大小
func NumChunks(fi os.FileInfo, chunkSize int) int {
    chunks := fi.Size() / int64(chunkSize)
    // 如果有余数,则需要额外一个块来存放剩余部分
    if rem := fi.Size() % int64(chunkSize); rem != 0 {
        chunks++
    }
    return int(chunks)
}

接下来,我们构建一个核心的chunker函数,负责打开文件、计算块数,并循环读取数据。

HTTPie AI
HTTPie AI

AI API开发工具

下载
// chunker 函数将指定文件分割成多个数据块
// filePtr: 指向文件路径的字符串指针
// 返回: 包含所有数据块的 fileChunks 切片和可能的错误
func chunker(filePtr *string) (fileChunks, error) {
    f, err := os.Open(*filePtr)
    if err != nil {
        return nil, fmt.Errorf("无法打开文件: %w", err)
    }
    defer f.Close() // 确保文件在函数结束时关闭

    fi, err := f.Stat()
    if err != nil {
        return nil, fmt.Errorf("无法获取文件信息: %w", err)
    }

    fmt.Printf("文件名称: %s, 大小: %d 字节\n", fi.Name(), fi.Size())

    // 设定每个数据块的大小,例如10000字节
    chunkSize := 10000
    chunks := NumChunks(fi, chunkSize)

    fmt.Printf("文件需要分成 %d 个数据块\n", chunks)

    // 创建一个切片来存储所有文件块,预分配容量以减少append时的内存重新分配
    file_chunks := make(fileChunks, 0, chunks)

    for i := 0; i < chunks; i++ {
        // 为当前块分配一个固定大小的字节切片
        // 这里的b的容量是chunkSize,长度也是chunkSize
        b := make(fileChunk, chunkSize)

        // 从文件中读取数据到切片b
        // n1是实际读取的字节数,err是读取过程中遇到的错误
        n1, err := f.Read(b)
        if err != nil {
            // 如果是文件末尾错误,且没有读取到任何数据,则表示已经处理完所有数据
            if err == io.EOF && n1 == 0 {
                break
            }
            // 其他错误则返回
            return nil, fmt.Errorf("读取文件块失败 (块 %d): %w", i, err)
        }

        fmt.Printf("块 %d: 实际读取 %d 字节\n", i, n1)

        // 关键步骤:根据实际读取的字节数n1对切片b进行重新切片。
        // 这确保了b的长度与实际读取的数据量完全一致,避免了末尾填充。
        b = b[:n1]

        // 将处理好的数据块添加到结果切片中
        file_chunks = append(file_chunks, b)
    }

    fmt.Printf("最终生成了 %d 个数据块\n", len(file_chunks))
    return file_chunks, nil
}

原始实现中存在的问题分析

上述chunker函数在处理文件时,对于大部分数据块都能正常工作。然而,当文件大小不是chunkSize的整数倍时,

立即学习go语言免费学习笔记(深入)”;

相关专题

更多
什么是分布式
什么是分布式

分布式是一种计算和数据处理的方式,将计算任务或数据分散到多个计算机或节点中进行处理。本专题为大家提供分布式相关的文章、下载、课程内容,供大家免费下载体验。

319

2023.08.11

分布式和微服务的区别
分布式和微服务的区别

分布式和微服务的区别在定义和概念、设计思想、粒度和复杂性、服务边界和自治性、技术栈和部署方式等。本专题为大家提供分布式和微服务相关的文章、下载、课程内容,供大家免费下载体验。

228

2023.10.07

treenode的用法
treenode的用法

​在计算机编程领域,TreeNode是一种常见的数据结构,通常用于构建树形结构。在不同的编程语言中,TreeNode可能有不同的实现方式和用法,通常用于表示树的节点信息。更多关于treenode相关问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

529

2023.12.01

C++ 高效算法与数据结构
C++ 高效算法与数据结构

本专题讲解 C++ 中常用算法与数据结构的实现与优化,涵盖排序算法(快速排序、归并排序)、查找算法、图算法、动态规划、贪心算法等,并结合实际案例分析如何选择最优算法来提高程序效率。通过深入理解数据结构(链表、树、堆、哈希表等),帮助开发者提升 在复杂应用中的算法设计与性能优化能力。

6

2025.12.22

Go中Type关键字的用法
Go中Type关键字的用法

Go中Type关键字的用法有定义新的类型别名或者创建新的结构体类型。本专题为大家提供Go相关的文章、下载、课程内容,供大家免费下载体验。

233

2023.09.06

go怎么实现链表
go怎么实现链表

go通过定义一个节点结构体、定义一个链表结构体、定义一些方法来操作链表、实现一个方法来删除链表中的一个节点和实现一个方法来打印链表中的所有节点的方法实现链表。

442

2023.09.25

go语言编程软件有哪些
go语言编程软件有哪些

go语言编程软件有Go编译器、Go开发环境、Go包管理器、Go测试框架、Go文档生成器、Go代码质量工具和Go性能分析工具等。本专题为大家提供go语言相关的文章、下载、课程内容,供大家免费下载体验。

245

2023.10.13

0基础如何学go语言
0基础如何学go语言

0基础学习Go语言需要分阶段进行,从基础知识到实践项目,逐步深入。php中文网给大家带来了go语言相关的教程以及文章,欢迎大家前来学习。

691

2023.10.26

小游戏4399大全
小游戏4399大全

4399小游戏免费秒玩大全来了!无需下载、即点即玩,涵盖动作、冒险、益智、射击、体育、双人等全品类热门小游戏。经典如《黄金矿工》《森林冰火人》《狂扁小朋友》一应俱全,每日更新最新H5游戏,支持电脑与手机跨端畅玩。访问4399小游戏中心,重温童年回忆,畅享轻松娱乐时光!官方入口安全绿色,无插件、无广告干扰,打开即玩,快乐秒达!

30

2025.12.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Go 教程
Go 教程

共32课时 | 3.1万人学习

Go语言实战之 GraphQL
Go语言实战之 GraphQL

共10课时 | 0.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号