你好,周工的这段代码我修改过,我是要写大量数据的时候直接写扇区,不通过cache。不当之处有很多,还请各位老鸟指点。<br />下面贴出我修改后的函数,我用过写数据应该没问题。<br />/*********************************************************************************************************<br />** 函数名称: FileWrite<br />** 功能描述: 写文件<br />**<br />** 输 入: Buf:要写的数据<br />** Size:要写的字节数<br />** Handle:文件句柄<br />** 输 出: 实际写的字节数<br />** <br />** 全局变量: 无<br />** 调用模块: 无<br />**<br />** 作 者: 陈明计<br />** 日 期: 2003年6月5日<br />**-------------------------------------------------------------------------------------------------------<br />** 修改人: tedden<br />** 日 期: 2007年10月13日<br />**<br />** 修改说明: 以循环写字节的方式写文件速度很慢,尤其在写大量数据的时候该方案效率很低。<br />** 修改后采用直接写扇区的方式直接操作逻辑盘,以加快数据传输速度。<br />** <br />**------------------------------------------------------------------------------------------------------<br />********************************************************************************************************/<br /> uint32 FileWrite(void *Buf, uint32 Size, HANDLE Handle)<br />{<br /><br />/********************************************************************************************************<br />************************************ removed by HMF *****************************************************<br />************************************ remove start *****************************************************<br /> uint8 *temp;<br /> uint32 i;<br /> <br /> temp = (uint8 *)Buf;<br /> for (i = 0; i < Size; i++)<br /> {<br /> if (FilePutCh(*temp, Handle) != RETURN_OK)<br /> {<br /> break;<br /> }<br /> temp++;<br /> }<br /> return i;<br />************************************ remove end ****************************************************/<br /><br />/*********************************************************************************************************<br />************************************ Added by tedden ********************************************************<br />************************************ add start *******************************************************/<br />unsigned int i, j, SecIndex,buf_point,Offset_temp,new_clus;<br />//unsigned short NextClusSecIndex, NextClusByteIndex;<br />Disk_RW_Parameter Pa;<br />MY_FILE * fp;<br />Disk_Info * DiskInfo;<br />unsigned char Rt; <br />unsigned char * temp;<br /><br /> temp = (unsigned char *)Buf; <br /> Rt = PARAMETER_ERR;<br /> fp = FileInfo + Handle; /* 获取打开文件列表描述符 */<br /> if (Handle >= 0 && Handle < MAX_OPEN_FILES) /* Handle是否有效 */<br /> <br /> if (((fp->Flags) & FILE_FLAGS_WRITE) != 0) /* 对应的打开文件信息表是否已使用,条件成立文件可写 */<br /> {<br /> Rt = FILE_EOF;<br /> if (fp->Offset <= fp->FileSize) /* 文件指针指在文件内部 */<br /> {<br /> Rt = NOT_FIND_DISK;<br /> <br /> DiskInfo = GetDiskInfo(fp->Drive); /* 获取文件所在逻辑盘信息 */<br /> <br /> if (DiskInfo != NULL) /* 逻辑盘存在 */ <br /> {<br /> <br /> /* 调整文件指针 */<br /> j = (fp->Offset) % (DiskInfo->SecPerClus * DiskInfo->BytsPerSec); <br /> /* 偏移量j=描述符内偏移量%(每簇扇区数×每扇区字节数) */<br /> if (j == 0) /* 余数为0,说明偏移在簇的末尾 */ <br /> <br /> {<br /> if (fp->Offset < fp->FileSize) /* 偏移在文件内 */<br /> {<br /> fp->Clus = FATGetNextClus(fp->Drive, fp->Clus); /* 获取下一个簇 */<br /> }<br /> else /* 偏移在文件尾,这个时候要添加一个新簇 */<br /> {<br /> i = FATAddClus(fp->Drive, fp->Clus); /* 申请添加新的簇 */<br /> if (i >= BAD_CLUS) /* 磁盘空间满,申请失败 */<br /> {<br /> return DISK_FULL;<br /> }<br /> fp->Clus = i; /* 修改文件描述符的簇指针 */<br /> if (fp->FstClus == EMPTY_CLUS) /* 如果是新建的文件,初始化文件的起始簇 */ <br /> {<br /> fp->FstClus = i;<br /> }<br /> }<br /> }<br /> <br /> /* 计算数据所在扇区,j在前面已经和簇取余 */<br /> i = j / DiskInfo->BytsPerSec; /* 数据所在的扇区 */<br /> j = j % DiskInfo->BytsPerSec; /* 数据在扇区的字节序号 */<br /> SecIndex = (fp->Clus - 2) * DiskInfo->SecPerClus + DiskInfo->DataStartSec + i;<br /> <br /> Rt = SECTOR_READ_ERR;<br /> buf_point = 0; /* 要写入数据的指针初始化 */<br /> <br /> /* 从下面开始调用底层驱动读写数据 */<br /> /* 初始化好底层驱动使用的结构体 */<br /> Pa.Drive = fp->Drive;<br /> Pa.SectorIndex = SecIndex;<br /> Pa.RsvdForLow = DiskInfo->RsvdForLow;<br /> Pa.Buf = CacheBuf;<br /> <br /> if (DiskInfo->DiakCommand != NULL)<br /> {<br /> while(1) /* 等待直到所有的数据写完 */<br /> {<br /><br /> if (DiskInfo->DiakCommand(DISK_READ_SECTOR, &Pa) != DISK_READ_OK) /* 扇区读取失败,直接返回 */<br /> {<br /> return Rt;<br /> }<br /> Offset_temp = fp->Offset; /* 记录偏移 */<br /> /* 读取成功,下面开始修改缓冲区的数据 */<br /> while(j < DISK_CACHE_SIZE ) /* 从j开始修改扇区数据 */<br /> {<br /> fp->Offset++ ; /* 修该偏移指针 */<br /> CacheBuf[j] = *temp;<br /> temp++;<br /> j++; <br /> buf_point++ ;<br /> if( buf_point == Size) /* 所有数据都已写入,跳出循环 */<br /> break;<br /> }<br /> /* 修改完成,将修改好的数据写回 */<br /> if (DiskInfo->DiakCommand(DISK_WRITE_SECTOR, &Pa) != DISK_WRITE_OK) /* 扇区写入失败,直接返回 */<br /> {<br /> fp->Offset = Offset_temp; /* 写入失败,写回偏移 */<br /> return Rt;<br /> }<br /> if (fp->Offset > fp->FileSize)<br /> {<br /> fp->FileSize = fp->Offset; /* 修改文件大小 */<br /> }<br /> j = 0; /* 缓冲指针归0 */<br /> <br /> /* 判断是否写完 */<br /> if( buf_point == Size) /* 已经写完 */<br /> {<br /> Rt = RETURN_OK;<br /> break;<br /> }<br /> else /* 没有写完,判断是否需要申请新的簇 */<br /> {<br /> if(fp->Offset < fp->FileSize) /* 偏移还没有到文件尾 */<br /> {<br /> if((fp->Offset) % (DiskInfo->SecPerClus * DiskInfo->BytsPerSec) != 0) /* 当前簇还没有写完 */<br /> {<br /> i++;<br /> SecIndex++;<br /> Pa.SectorIndex = SecIndex; /* 修改索引 */<br /> }<br /> else /* 当前簇已经写满 */<br /> {<br /> fp->Clus = FATGetNextClus(fp->Drive, fp->Clus); /* 获取下一个簇 */<br /> i = 0; /* 第一个扇区 */<br /> SecIndex = (fp->Clus - 2) * DiskInfo->SecPerClus + DiskInfo->DataStartSec + i; /* 重新计算索引 */<br /> Pa.SectorIndex = SecIndex; /* 修改结构体参数 */<br /> }<br /> }<br /> else /* 偏移到达文件尾 */<br /> {<br /> if((fp->Offset) % (DiskInfo->SecPerClus * DiskInfo->BytsPerSec) != 0) /* 当前簇还没有写完 */<br /> {<br /> i++;<br /> SecIndex++;<br /> Pa.SectorIndex = SecIndex; /* 修改索引 */<br /> }<br /> else /* 当前簇已经写满,要申请新的簇 */<br /> {<br /> new_clus = FATAddClus(fp->Drive, fp->Clus);<br /> if(new_clus >= BAD_CLUS) /* 获取新簇失败 */<br /> {<br /> Rt = DISK_FULL;<br /> return Rt;<br /> }<br /> fp->Clus = new_clus;<br /> i = 0; /* 第一个扇区 */<br /> SecIndex = (fp->Clus - 2) * DiskInfo->SecPerClus + DiskInfo->DataStartSec + i; /* 重新计算索引 */<br /> Pa.SectorIndex = SecIndex; /* 修改结构体参数 */<br /> }<br /> }<br /> }<br /> }<br /> } <br /> }<br /> }<br /> }<br /> return buf_point;<br /><br />/************************************ add end *******************************************************/<br />}
|