MTK优美代码赏析7:文件搜索与匹配
2010-10-10 12:06
429 查看
最近因需要拓展音乐播放器功能,研究了下MTK的文件系统,趁周末我总结一下关于文件系统关键的接口<文件搜索与匹配>MTK实现的方法。
关于文件搜索,因为都是基于FAT格式的系统,所以MTK文件处理的思路和Window是很相似的。
通过FindFirstFile函数获取操作句柄HANDLE,将此句柄作为参数传入FindNextFile函数,通过FindNextFile不断搜索下一个文件/文件夹,当FindNextFile返回值为0时表示搜索完成,查询完成后通过FindClose关闭句柄。
对应MTK中的接口为FS_FindFirst,FS_FindNext和FS_FindClose,下面拿一段代码来看(来自aud_vr_sd.c)
//作者:张素丰,转载请注明出处:http://www.zhangsufeng.cn/?p=237
/*****************************************************************************
* FUNCTION
* aud_vr_sd_scan_tags_in_group_folder
* DESCRIPTION
* vr sd scan all tags in a group folder
* PARAMETERS
* group_id [IN]
* path [?]
* RETURNS
* void
*****************************************************************************/
void aud_vr_sd_scan_tags_in_group_folder(kal_uint16 group_id, kal_uint16 *path)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
kal_uint16 filename[VR_MAX_DB_PATH_LEN + 1];
kal_uint16 filename_expr[VR_MAX_DB_PATH_LEN + 1];
kal_int32 word_id;
FS_HANDLE fd_cursor;
FS_DOSDirEntry file_info;
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
vr_sd_ctx.id_length[group_id] = 0;
kal_wsprintf(filename_expr, "%wMTKVR_????.vrd", path);
if ((fd_cursor = FS_FindFirst(filename_expr, 0, 0, &file_info, filename, (VR_MAX_DB_PATH_LEN + 1) << 1)) >= 0)
{
/* loop through all vrd files in a group folder */
do
{
/* filter out folder results */
if (!(file_info.Attributes & FS_ATTR_DIR))
{
/* parse word id and add to id array and increment id length */
if ((word_id = aud_vr_sd_extract_word_id(filename)) >= 0)
{
vr_sd_ctx.id_array[group_id][vr_sd_ctx.id_length[group_id]++] = word_id;
}
}
} while (FS_FindNext(fd_cursor, &file_info, filename, (VR_MAX_DB_PATH_LEN + 1) << 1) == FS_NO_ERROR);
FS_FindClose(fd_cursor);
}
}
下面讲一讲匹配,这里所说的匹配主要是将文件格式(即后缀名)的匹配,在获取到文件名以后进行。
思路也都是相同的,那就是从文件名末端开始搜索到第一个".",然后截取"."后面这一段作为拓展名,然后把这个拓展名拿到自己的需要的格式列表中对比即可。
MTK中有两种方式实现了这个需求,
方式1(来自FileManagerSrc.c):
/*****************************************************************************
* FUNCTION
* mmi_fmgr_get_file_group
* DESCRIPTION
* check file type belongs to which file group
* PARAMETERS
* path [?]
* RETURNS
* void
*****************************************************************************/
U8 mmi_fmgr_get_file_group(S8 *path)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
FMGR_FILTER file_type;
S32 result;
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
result = mmi_fmgr_get_file_type(path, &file_type);
if (result == FS_FILE_NOT_FOUND)
{
return FMGR_GROUP_UNKNOWN;
}
if (FMGR_FILTER_IS_SET_AUDIO(&file_type))
{
return FMGR_GROUP_AUDIO;
}
else if (FMGR_FILTER_IS_SET_IMAGE(&file_type))
{
return FMGR_GROUP_IMAGE;
}
else if (FMGR_FILTER_IS_SET_VIDEO(&file_type))
{
return FMGR_GROUP_VIDEO;
}
else if (FMGR_FILTER_IS_SET_SWFLASH(&file_type))
{
return FMGR_GROUP_SWFLASH;
}
else
{
return FMGR_GROUP_UNKNOWN;
}
}
在mmi_fmgr_get_file_type函数内实现了相应的逻辑,这个流程依赖于FileMgr.c中
const fmgr_filter_struct fmgr_filter[FMGR_MAX_FILTER_COUNT];
方式2: 依赖于系统的全局变量的东西有时并不能满足我们应用的需求,这个时候我们需要自己定义一个私有的fmgr_filter,来实现拓展名的判断。
这个流程的实现可以参照09A代码AudioPlayerPlayList.c中mmi_audply_playlist_generate_search函数。
下面来对比两个获取后缀名的函数:
/*****************************************************************************
* FUNCTION
* mmi_fmgr_extract_ext_file_name
* DESCRIPTION
* get pointer to the extension file name in the file path
* PARAMETERS
* path [?]
* RETURNS
* void
*****************************************************************************/
PS8 mmi_fmgr_extract_ext_file_name(S8 *path)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
S16 i, length;
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
length = (S16) mmi_ucs2strlen(path);
i = length - 1;
while (i >= 0)
{
if (path[i << 1] == '\\' && path[(i << 1) + 1] == 0)
{
return NULL;
}
if (path[i << 1] == '.' && path[(i << 1) + 1] == 0 && (i != length - 1))
{
break;
}
i--;
}
if (i < 0)
{
return NULL;
}
return &path[(i + 1) << 1];
}
另一种系统string处理的接口:
/*****************************************************************************
* FUNCTION
* app_ucs2_strrchr
* DESCRIPTION
* Scan a UCS2 encoded string for the last occurrence of a character.
* PARAMETERS
* string [IN] UCS2 encoded string to search in.
* ch [IN] UCS2 encoded wide-character to search for.
* RETURNS
* returns pointer to the last occurrence of ch in string
* returns NULL if ch does not occur in string
*****************************************************************************/
kal_int8 *app_ucs2_strrchr(const kal_int8 * string, kal_wchar ch)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
kal_int8 *cursor = (kal_int8 *)string;
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
while (*cursor || *(cursor+1)) /* find end of string */
{
cursor += 2;
}
/* search towards front */
while ((kal_int8 *)string != cursor &&
(*(cursor+1)<<8|(kal_uint8)(*cursor)) != ch)
{
cursor -= 2;
}
if ((*(cursor+1)<<8|(kal_uint8)(*cursor)) == ch) /* found ?*/
{
return cursor;
}
return NULL;
}
PS8 test(const UI_string_type ext)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
U8 i = 0;
U32 ext_len = 0;
UI_character_type file_ext[FMGR_MAX_EXT_LEN + 1];
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
/* skip ".". */
{
PS8 dot = (PS8)app_ucs2_strrchr((const PS8)ext, (U16)L'.');
if (dot)
{
dot += 2;
}
else
{
dot = (PS8)ext;
}
mmi_ucs2ncpy((PS8)file_ext, (const PS8)dot, FMGR_MAX_EXT_LEN);
ext_len = mmi_ucs2strlen((const PS8)dot);
return dot;
}
}
关于文件搜索,因为都是基于FAT格式的系统,所以MTK文件处理的思路和Window是很相似的。
通过FindFirstFile函数获取操作句柄HANDLE,将此句柄作为参数传入FindNextFile函数,通过FindNextFile不断搜索下一个文件/文件夹,当FindNextFile返回值为0时表示搜索完成,查询完成后通过FindClose关闭句柄。
对应MTK中的接口为FS_FindFirst,FS_FindNext和FS_FindClose,下面拿一段代码来看(来自aud_vr_sd.c)
//作者:张素丰,转载请注明出处:http://www.zhangsufeng.cn/?p=237
/*****************************************************************************
* FUNCTION
* aud_vr_sd_scan_tags_in_group_folder
* DESCRIPTION
* vr sd scan all tags in a group folder
* PARAMETERS
* group_id [IN]
* path [?]
* RETURNS
* void
*****************************************************************************/
void aud_vr_sd_scan_tags_in_group_folder(kal_uint16 group_id, kal_uint16 *path)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
kal_uint16 filename[VR_MAX_DB_PATH_LEN + 1];
kal_uint16 filename_expr[VR_MAX_DB_PATH_LEN + 1];
kal_int32 word_id;
FS_HANDLE fd_cursor;
FS_DOSDirEntry file_info;
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
vr_sd_ctx.id_length[group_id] = 0;
kal_wsprintf(filename_expr, "%wMTKVR_????.vrd", path);
if ((fd_cursor = FS_FindFirst(filename_expr, 0, 0, &file_info, filename, (VR_MAX_DB_PATH_LEN + 1) << 1)) >= 0)
{
/* loop through all vrd files in a group folder */
do
{
/* filter out folder results */
if (!(file_info.Attributes & FS_ATTR_DIR))
{
/* parse word id and add to id array and increment id length */
if ((word_id = aud_vr_sd_extract_word_id(filename)) >= 0)
{
vr_sd_ctx.id_array[group_id][vr_sd_ctx.id_length[group_id]++] = word_id;
}
}
} while (FS_FindNext(fd_cursor, &file_info, filename, (VR_MAX_DB_PATH_LEN + 1) << 1) == FS_NO_ERROR);
FS_FindClose(fd_cursor);
}
}
下面讲一讲匹配,这里所说的匹配主要是将文件格式(即后缀名)的匹配,在获取到文件名以后进行。
思路也都是相同的,那就是从文件名末端开始搜索到第一个".",然后截取"."后面这一段作为拓展名,然后把这个拓展名拿到自己的需要的格式列表中对比即可。
MTK中有两种方式实现了这个需求,
方式1(来自FileManagerSrc.c):
/*****************************************************************************
* FUNCTION
* mmi_fmgr_get_file_group
* DESCRIPTION
* check file type belongs to which file group
* PARAMETERS
* path [?]
* RETURNS
* void
*****************************************************************************/
U8 mmi_fmgr_get_file_group(S8 *path)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
FMGR_FILTER file_type;
S32 result;
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
result = mmi_fmgr_get_file_type(path, &file_type);
if (result == FS_FILE_NOT_FOUND)
{
return FMGR_GROUP_UNKNOWN;
}
if (FMGR_FILTER_IS_SET_AUDIO(&file_type))
{
return FMGR_GROUP_AUDIO;
}
else if (FMGR_FILTER_IS_SET_IMAGE(&file_type))
{
return FMGR_GROUP_IMAGE;
}
else if (FMGR_FILTER_IS_SET_VIDEO(&file_type))
{
return FMGR_GROUP_VIDEO;
}
else if (FMGR_FILTER_IS_SET_SWFLASH(&file_type))
{
return FMGR_GROUP_SWFLASH;
}
else
{
return FMGR_GROUP_UNKNOWN;
}
}
在mmi_fmgr_get_file_type函数内实现了相应的逻辑,这个流程依赖于FileMgr.c中
const fmgr_filter_struct fmgr_filter[FMGR_MAX_FILTER_COUNT];
方式2: 依赖于系统的全局变量的东西有时并不能满足我们应用的需求,这个时候我们需要自己定义一个私有的fmgr_filter,来实现拓展名的判断。
这个流程的实现可以参照09A代码AudioPlayerPlayList.c中mmi_audply_playlist_generate_search函数。
下面来对比两个获取后缀名的函数:
/*****************************************************************************
* FUNCTION
* mmi_fmgr_extract_ext_file_name
* DESCRIPTION
* get pointer to the extension file name in the file path
* PARAMETERS
* path [?]
* RETURNS
* void
*****************************************************************************/
PS8 mmi_fmgr_extract_ext_file_name(S8 *path)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
S16 i, length;
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
length = (S16) mmi_ucs2strlen(path);
i = length - 1;
while (i >= 0)
{
if (path[i << 1] == '\\' && path[(i << 1) + 1] == 0)
{
return NULL;
}
if (path[i << 1] == '.' && path[(i << 1) + 1] == 0 && (i != length - 1))
{
break;
}
i--;
}
if (i < 0)
{
return NULL;
}
return &path[(i + 1) << 1];
}
另一种系统string处理的接口:
/*****************************************************************************
* FUNCTION
* app_ucs2_strrchr
* DESCRIPTION
* Scan a UCS2 encoded string for the last occurrence of a character.
* PARAMETERS
* string [IN] UCS2 encoded string to search in.
* ch [IN] UCS2 encoded wide-character to search for.
* RETURNS
* returns pointer to the last occurrence of ch in string
* returns NULL if ch does not occur in string
*****************************************************************************/
kal_int8 *app_ucs2_strrchr(const kal_int8 * string, kal_wchar ch)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
kal_int8 *cursor = (kal_int8 *)string;
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
while (*cursor || *(cursor+1)) /* find end of string */
{
cursor += 2;
}
/* search towards front */
while ((kal_int8 *)string != cursor &&
(*(cursor+1)<<8|(kal_uint8)(*cursor)) != ch)
{
cursor -= 2;
}
if ((*(cursor+1)<<8|(kal_uint8)(*cursor)) == ch) /* found ?*/
{
return cursor;
}
return NULL;
}
PS8 test(const UI_string_type ext)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
U8 i = 0;
U32 ext_len = 0;
UI_character_type file_ext[FMGR_MAX_EXT_LEN + 1];
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
/* skip ".". */
{
PS8 dot = (PS8)app_ucs2_strrchr((const PS8)ext, (U16)L'.');
if (dot)
{
dot += 2;
}
else
{
dot = (PS8)ext;
}
mmi_ucs2ncpy((PS8)file_ext, (const PS8)dot, FMGR_MAX_EXT_LEN);
ext_len = mmi_ucs2strlen((const PS8)dot);
return dot;
}
}
相关文章推荐
- MTK优美代码赏析1:二分查找
- MTK优美代码赏析3:nvram存储和读取部分的分析
- MTK优美代码赏析6:电话本里的快速排序和插入排序算法
- MTK优美代码赏析4:MTK_MMI协议栈
- MTK优美代码赏析8:可变参数的C函数
- MTK优美代码赏析4:MTK_MMI协议栈
- MTK优美代码赏析3
- MTK优美代码赏析5:LCD_BlackWrite与MTK中断控制器
- MTK优美代码赏析2:MenuItemMask_flag
- MTK优美代码赏析4:MTK_MMI协议栈
- MTK优美代码赏析1:二分查找
- MTK优美代码赏析2:MenuItemMask_flag
- Linux下代码行查询,显示文件树,搜索文件
- MTK代码DCT修改dws文件常见问题总结
- C语言实现修改文本文件中特定行的实现代码(百度一天没找到,bing搜索十分钟就找到了)
- .Net/C# 封装磁盘目录文件搜索功能的工具类 (实现了与搜索相关的事件,以便插入客户处理代码)
- MTK平台DTS文件匹配过程
- Java递归搜索指定文件夹下的匹配文件
- 匹配路径特征的文件搜索