📄 file.c
字号:
}
/*********************************************************************************************************
** 函数名称: _FileOpenRW
** 功能描述: 只读写方式打开文件,内部使用
**
** 输 入: DirFileName:用户使用的文件名
**
** 输 出: 文件句柄,Not_Open_FILE为不能打开
**
** 全局变量: 无
** 调用模块: _FileOpenR,_FileOpenW
**
** 作 者: 陈明计
** 日 期: 2003年6月5日
**-------------------------------------------------------------------------------------------------------
** 修改人:
** 日 期:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
HANDLE _FileOpenRW(char *DirFileName)
{
HANDLE Rt;
Rt = _FileOpenR(DirFileName);
if (Rt == Not_Open_FILE)
{
Rt = _FileOpenW(DirFileName);
}
else
{
if (FindOpenFileW(FileInfo[Rt].Drive, FileInfo[Rt].DirClus, FileInfo[Rt].Name) == Not_Open_FILE)
{
FileInfo[Rt].Flags |= (FILE_FLAGS_WRITE | FILE_FLAGS_READ);
}
else
{
FileInfo[Rt].Flags = 0;
Rt = Not_Open_FILE;
}
}
return Rt;
}
/*********************************************************************************************************
** 函数名称: FileOpen
** 功能描述: 以指定方式打开文件
**
** 输 入: DirFileName:用户使用的文件名
** Type:打开方式
** 输 出: 文件句柄,Not_Open_FILE为不能打开
**
** 全局变量: 无
** 调用模块: _FileOpenR,_FileOpenW,_FileOpenRW
**
** 作 者: 陈明计
** 日 期: 2003年6月5日
**-------------------------------------------------------------------------------------------------------
** 修改人:
** 日 期:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
HANDLE FileOpen(char *DirFileName, char *Type)
{
HANDLE Rt;
Rt = Not_Open_FILE;
Type = FsStrCopy(Type);
strupr(Type);
if (Type[0] == 'R')
{
if (Type[1] == 'W')
{
DirFileName = FsStrCopy(DirFileName);
strupr(DirFileName);
Rt = _FileOpenRW(DirFileName);
}
else
{
DirFileName = FsStrCopy(DirFileName);
strupr(DirFileName);
Rt = _FileOpenR(DirFileName);
}
return Rt;
}
if (Type[0] == 'W')
{
if (Type[1] == 'R')
{
DirFileName = FsStrCopy(DirFileName);
strupr(DirFileName);
Rt = _FileOpenRW(DirFileName);
}
else
{
DirFileName = FsStrCopy(DirFileName);
strupr(DirFileName);
Rt = _FileOpenW(DirFileName);
}
}
return Rt;
}
/*********************************************************************************************************
** 函数名称: FileClose
** 功能描述: 关闭指定文件
**
** 输 入: Handle:文件句柄
**
** 输 出: RETURN_OK:成功
** 其它参考fat.h中关于返回值的说明
** 全局变量: 无
** 调用模块: 无
**
** 作 者: 陈明计
** 日 期: 2003年6月5日
**-------------------------------------------------------------------------------------------------------
** 修改人: 严寒亮
** 日 期: 2004年11月5日
** 说 明: 增加文件的最后访问时间属性和最后修改时间属性
**------------------------------------------------------------------------------------------------------
** 流 程: 判断文件是否有写状态-Y->取出该文件FDT项-->判断文件大小是否变化-Y->更新FDT中首簇号-->保存FDT项
** 注 意: 关闭文件后,将释放其登记项,并把修改过的扇区回写保存,但其仍占用原来的cache。
********************************************************************************************************/
uint8 FileClose(HANDLE Handle)
{
uint8 Rt;
FDT FileFDT;
MY_FILE *fp;
SYS_TIME CurTime;
Rt = PARAMETER_ERR;
if (Handle < MAX_OPEN_FILES)
{
if(FS_GetDateTime(&CurTime) != RETURN_OK) // 获取当前时间
{
return GET_TIME_ERR;
}
fp = FileInfo + Handle; // 获取该文件的FDT项
Rt = FindFDTInfo(&FileFDT, fp->Drive, fp->DirClus, fp->Name);
if (Rt != RETURN_OK)
{
return Rt;
}
FileFDT.LstAccDate = CurTime.date; // 更新文件最后访问时间
// 如果文件不是以只写方式打开就不需要保存
if ((fp->Flags & FILE_FLAGS_WRITE) == FILE_FLAGS_WRITE)
{
if (FileFDT.FileSize < fp->FileSize) // 查看文件大小是否发生变化
{
FileFDT.FileSize = fp->FileSize;
// 更新文件最后修改时间
FileFDT.WrtTime = CurTime.time + 1; // 修改时间需要加2秒,因为它不能计算到毫秒戳
FileFDT.WrtDate = CurTime.date;
if (FileFDT.FstClusLO == 0)
if (FileFDT.FstClusHI == 0)
{
FileFDT.FstClusLO = fp->FstClus & 0xffff;
FileFDT.FstClusHI = (fp->FstClus >> 16) & 0xffff;
}
}
}
ChangeFDT(fp->Drive, fp->DirClus, &FileFDT); // 将修改后的FDT项保存
fp->Flags = 0;
}
return Rt;
}
/*********************************************************************************************************
** 函数名称: FileGetCh
** 功能描述: 从文件读一个字节
**
** 输 入: Ch:返回读到的数据
** Handle:文件句柄
** 输 出: RETURN_OK:成功
** 其它参考fat.h中关于返回值的说明
** 全局变量: 无
** 调用模块: 无
**
** 作 者: 陈明计
** 日 期: 2003年6月5日
**-------------------------------------------------------------------------------------------------------
** 修改人: 陈明计
** 日 期: 2004年4月10日
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
uint8 FileGetCh(uint8 *Ch, HANDLE Handle)
{
uint32 i, j, SecIndex;
MY_FILE *fp;
Disk_Info * DiskInfo;
uint8 Rt;
uint8 *Buf;
Rt = PARAMETER_ERR;
fp = FileInfo + Handle;
if (Handle < MAX_OPEN_FILES) /* Handle是否有效 */
if (fp->Flags != 0) /* 对应的打开文件信息表是否已使用 */
{
Rt = FILE_EOF;
if (fp->Offset >= fp->FileSize)
{
/* 如果读数据超出文件的长度,看一看谁否有别的程序正在写这个文件 */
/* 如果有,则可能文件的长度有变化,更正之*/
Handle = FindOpenFileW(fp->Drive, fp->DirClus, fp->Name);
if (Handle < MAX_OPEN_FILES)
{
fp->FileSize = FileInfo[Handle].FileSize;
if (fp->Offset == 0)
{
fp->FstClus = FileInfo[Handle].FstClus;
fp->Clus = fp->FstClus;
}
}
}
Rt = FILE_EOF;
if (fp->Offset < fp->FileSize) /* 是否到文件结束 */
{
Rt = NOT_FIND_DISK;
/* 获取文件所在逻辑盘信息 */
DiskInfo = GetDiskInfo(fp->Drive);
if (DiskInfo != NULL)
{
/* 计算数据所在扇区 */
j = fp->Offset % (DiskInfo->SecPerClus * DiskInfo->BytsPerSec);
i = j / DiskInfo->BytsPerSec;
j = j % DiskInfo->BytsPerSec;
SecIndex = (fp->Clus - 2) * DiskInfo->SecPerClus +
DiskInfo->DataStartSec + i;
Rt = SECTOR_READ_ERR;
/* 打开扇区 */
Buf = OpenSec(fp->Drive, SecIndex);
if (Buf != NULL)
{
/* 读取扇区数据 */
if (ReadSec(fp->Drive, SecIndex) == RETURN_OK)
{
/* 读取数据 */
*Ch = Buf[j];
/* 调整文件指针 */
fp->Offset++;
j++;
if (j >= DiskInfo->BytsPerSec)
{
i++;
if (i >= DiskInfo->SecPerClus)
{
fp->Clus = FATGetNextClus(fp->Drive, fp->Clus);
}
}
Rt = RETURN_OK;
}
/* 关闭扇区 */
CloseSec(fp->Drive, SecIndex);
}
}
}
}
return Rt;
}
/*********************************************************************************************************
** 函数名称: FileRead
** 功能描述: 读取文件
**
** 输 入: Buf:保存读回的数据
** Size:要读的字节数
** Handle:文件句柄
** 输 出: 实际读到的字节数
**
** 全局变量: 无
** 调用模块: 无
**
** 作 者: 陈明计
** 日 期: 2003年6月5日
**-------------------------------------------------------------------------------------------------------
** 修改人:
** 日 期:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
uint32 FileRead(void *Buf, uint32 Size, HANDLE Handle)
{
uint32 i, j, k, SecIndex;
MY_FILE *fp;
Disk_Info * DiskInfo;
uint32 Rt;
uint8 *Buf1, *Buf2;
Rt = 0;
fp = FileInfo + Handle;
Buf2 = (uint8 *)Buf;
if (Handle < MAX_OPEN_FILES) /* Handle是否有效 */
if (fp->Flags != 0) /* 对应的打开文件信息表是否已使用 */
{
if (fp->Offset + Size >= fp->FileSize)
{
/* 如果读数据超出文件的长度,看一看谁否有别的程序正在写这个文件 */
/* 如果有,则可能文件的长度有变化,更正之*/
Handle = FindOpenFileW(fp->Drive, fp->DirClus, fp->Name);
if (Handle < MAX_OPEN_FILES)
{
fp->FileSize = FileInfo[Handle].FileSize;
if (fp->Offset == 0)
{
fp->FstClus = FileInfo[Handle].FstClus;
fp->Clus = fp->FstClus;
}
}
}
while (Size != 0)
{
if (fp->Offset >= fp->FileSize) /* 是否到文件结束 */
{
break;
}
/* 获取文件所在逻辑盘信息 */
DiskInfo = GetDiskInfo(fp->Drive);
if (DiskInfo == NULL)
{
break;
}
/* 计算数据所在扇区 */
j = fp->Offset % (DiskInfo->SecPerClus * DiskInfo->BytsPerSec);
i = j / DiskInfo->BytsPerSec;
j = j % DiskInfo->BytsPerSec;
SecIndex = (fp->Clus - 2) * DiskInfo->SecPerClus +
DiskInfo->DataStartSec + i;
/* 打开扇区 */
Buf1 = OpenSec(fp->Drive, SecIndex);
if (Buf1 == NULL)
{
break;
}
/* 读取扇区数据 */
if (ReadSec(fp->Drive, SecIndex) != RETURN_OK)
{
break;
}
/* 读取数据 */
k = DiskInfo->BytsPerSec - j;
if (Size < k)
{
k = Size;
}
if ((fp->Offset + k) > fp->FileSize)
{
k = fp->FileSize - fp->Offset;
}
Size -= k;
Rt += k;
fp->Offset += k;
memcpy(Buf2, Buf1 + j, k);
Buf2 += k;
/* 关闭扇区 */
CloseSec(fp->Drive, SecIndex);
j += k;
if (j >= DiskInfo->BytsPerSec)
{
i++;
if (i >= DiskInfo->SecPerClus)
{
fp->Clus = FATGetNextClus(fp->Drive, fp->Clus);
}
}
}
}
return Rt;
}
/*********************************************************************************************************
** 函数名称: FilePutCh
** 功能描述: 写一个字节到文件
**
** 输 入: Ch:要写的数据
** Handle:文件句柄
** 输 出: RETURN_OK:成功
** 其它参考fat.h中关于返回值的说明
** 全局变量: 无
** 调用模块: 无
**
** 作 者: 陈明计
** 日 期: 2003年6月5日
**-------------------------------------------------------------------------------------------------------
** 修改人: 陈明计
** 日 期: 2004年4月10日
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
uint8 FilePutCh(uint8 Ch, HANDLE Handle)
{
uint32 i, j, SecIndex;
MY_FILE *fp;
Disk_Info * DiskInfo;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -