精确计算base64文件大小(含测试文件和源码)

本文深入探讨Base64编码原理,介绍如何将二进制数据转换为文本形式,适用于电子邮件及XML存储等场景。文章详细解释了Base64编码的计算方法,并通过实例演示如何准确计算编码后的文件大小。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


苟且,诗与远方

1.base64简介

Base64这个术语最初是在“MIME内容传输编码规范”中提出的。Base64不是一种加密算法,虽然编码后的字符串看起来有点加密的赶脚。它实际上是一种“二进制到文本”的编码方法,它能够将给定的任意二进制数据转换(映射)为ASCII字符串的形式,以便在只支持文本的环境中也能够顺利地传输二进制数据。例如支持MIME的电子邮件应用,或需要在XML中存储复杂数据时。

2.在线获取文件base64

链接1: 在线获取文件base64.
链接2: 百度AI-base64音频测试文件.
文件信息

项目Value
文件来源百度AI官方
下载地址http://speech-doc.gz.bcebos.com/rest-api-asr/public_audio/16k.wav
文件名16k.wav
文件类型wav格式音频文件
windows下文件大小126 KB (129998 字节)
文件精确大小129998.25字节
base64总长度173332位
base64文件实体部分长度173310位
base64文件尾部还有多少个’=’1个

3. 拆分base64文件

在这里插入图片描述
**看上图,圈出来的data:audio/wav;base64,一共22个字符为文件头,其他文文件实体。**
.
.

4. 精确计算base64文件大小

	/**
	 * @功能  精确计算base64字符串文件大小(单位:B)
	 * @注意  base64字符串(不含data:audio/wav;base64,文件头)
	 */
	public static double base64file_size( String base64String )  {

		 	//1.获取base64字符串长度(不含data:audio/wav;base64,文件头)
			int size0 = base64String.length();

			//2.获取字符串的尾巴的最后10个字符,用于判断尾巴是否有等号,正常生成的base64文件'等号'不会超过4个
			String tail = base64String.substring(size0-10);

			//3.找到等号,把等号也去掉,(等号其实是空的意思,不能算在文件大小里面)
			int equalIndex = tail.indexOf("=");		
			if(equalIndex > 0) {
			  	size0 = size0 - (10 - equalIndex);
	        }

		 	//4.计算后得到的文件流大小,单位为字节
			return size0 -( (double)size0 / 8 ) * 2;
	}
	计算出来的结果为:129998.25字节,windows系统和大多数API129998字节

//* 以上面的测试文件16k.wav为例,其base64实体长度为173310,大小精确计算出来为129998.25字节,
//* 如果是调用百度官方语音识别API接口接收时,接收到的数据大小我们需要传入129998,不然接口会报文件大小错误。

5. 网上其他错误的计算方法


int strLen=173310;
int fileSize=strLen-(strLen/8)*2;

计算出来的结果为:129999字节

// 错误1:没有除去文件尾巴的等于号,' = ' 是为空的占位符,不计算在文件大小里面的。
// 错误2:base64长度除于8得到的是21663.75,int类型把小数去掉了,精度不够了。
.
.
.
.
.

研究不易,源码免费,欢迎各位观众老爷 右上角 留言点赞

.
.
.
.
.

<think>我们被要求批量修改FLM文件中的芯片型号标识。FLM文件是ARM CMSIS格式的Flash编程算法文件,通常用于嵌入式开发中的Flash烧录。根据引用[2]引用[3],FLM文件内部包有芯片型号、Flash地址范围等信息。修改这些信息需要了解FLM文件的结构。 然而,FLM文件实际上是一个特殊的ELF文件(ARM对象文件格式),它包可执行代码数据结构。要修改其中的芯片型号标识,我们通常需要修改文件中的特定字符串(如芯片型号名称)相关的地址信息(如Flash起始地址大小)。 但是,直接修改二进制文件中的字符串有风险,因为字符串长度变化可能导致文件结构破坏。因此,建议使用以下方法: 方法1:使用十六进制编辑器(适用于简单替换且长度不变的情况) 步骤: 1. 用十六进制编辑器(如HxD、010 Editor)打开FLM文件。 2. 搜索原芯片型号字符串(如“STM32F103”),注意字符串可能是以空字符结尾的C字符串。 3. 用新字符串(如“CH32F103”)替换,确保新字符串长度不超过原字符串(若不够则用空字符填充,若超出则可能破坏文件结构)。 4. 保存文件。 方法2:重新编译FLM算法(推荐,但需要源码) 根据引用[1],FLM文件是通过编译Keil工程生成的。如果我们有算法的源代码,则可以修改源码中的芯片型号标识,然后重新编译生成FLM文件。 步骤: 1. 打开生成FLM的Keil工程。 2. 在源代码中,找到定义设备名称的常量(通常在FlashDev.c或类似文件中),例如: ```c struct FlashDevice const FlashDevice = { FLASH_DRV_VERS, // Driver Version "STM32F103 64KB Flash", // Device Name ONCHIP, // Device Type 0x08000000, // Device Start Address 0x10000, // Device Size (64KB) 1024, // Programming Page Size 0, // Reserved, must be 0 0xFF, // Initial Content of Erased Memory 100, // Program Page Timeout 3000, // Erase Sector Timeout 0x00000200, 0x0000FC00, // Sector Size and Address (example) 0x00000400, 0x0000F800, // ... more sectors ... 0x00000080, 0x0000FF80, // ... last sector ... SECTOR_END }; ``` 3. 将"Device Name"字段修改为新的型号标识,如"CH32F103 64KB Flash"。 4. 如果需要修改地址范围(如引用[3]中提到的Address RangeRAM for Algorithm),则修改相应的地址大小。 5. 重新编译工程,生成新的FLM文件。 方法3:使用脚本自动化修改(需要了解FLM文件结构) 我们可以编写一个Python脚本,利用ELF解析库(如pyelftools)来修改FLM文件中的特定字符串。但是,由于FLM文件是二进制文件,且字符串可能位于特定的段(如.rodata段)中,我们需要谨慎操作。 步骤: 1. 安装pyelftools: `pip install pyelftools` 2. 编写脚本,读取FLM文件,找到所有字符串表,然后替换目标字符串(注意长度限制)。 3. 重新计算校验(如果有的话)。 示例脚本(仅作为思路,实际需要根据FLM结构调整): ```python from elftools.elf.elffile import ELFFile from elftools.elf.sections import StringTableSection def replace_in_flm(flm_path, old_str, new_str): if len(old_str) != len(new_str): raise ValueError("字符串长度必须相同") with open(flm_path, 'r+b') as f: # 读取ELF文件 elffile = ELFFile(f) # 遍历所有段 for section in elffile.iter_sections(): if isinstance(section, StringTableSection): # 如果是字符串表 data = section.data() # 在字符串表中查找旧字符串 index = data.find(old_str.encode()) if index != -1: # 定位到该位置,写入新字符串 f.seek(section.header['sh_offset'] + index) f.write(new_str.encode()) print(f"成功替换: {old_str} -> {new_str}") return print("未找到目标字符串") # 示例:替换FLM文件中的芯片型号 replace_in_flm("STM32F103.FLM", "STM32F103", "CH32F103") ``` 注意:此方法要求新旧字符串长度完全一致,否则会破坏字符串表结构。 方法4:使用JLink工具(间接方法) 根据引用[2],JLink可以通过修改JLinkDevices.xml文件来指定不同的FLM文件。因此,我们可以不修改FLM文件本身,而是通过修改JLinkDevices.xml,将原芯片型号指向新的FLM文件。例如: ```xml <Device> <ChipInfo Vendor="WCH" Name="CH32F103C8" Core="Cortex-M3" WorkRAMAddr="0x20000000" WorkRAMSize="0x5000"/> <FlashBankInfo Name="Flash" BaseAddr="0x08000000" MaxSize="0x10000" Loader="Path\To\Your\Modified_Flash.FLM" LoaderType="FLASH_ALGO_TYPE_OPEN"/> </Device> ``` 总结: - 如果有源码,重新编译是最安全、最灵活的方法(方法2)。 - 如果没有源码且修改的字符串长度不变,可以使用十六进制编辑器(方法1)或脚本(方法3)。 - 如果不想修改FLM文件,可以修改JLinkDevices.xml(方法4)来适配新的芯片型号。 请根据实际情况选择合适的方法。 相关问题: 1. 如何验证修改后的FLM文件是否有效? 2. 如何批量修改多个FLM文件中的相同信息? 3. 修改FLM文件中的地址范围需要注意什么?</think>### 批量修改FLM文件中的芯片型号标识方法 根据引用内容,FLM文件是ARM格式的Flash编程算法文件,包芯片型号、地址范围等关键信息。以下是四种批量修改方法,按操作复杂度排序: --- ### 方法1:十六进制编辑器批量替换(快速简单) **适用场景**:仅修改型号字符串且新旧字符长度相同 ```powershell # PowerShell批量处理脚本 $oldChip = "STM32F103" $newChip = "CH32F103" Get-ChildItem -Path ".\*.flm" | ForEach-Object { $bytes = [System.IO.File]::ReadAllBytes($_.FullName) $content = [System.Text.Encoding]::ASCII.GetString($bytes) $newContent = $content.Replace($oldChip, $newChip) [System.IO.File]::WriteAllBytes($_.FullName, [System.Text.Encoding]::ASCII.GetBytes($newContent)) Write-Host "已修改: $($_.Name)" } ``` **注意**: 1. 新旧型号字符串**长度必须相同**(如`STM32F407`→`CH32F407`) 2. 修改后需验证地址范围一致性(引用[3]) --- ### 方法2:Keil工程重编译(最可靠) **步骤**(引用[1]): 1. 创建批处理脚本遍历所有工程 ```bat @echo off for /R %%i in (*.uvprojx) do ( echo 编译工程: %%~nxi UV4.exe "%%i" -b -j0 -t STM32F103 // 修改为你的目标型号 move "Objects\*.FLM" "Output_FLM\" ) ``` 2. 修改工程配置: - 在`C/C++`选项卡添加型号宏定义:`-DCHIP_MODEL=CH32F103` - 在源码中使用宏定义设备名称: ```c struct FlashDevice const FlashDevice = { FLASH_DRV_VERS, STRINGIFY(CHIP_MODEL) " 128KB Flash", // 自动生成型号标识 0x08000000, 0x20000, ... }; ``` --- ### 方法3:Python解析二进制结构(精确修改) ```python import struct import glob def modify_flm_chipname(flm_path, new_name): with open(flm_path, 'r+b') as f: # FLM头结构: [magic:4s][header_size:I][version:I][name_offset:I] header = f.read(16) name_offset = struct.unpack('<I', header[12:16])[0] # 定位型号字符串区域 f.seek(name_offset) old_name = f.read(32).split(b'\x00')[0].decode() # 写入新型号(保持32字节空间) f.seek(name_offset) f.write(new_name.ljust(32, '\x00').encode('ascii')) return old_name # 批量处理 for flm in glob.glob('*.flm'): old = modify_flm_chipname(flm, "CH32F103") print(f"{flm}: {old} -> CH32F103") ``` **优势**:可同步修改地址范围(引用[3]) ```python # 修改Flash地址范围 (示例偏移量0x40) f.seek(0x40) f.write(struct.pack('<II', 0x08000000, 0x20000)) # Start, Size ``` --- ### 方法4:JLink配置文件映射(无需修改文件) 在`JLinkDevices.xml`中添加别名映射(引用[2]): ```xml <Device> <ChipInfo Vendor="WCH" Name="CH32F103" Core="Cortex-M3" /> <FlashBankInfo Name="Flash" BaseAddr="0x08000000" MaxSize="0x20000" Loader="STM32F103.FLM" LoaderType="FLASH_ALGO_TYPE_OPEN"/> <Aliases> <Alias Name="STM32F103"/> <!-- 将STM32型号映射到CH32算法 --> </Aliases> </Device> ``` --- ### 关键验证步骤 1. **地址范围检查**(引用[3]): - 使用J-Flash工具打开FLM文件 - 确认`Start``Size`与目标芯片的Flash地址完全一致 ```mermaid graph LR A[FLM文件] --> B{Address Range} B -->|Start| C[0x08000000] B -->|Size| D[0x20000] C --> E[匹配芯片手册] D --> E ``` 2. **烧录测试**: ```bash JLink.exe -device CH32F103 -if SWD -speed 4000 -autoconnect 1 ``` --- ### 注意事项 1. **长度一致性**:新老型号字符串长度需相同,否则会破坏FLM结构 2. **版本兼容**:修改后需重新测试擦除/编程函数(引用[1]中的NOR FLASH接口) 3. **厂商差异**:ST/CH等厂商的FLM可能包特定校验机制 4. **备份原则**:修改前保留原始FLM副本 > 推荐优先使用方法2(源码重编译),可确保算法完整性。若需修改现成FLM文件,方法3(Python解析)最安全可靠[^1][^2][^3]。 --- ### 相关问题 1. 如何在不破坏FLM文件结构的情况下修改地址范围? 2. 不同厂商的FLM文件头部结构有何差异? 3. 在Keil工程中如何自动化生成多型号FLM文件? 4. JLink的Aliases机制支持哪些类型的设备映射?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

秋后的虫子君

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值