Thursday, December 20, 2007

宽字符处理函数函数与普通函数对照表

宽字符处理函数函数与普通函数对照表
 

字符分类:     宽字符函数普通C函数描述
iswalnum()     isalnum() 测试字符是否为数字或字母
iswalpha()     isalpha() 测试字符是否是字母
iswcntrl()     iscntrl() 测试字符是否是控制符
iswdigit()     isdigit() 测试字符是否为数字
iswgraph()     isgraph() 测试字符是否是可见字符
iswlower()     islower() 测试字符是否是小写字符
iswprint()     isprint() 测试字符是否是可打印字符
iswpunct()     ispunct() 测试字符是否是标点符号
iswspace()     isspace() 测试字符是否是空白符号
iswupper()     isupper() 测试字符是否是大写字符
iswxdigit()     isxdigit()测试字符是否是十六进制的数字


大小写转换:    
宽字符函数    普通C函数描述
towlower()     tolower() 把字符转换为小写
towupper()     toupper() 把字符转换为大写


字符比较:     宽字符函数普通C函数描述
wcscoll()     strcoll() 比较字符串


日期和时间转换:
宽字符函数描述
strftime()     根据指定的字符串格式和locale设置格式化日期和时间
wcsftime()     根据指定的字符串格式和locale设置格式化日期和时间, 并返回宽字符串
strptime()     根据指定格式把字符串转换为时间值, 是strftime的反过程


打印和扫描字符串:
宽字符函数描述
fprintf()/fwprintf()     使用vararg参量的格式化输出
fscanf()/fwscanf()         格式化读入
printf()             使用vararg参量的格式化输出到标准输出
scanf()             从标准输入的格式化读入
sprintf()/swprintf()     根据vararg参量表格式化成字符串
sscanf()             以字符串作格式化读入
vfprintf()/vfwprintf()     使用stdarg参量表格式化输出到文件
vprintf()             使用stdarg参量表格式化输出到标准输出
vsprintf()/vswprintf()     格式化stdarg参量表并写到字符串


数字转换:
宽字符函数    普通C函数描述
wcstod()     strtod()  把宽字符的初始部分转换为双精度浮点数
wcstol()     strtol()  把宽字符的初始部分转换为长整数
wcstoul()     strtoul() 把宽字符的初始部分转换为无符号长整数


多字节字符和宽字符转换及操作:
宽字符函数描述
mblen()         根据locale的设置确定字符的字节数
mbstowcs()         把多字节字符串转换为宽字符串
mbtowc()/btowc()    把多字节字符转换为宽字符
wcstombs()         把宽字符串转换为多字节字符串
wctomb()/wctob()     把宽字符转换为多字节字符


输入和输出:
宽字符函数    普通C函数描述
fgetwc()     fgetc()     从流中读入一个字符并转换为宽字符
fgetws()     fgets()     从流中读入一个字符串并转换为宽字符串
fputwc()     fputc()     把宽字符转换为多字节字符并且输出到标准输出
fputws()     fputs()     把宽字符串转换为多字节字符并且输出到标准输出串
getwc()     getc()     从标准输入中读取字符, 并且转换为宽字符
getwchar()     getchar()     从标准输入中读取字符, 并且转换为宽字符
None         gets()     使用fgetws()
putwc()     putc()     把宽字符转换成多字节字符并且写到标准输出
putwchar()     putchar()     把宽字符转换成多字节字符并且写到标准输出
None         puts()     使用fputws()
ungetwc()     ungetc()     把一个宽字符放回到输入流中


字符串操作:
宽字符函数        普通C函数描述
wcscat()         strcat()     把一个字符串接到另一个字符串的尾部
wcsncat()         strncat()     类似于wcscat(), 而且指定粘接字符串的粘接长度.
wcschr()         strchr()     查找子字符串的第一个位置
wcsrchr()         strrchr()     从尾部开始查找子字符串出现的第一个位置
wcspbrk()         strpbrk()     从一字符字符串中查找另一字符串中任何一个字符第一次出现的位置
wcswcs()/wcsstr()     strchr()     在一字符串中查找另一字符串第一次出现的位置
wcscspn()         strcspn()     返回不包含第二个字符串的的初始数目
wcsspn()         strspn()     返回包含第二个字符串的初始数目
wcscpy()         strcpy()     拷贝字符串
wcsncpy()         strncpy()     类似于wcscpy(), 同时指定拷贝的数目
wcscmp()         strcmp()     比较两个宽字符串
wcsncmp()         strncmp()     类似于wcscmp(), 还要指定比较字符字符串的数目
wcslen()         strlen()     获得宽字符串的数目
wcstok()         strtok()     根据标示符把宽字符串分解成一系列字符串
wcswidth()         None         获得宽字符串的宽度
wcwidth()         None         获得宽字符的宽度


另外还有对应于memory操作的 wmemcpy(), wmemchr(), wmemcmp(), wmemmove(), wmemset().

宽字符处理函数函数与普通函数对照表

宽字符处理函数函数与普通函数对照表
 

字符分类:     宽字符函数普通C函数描述
iswalnum()     isalnum() 测试字符是否为数字或字母
iswalpha()     isalpha() 测试字符是否是字母
iswcntrl()     iscntrl() 测试字符是否是控制符
iswdigit()     isdigit() 测试字符是否为数字
iswgraph()     isgraph() 测试字符是否是可见字符
iswlower()     islower() 测试字符是否是小写字符
iswprint()     isprint() 测试字符是否是可打印字符
iswpunct()     ispunct() 测试字符是否是标点符号
iswspace()     isspace() 测试字符是否是空白符号
iswupper()     isupper() 测试字符是否是大写字符
iswxdigit()     isxdigit()测试字符是否是十六进制的数字


大小写转换:    
宽字符函数    普通C函数描述
towlower()     tolower() 把字符转换为小写
towupper()     toupper() 把字符转换为大写


字符比较:     宽字符函数普通C函数描述
wcscoll()     strcoll() 比较字符串


日期和时间转换:
宽字符函数描述
strftime()     根据指定的字符串格式和locale设置格式化日期和时间
wcsftime()     根据指定的字符串格式和locale设置格式化日期和时间, 并返回宽字符串
strptime()     根据指定格式把字符串转换为时间值, 是strftime的反过程


打印和扫描字符串:
宽字符函数描述
fprintf()/fwprintf()     使用vararg参量的格式化输出
fscanf()/fwscanf()         格式化读入
printf()             使用vararg参量的格式化输出到标准输出
scanf()             从标准输入的格式化读入
sprintf()/swprintf()     根据vararg参量表格式化成字符串
sscanf()             以字符串作格式化读入
vfprintf()/vfwprintf()     使用stdarg参量表格式化输出到文件
vprintf()             使用stdarg参量表格式化输出到标准输出
vsprintf()/vswprintf()     格式化stdarg参量表并写到字符串


数字转换:
宽字符函数    普通C函数描述
wcstod()     strtod()  把宽字符的初始部分转换为双精度浮点数
wcstol()     strtol()  把宽字符的初始部分转换为长整数
wcstoul()     strtoul() 把宽字符的初始部分转换为无符号长整数


多字节字符和宽字符转换及操作:
宽字符函数描述
mblen()         根据locale的设置确定字符的字节数
mbstowcs()         把多字节字符串转换为宽字符串
mbtowc()/btowc()    把多字节字符转换为宽字符
wcstombs()         把宽字符串转换为多字节字符串
wctomb()/wctob()     把宽字符转换为多字节字符


输入和输出:
宽字符函数    普通C函数描述
fgetwc()     fgetc()     从流中读入一个字符并转换为宽字符
fgetws()     fgets()     从流中读入一个字符串并转换为宽字符串
fputwc()     fputc()     把宽字符转换为多字节字符并且输出到标准输出
fputws()     fputs()     把宽字符串转换为多字节字符并且输出到标准输出串
getwc()     getc()     从标准输入中读取字符, 并且转换为宽字符
getwchar()     getchar()     从标准输入中读取字符, 并且转换为宽字符
None         gets()     使用fgetws()
putwc()     putc()     把宽字符转换成多字节字符并且写到标准输出
putwchar()     putchar()     把宽字符转换成多字节字符并且写到标准输出
None         puts()     使用fputws()
ungetwc()     ungetc()     把一个宽字符放回到输入流中


字符串操作:
宽字符函数        普通C函数描述
wcscat()         strcat()     把一个字符串接到另一个字符串的尾部
wcsncat()         strncat()     类似于wcscat(), 而且指定粘接字符串的粘接长度.
wcschr()         strchr()     查找子字符串的第一个位置
wcsrchr()         strrchr()     从尾部开始查找子字符串出现的第一个位置
wcspbrk()         strpbrk()     从一字符字符串中查找另一字符串中任何一个字符第一次出现的位置
wcswcs()/wcsstr()     strchr()     在一字符串中查找另一字符串第一次出现的位置
wcscspn()         strcspn()     返回不包含第二个字符串的的初始数目
wcsspn()         strspn()     返回包含第二个字符串的初始数目
wcscpy()         strcpy()     拷贝字符串
wcsncpy()         strncpy()     类似于wcscpy(), 同时指定拷贝的数目
wcscmp()         strcmp()     比较两个宽字符串
wcsncmp()         strncmp()     类似于wcscmp(), 还要指定比较字符字符串的数目
wcslen()         strlen()     获得宽字符串的数目
wcstok()         strtok()     根据标示符把宽字符串分解成一系列字符串
wcswidth()         None         获得宽字符串的宽度
wcwidth()         None         获得宽字符的宽度


另外还有对应于memory操作的 wmemcpy(), wmemchr(), wmemcmp(), wmemmove(), wmemset().

Monday, November 05, 2007

putty 备份

Putty �份

Putty 主要是��西都存在 registry �面, 所以要�份主要就是�份 registry �面的�料.

  1. �行 → regedit
  2. 到 HKEY_CURRENT_USER\Software\SimonTatham\PuTTY
  3. 在此目�下有 Sessions 目�: �定��的�目、�定值
  4. 再�是 SshHostKeys 目�: ��所有曾�定�的 Remote Host Public Key
  5. ���, 就是� PuTTY �整� registry �出�就�了~

Tuesday, September 18, 2007

vmstate

vmstat 1
 
vmstat 是用来实时查看内存使用情况,反映的情况比用top直观一些.
如果直接使用,只能得到当前的情况,最好用个时间间隔来采集
vmstat T 其中T用具体的时间标示,单位是 秒 例如:vmstat 5 表格每隔5秒采集一次.
这样在刷新的时候就能比较系统的看到那个列不正常的
procs:
r-->;在运行队列中等待的进程数
b-->;在等待io的进程数
w-->;可以进入运行队列但被替换的进程

memoy
swap-->;现时可用的交换内存(k表示)
free-->;空闲的内存(k表示)

pages
re--》回收的页面
mf--》非严重错误的页面
pi--》进入页面数(k表示)
po--》出页面数(k表示)
fr--》空余的页面数(k表示)
de--》提前读入的页面中的未命中数
sr--》通过时钟算法扫描的页面

disk 显示每秒的磁盘操作。 s表示scsi盘,0表示盘号

fault 显示每秒的中断数
in--》设备中断
sy--》系统中断
cy--》cpu交换

cpu 表示cpu的使用状态
cs--》用户进程使用的时间
sy--》系统进程使用的时间
id--》cpu空闲的时间


其中:
如果 r经常大于 4 ,且id经常少于40,表示cpu的负荷很重。
如果pi,po 长期不等于0,表示内存不足。
如果disk 经常不等于0, 且在 b中的队列 大于3, 表示 io性能不好。

Sunday, September 16, 2007

Bugzilla

Bugzilla使用指南


翻译:Jerry [2005-11-11]
原文出处:http://www.51frient.com
原文作者:不详
转载请注明:来自Sawin系统分析之窗

绪言

什么是Bugzilla

Bugzilla是一个错误跟踪系统,用于对软件产品程序开发过程的错误跟踪。它的强大功能表现在以下几个方面:
1.         强大的检索功能
2.         用户可配置的通过Email公布Bug变更
3.         历史变更记录
4.         通过跟踪和描述处理Bug
5.         附件管理
6.         完备的产品分类方案和细致的安全策略
7.         安全的审核机制
8.         强大的后端数据库支持
9.         Web,Xml,Email和控制界面
10.     友好的网络用户界面
11.     丰富多样的配置设定
12.     版本间向下兼容

为什么使用Bugzilla

Bugzilla是一个拥有强大功能的错误跟踪系统。它可以使我们更好的在软件开发过程中跟踪软件错误的处理过程,为开发和测试工作以及产品质量的度量提供数据支持,从而有效的保证软件产品的质量。
 

Bugzilla使用指南

新建一个Bugzilla账号

1.       点击"Open a new Bugzilla account"链接,输入你的Email地址(如:XXX@office)然后点击"Create Account"。
2.       稍候,你会收到一封邮件。邮件中包含你的登录账号(与你的Email相同)和口令,这个口令时Bugzilla系统随机生成的,你可以根据你的需要进行变更。
3.         在页面的黄色页角中点击"Log In"链接,而后输入你的账号和口令。最后点击"Login"

产品和结构(Product and Component)

Bug记录按产品分类,每种产品按功能拆分成几类。以Bugzilla产品为例,它由以下几部分构成:
l          Administration
l          Bugzilla-General
l          Creating/Changing Bug
l          Documentation
l          Email
l          Installation
l          Query/Buglist
l          Reporting/Charting
l          User Accounts
l          Changing Passwords
l          User Interface

Bug报告状态分类和Bug处理意见(Status and Resolution):

1.       Bug报告状态分类(Status)
l          待确认的(Unconfirmed)
l          新提交的(New)
l          已分配的(Assigned)
l          问题未解决的(Reopened)
l          待返测的(Resolved)
l          待归档的(Verified)
l          已归档的(Closed)
2.       Bug处理意见(Resolution)
l          已修改的(Fixed)
l          不是问题(Nvalid)
l          无法修改(Wontfix)
l          以后版本解决(Later)
l          保留(Remind)
l          重复(Duplicate)
l          无法重现(Worksforme)

指定处理人(Assigned To)

l          可以指定一个处理人
l          如不指定处理人,则系统指定管理员为默认处理人

超链接(URL)

l          输入超链接地址,引导处理人找到与报告相关联的信息

概述(Summary)

l          概述部分"Summary"的描述,应保证处理人在阅读时能够清楚提交者在进行什么操作的时候发现了什么问题。
l          如果是通用组件部分的测试,则必须将这一通用组件对应的功能名称写入概述中,以便今后查询。

硬件平台和操作系统(Platform and OS)

l          测试应用的硬件平台(Platform),通常选择"PC"
l          测试应用的操作系统平台(OS)

版本(Version)

l          产生Bug的软件版本

Bug报告优先级(Priority)

l          分五个等级即P1-P5,P1的优先级别最高之后逐级递减

Bug状态(Severity)

l          Blocker,阻碍开发和/或测试工作
l          Critical,死机,丢失数据,内存溢出
l          Major,较大的功能缺陷
l          Normal,普通的功能缺陷
l          Minor,较轻的功能缺陷
l          Trivial,产品外观上的问题或一些不影响使用的小毛病,如菜单或对话框中的文字拼写或字体问题等等
l          Enhancement,建议或意见

报告人(Reporter)

l          Bug报告提交者的账号

邮件抄送列表(CC List)

l          Bug报告抄送对象,该项可以不填
l          如需要抄送多人,可将邮件地址用","分隔

从属关系(Bug "ID" depends on,Bug "ID" blocks)

l          "Bug "ID" depends on"如果该Bug必须在其他Bug修改以后才能够修改,则在此项目后填写那个Bug的编号
l          "Bug "ID" blocks"如果该Bug的存在影响了其他Bug的修改,则在此项目后填写被影响的Bug编号

附加描述(Additional Comments)

l          在Bug跟踪过程中测试与开发人员通过这里进行沟通
l          开发人员可以在这里填写处理意见和处理记录
l          测试人员可以在这里填写返测意见和对在返测过程中发现的新问题进行描述

Bug查找

l          可以通过页脚中的"Query"链接进入查找界面
l          根据查找的需要在界面中选择对象或输入关键字
l          查找功能能够进行字符或字串的匹配查找
l          查找功能具有布尔逻辑检索功能
l          你可以通过在查找页面中选择"Remember this as my default query"将当前检索页面中设定的项目保存。以后可以从页脚中的My bugs中直接调用这个项目进行检索
l          你还可以通过在"Remember this query, and name it:"后面输入字符,将你当前检索页面中设定的项目保存命名,同时选中"and put it in my page footer"。则以后这个被命名的检索将出现在页脚中。(有关如何在页脚中设定显示的项目请参见1.5.3)

Bug列表

l          如果你运行了Bug检索功能,系统会根据你的需要列出相关的项目
l          你可以通过列表页脚附近的"Change Columns"设定在列表中显示的Bug记录中的字段名称
l          如果你拥有必要的权限,你还可以通过"Change several bugs"修改列表中罗列出的Bug的记录。例如:修改Bug的所有者
l          通过"Send mail to bug owners"你可以给列表中罗列的Bug记录的所有者发信
l          如果你对查找的结果不满意,希望重新调整检索设定。你可以通过"Edit this query"实现
l          通常情况下,检索结果中只显示最基本的信息。你可以通过"Long Format"显示更详细的内容

用户属性设置(Edit prefs)

1           账号设置(Account Settings)
l          在这里你可以改变你账号的基本信息,如口令,Email地址,真实姓名
l          为了安全起见,在此页进行任何更改之前你都必须输入你当前的口令
l          当你变更了你的Email地址,系统会给你的新老Email地址分别发一封确认邮件,你必须到邮件中指定的地址对你的更改进行确认
2           Email设置(Email Settings)
l          你可以在此通过选择告诉系统,你希望在什么条件下收到和你相关的邮件
3           页脚(Page Footer)
l          设定"Preset Queries"是否在页脚中显示
4           用户权限(Permissions)
你可以在此查看自己账号现在的权限
 
 
测试跟踪工具Bugzilla介绍
文章出处:http://www.csai.cn 作者:徐异婕 发布时间:2005-11-06

 

    也许你还没有看到一个错误管理系统所具有的价值;也许你正被大量的测试数据所淹没,而迫切的需要一个产品缺陷的记录及跟踪的好帮手;也许你正在通过如:电子表格、数据库等各种方式来不断的开发和完善一个错误跟踪系统。Mozilla公司向我们提供了一个共享的免费工具Buzilla.作为一个产品缺陷的记录及跟踪工具,它能够为你建立一个完善的Bug跟踪体系,包括报告Bug、查询Bug记录并产生报表、处理解决、管理员系统初始化和设置四部分。并具有如下特点:

  1。基于Web方式,安装简单、运行方便快捷、管理安全。

  2。有利于缺陷的清楚传达。本系统使用数据库进行管理,提供全面详尽的报告输入项,产生标准化的Bug报告。 提供大量的分析选项和强大的查询匹配能力,能根据各种条件组合进行Bug统计。当错误在它的生命周期中变化时,开发人员、测试人员、及管理人员将及时获得动态的变化信息,允许你获取历史纪录,并在检查错误的状态时参考这一记录。

  3。系统灵活,强大的可配置能力。Buzilla工具可以对软件产品设定不同的模块,并针对不同的模块设定制定的开发人员和测试人员;这样可以实现提交报告时自动发给指定的责任人;并可设定不同的小组,权限也可划分。设定不同的用户对Bug记录的操作权限不同,可有效控制进行管理。允许设定不同的严重程度和优先级可以在错误的生命其中管理错误,从最初的报告到最后的解决,确保了错误不会被忽略,同时可以使注意力集中在优先级和严重程度高的错误上。

  4。自动发送Email,通知相关人员。根据设定的不同责任人,自动发送最新的动态信息,有效的帮助测试人员和开发人员进行沟通。

  下面我们将按照Bugzilla的操作说明、 Bugzilla管理员的操作指南两部分来说明这个工具的具体使用。本文有不少观点来自个人使用心得,有不妥之处,敬请斧正。

Bugzilla操作说明

1、 用户登录及设置


1.1用户登录

  1. 用户输入服务器地址http://192.168.1.6/bugzilla/。

  2. 进入主页面后,点击【Forget the currently stored login】,再点击【login in】进入。

  3. 进入注册页面,输入用户名和密码即可登录。用户名为Email 地址,初始密码为用户名缩写。

  4. 如忘记密码,输入用户名,点击【submit request】,根据收到的邮件进行重新设置。

1.2、修改密码及设置

  1.Login登录后,【Edit prefs】->【accout settings】 进行密码修改。

  2.【Edit prefs】->【email settings】 进行邮件设置。

  3.【Edit prefs】-> 【permissions】 进行权限查询

2、Bug的处理过程

2.1、报告Bug

2.1.1测试人员报告Bug

  1. 请先进行查询,确认要提交的bug报告不会在原有纪录中存在,若已经存在,不要提交,若有什么建议,可在原有纪录中增加注释,告知其属主,让bug的属主看到这个而自己去修改。

  2. 若Bug不存在,创建一份有效的bug报告后进行提交。

  3. 操作:点击New,选择产品后,填写下表。

  4. 填表注意:Assigned to: 为空则默认为设定的 owner, 也可手工制定。CC: 可为多人,需用","隔开。Desription中要详细说明下列情况:

  1) 发现问题的步骤

  2) 执行上述步骤后出现的情况。

  3) 期望应出现的正确结果。

  选择group设置限定此bug对组的权限,若为空,则为公开。

  5. 操作结果:Bug状态(status)可以选择Initial state 为New或Unconfirmed.

  系统将自动通过Email通知项目组长或直接通知开发者。

  6.帮助: Bug writing guidelines

2.1.2 开发人员报告Bug.

  1. 具体方法同测试人员报告。

  2. 区别: Bug初始状态将自动设为Unconfirmed,待测试人员确定后变为"New".

2.2、Bug的不同处理情况

2.2.1 Bug的属主 (owner) 处理问题后,提出解决意见及方法。

  1 . 给出解决方法并填写Additional Comments,还可创建附件(如:更改提交单)

  2.具体操作(填表项如下)

  3 . 填表注意:

  FIXED 描述的问题已经修改

  INVALID 描述的问题不是一个bug (输入错误后,通过此项来取消)

  WONTFIX 描述的问题将永远不会被修复。

  LATER 描述的问题将不会在产品的这个版本中解决.

  DUPLICATE 描述的问题是一个存在的bug的复件。

  WORKSFORME 所有要重新产生这个bug的企图是无效的。如果有更多的信息出现,请重新分配这个bug,而现在只把它归档。

2.2.2 项目组长或开发者重新指定Bug的属主。(owner)

  1. 为此bug不属于自己的范围,可置为 Assigned,等待测试人员重新指定。

  2. 为此bug不属于自己的范围,但知道谁应该负责,直接输入被指定人的Email, 进行Ressigned。

  3. 操作:(可选项如下)

  * Accept bug (change status to ASSIGNED)

  * Reassign bug to

  * Reassign bug to owner and QA contact of selected component

  4. 操作结果:此时bug状态又变为New,此bug的owner变为被指定的人。

2.2.3测试人员验证已修改的 Bug.

  1. 测试人员查询开发者已修改的bug,即Status为"Resolved",Resolution为"Fixed".进行重新测试。(可创建test case附件)

  2. 经验证无误后,修改Resolution为VERIFIED。待整个产品发布后,修改为CLOSED。

  若还有问题,REOPENED,状态重新变为"New",并发邮件通知。

  3. 具体操作(可选择项)

   1. Leave as RESOLVED FIXED

   2. Reopen bug

   3. Mark bug as VERIFIED

   4. Mark bug as CLOSED

2.2.4 Bug报告者(reporter)或其他有权限的用户修改及补充Bug

  1. 可以修改Bug的各项内容。

  2. 可以增加建立附件,增加了相关性, 并加一些评论来解释你正在做些什么和你为什么做。

  3. 操作结果:每当一些人修改了bug报告或加了一个评论,他们将会被加到CC列表中,bug报告中的改变会显在要发给属主、写报告者和CC列表中的人的电子邮件中。

2.2.5测试人员确认开发人员报告的Bug是否存在.

  1. 查询状态为"Unconfirmed"的Bug,

  2. 测试人员对开发人员提交的Bug进行确认,确认Bug存在。

  3. 具体操作:选中"Confirm bug(change status to New)"后,进行commit.

  4. 操作结果:状态变为"New".

2.3、查询Bug

  1.直接输入Bug Id,点击find 查询。可以查看Bug的活动纪录。

  2.点击Query,输入条件进行查询。

  3.查询Bug活动的历史

  4.产生报表。

  5.帮助:点击Clue.

3、关于权限的说明

  1. 组内成员对bug具有查询的权利,但不能进行修改。

  2. Bug的owner 和 reporter 具有修改的权利。

  3. 具有特殊权限的用户具有修改的权利。

4、 BUG处理流程

  1. 测试人员或开发人员发现bug后,判断属于哪个模块的问题,填写bug报告后,通过Email通知项目组长或直接通知开发者。

  2. 项目组长根据具体情况,重新reassigned分配给bug所属的开发者。

  3. 开发者收到Email信息后,判断是否为自己的修改范围.

  1) 若不是,重新reassigned分配给项目组长或应该分配的开发者。

  2) 若是,进行处理,resolved并给出解决方法。(可创建补丁附件及补充说明)

  4. 测试人员查询开发者已修改的bug,进行重新测试。(可创建test case附件)

  1) 经验证无误后,修改状态为VERIFIED。待整个产品发布后,修改为CLOSED。

  2) 还有问题,REOPENED,状态重新变为"New",并发邮件通知。

  5. 如果这个BUG一周内一直没被处理过。Bugzilla就会一直用email骚扰它的属主,直到采取行动。

5、一个Bug的生存周期



Bugzilla管理员操作指南

1、主要工作内容:


1. 1产品(Product)、版本号(versions)和模块(Components)的定义,同时指定模块相应的开发者(owner)和测试人员(QA Contact)。

1.2小组的定义和划分

1.3测试中Bug严重程度、优先级的定义

1. 4增加用户,并分别设定全部用户的分组、权限。

1. 5主要参数(parameters)的设置

  1) urlbase: 输入bugzilla 工具所在的服务器IP地址。

  2) usebuggroupsentry: 设为ON,可以分组。

  3) whinedays:Bug在whinedays设定的期限内若未被处理,将自动重发mail,默认为7天。

  4) defaultpriority:设定默认的优先级

  5) commentonresolve:设为ON,系统将强制要求开发者处理完Bug 后,必须填写修改的内容。

2、基本操作:

2.1创建默认的管理员用户。

  运行checksetup.pl。若不小心删除管理员,重新运行checksetup.pl.

2.2 管理用户

2.1 增加新用户

  点击页面右下角【users】,submit后,出现【Add new user】页面。输入相应输入即可。Login name: 一般为邮件地址,可以设为其他标识。

2.2 禁止一个用户

  填写Disabled text 输入框即可。

2.3 修改用户

  可以修改用户注册名、密码。

  设置权限

  QA的权限一般设为: Canconfirm, editbugs

  Developer的权限设为: none

  分组控制:group

3、管理group

3.1.增加group

  edit groupàadd groups (New User Regexp可不填/active 选择则可选)->add

3.2修改group ,submit 即可。

  4、管理Product 和 component

  a)增加Product

  b) Component 对应一个owner(进行fixed),QA Contact(确保已fixed)

  c) Component Number of Unconfirmed =10000,此产品将选择bug的初始状态

 
 

Tuesday, September 04, 2007

sip 消息

您可以列出所有已知的SIP应答吗?

1xx = 通知性应答

  • 100 正在尝试
  • 180 正在拨打
  • 181 正被转接
  • 182 正在排队
  • 183 通话进展

2xx = 成功应答

  • 200 OK
  • 202 被接受:用于转介

3xx = 转接应答

  • 300 多项选择
  • 301 被永久迁移
  • 302 被暂时迁移
  • 305 使用代理服务器
  • 380 替代服务

4xx = 呼叫失败

  • 400 呼叫不当
  • 401 未经授权:只供注册机构使用,代理服务器应使用代理服务器授权407
  • 402 要求付费(预订为将来使用)
  • 403 被禁止的
  • 404 未发现:未发现用户
  • 405 不允许的方法
  • 406 不可接受
  • 407 需要代理服务器授权
  • 408 呼叫超时:在预定时间内无法找到用户
  • 410 已消失:用户曾经存在,但已从此处消失
  • 413 呼叫实体过大
  • 414 呼叫URI过长
  • 415 不支持的媒体类型
  • 416 不支持的URI方案
  • 420 不当扩展:使用了不当SIP协议扩展,服务器无法理解该扩展
  • 421 需要扩展
  • 423 时间间隔过短
  • 480 暂时不可使用
  • 481 通话/事务不存在
  • 482 检测到循环
  • 483 跳数过多
  • 484 地址不全
  • 485 模糊不清
  • 486 此处太忙
  • 487 呼叫被终止
  • 488 此处不可接受
  • 491 呼叫待批
  • 493 无法解读:无法解读 S/MIME文体部分

5xx = 服务器失败

  • 500 服务器内部错误
  • 501 无法实施:SIP呼叫方法在此处无法实施
  • 502 不当网关
  • 503 服务不可使用
  • 504 服务器超时
  • 505 不支持该版本:服务器不支持SIP协议的这个版本
  • 513 消息过长

6xx = 全局失败

  • 600 各处均忙
  • 603 拒绝
  • 604 无处存在
  • 606 不可使用

Wednesday, August 15, 2007

wav文件格式分析详解

 
 
 
     wav文件格式分析详解

                                               作者:曹京
                                               日期:2006年7月17日
                                         

一、综述
    WAVE文件作为多媒体中使用的声波文件格式之一,它是以RIFF格式为标准的。
RIFF是英文Resource Interchange File Format的缩写,每个WAVE文件的头四个
字节便是"RIFF"。
    WAVE文件是由若干个Chunk组成的。按照在文件中的出现位置包括:RIFF WAVE
Chunk, Format Chunk, Fact Chunk(可选), Data Chunk。具体见下图:

------------------------------------------------
|             RIFF WAVE Chunk                  |
|             ID  = 'RIFF'                     |
|             RiffType = 'WAVE'                |
------------------------------------------------
|             Format Chunk                     |
|             ID = 'fmt '                      |
------------------------------------------------
|             Fact Chunk(optional)             |
|             ID = 'fact'                      |
------------------------------------------------
|             Data Chunk                       |
|             ID = 'data'                      |
------------------------------------------------
            图1   Wav格式包含Chunk示例

    其中除了Fact Chunk外,其他三个Chunk是必须的。每个Chunk有各自的ID,位
于Chunk最开始位置,作为标示,而且均为4个字节。并且紧跟在ID后面的是Chunk大
小(去除ID和Size所占的字节数后剩下的其他字节数目),4个字节表示,低字节
表示数值低位,高字节表示数值高位。下面具体介绍各个Chunk内容。
PS:
    所有数值表示均为低字节表示低位,高字节表示高位。

二、具体介绍
RIFF WAVE Chunk
    ==================================
    |       |所占字节数|  具体内容   |
    ==================================
    | ID    |  4 Bytes |   'RIFF'    |
    ----------------------------------
    | Size  |  4 Bytes |             |
    ----------------------------------
    | Type  |  4 Bytes |   'WAVE'    |
    ----------------------------------
            图2  RIFF WAVE Chunk

    以'FIFF'作为标示,然后紧跟着为size字段,该size是整个wav文件大小减去ID
和Size所占用的字节数,即FileLen - 8 = Size。然后是Type字段,为'WAVE',表
示是wav文件。
    结构定义如下:
 struct RIFF_HEADER
 {
  char szRiffID[4];  // 'R','I','F','F'
  DWORD dwRiffSize;
  char szRiffFormat[4]; // 'W','A','V','E'
 };

 

Format Chunk
    ====================================================================
    |               |   字节数  |              具体内容                |
    ====================================================================
    | ID            |  4 Bytes  |   'fmt '                             |
    --------------------------------------------------------------------
    | Size          |  4 Bytes  | 数值为16或18,18则最后又附加信息     |
    --------------------------------------------------------------------  ----
    | FormatTag     |  2 Bytes  | 编码方式,一般为0x0001               |     |
    --------------------------------------------------------------------     |
    | Channels      |  2 Bytes  | 声道数目,1--单声道;2--双声道       |     |
    --------------------------------------------------------------------     |
    | SamplesPerSec |  4 Bytes  | 采样频率                             |     |
    --------------------------------------------------------------------     |
    | AvgBytesPerSec|  4 Bytes  | 每秒所需字节数                       |     |===> WAVE_FORMAT
    --------------------------------------------------------------------     |
    | BlockAlign    |  2 Bytes  | 数据块对齐单位(每个采样需要的字节数) |     |
    --------------------------------------------------------------------     |
    | BitsPerSample |  2 Bytes  | 每个采样需要的bit数                  |     |
    --------------------------------------------------------------------     |
    |               |  2 Bytes  | 附加信息(可选,通过Size来判断有无) |     |
    --------------------------------------------------------------------  ----
                            图3  Format Chunk

    以'fmt '作为标示。一般情况下Size为16,此时最后附加信息没有;如果为18
则最后多了2个字节的附加信息。主要由一些软件制成的wav格式中含有该2个字节的
附加信息。
    结构定义如下:
 struct WAVE_FORMAT
 {
  WORD wFormatTag;
  WORD wChannels;
  DWORD dwSamplesPerSec;
  DWORD dwAvgBytesPerSec;
  WORD wBlockAlign;
  WORD wBitsPerSample;
 };
 struct FMT_BLOCK
 {
  char  szFmtID[4]; // 'f','m','t',' '
  DWORD  dwFmtSize;
  WAVE_FORMAT wavFormat;
 };


Fact Chunk
    ==================================
    |       |所占字节数|  具体内容   |
    ==================================
    | ID    |  4 Bytes |   'fact'    |
    ----------------------------------
    | Size  |  4 Bytes |   数值为4   |
    ----------------------------------
    | data  |  4 Bytes |             |
    ----------------------------------
            图4  Fact Chunk

    Fact Chunk是可选字段,一般当wav文件由某些软件转化而成,则包含该Chunk。
    结构定义如下:
 struct FACT_BLOCK
 {
  char  szFactID[4]; // 'f','a','c','t'
  DWORD  dwFactSize;
 };

 

Data Chunk
    ==================================
    |       |所占字节数|  具体内容   |
    ==================================
    | ID    |  4 Bytes |   'data'    |
    ----------------------------------
    | Size  |  4 Bytes |             |
    ----------------------------------
    | data  |          |             |
    ----------------------------------
             图5 Data Chunk

    Data Chunk是真正保存wav数据的地方,以'data'作为该Chunk的标示。然后是
数据的大小。紧接着就是wav数据。根据Format Chunk中的声道数以及采样bit数,
wav数据的bit位置可以分成以下几种形式:
    ---------------------------------------------------------------------
    |   单声道  |    取样1    |    取样2    |    取样3    |    取样4    |
    |           |--------------------------------------------------------
    |  8bit量化 |    声道0    |    声道0    |    声道0    |    声道0    |
    ---------------------------------------------------------------------
    |   双声道  |          取样1            |           取样2           |
    |           |--------------------------------------------------------
    |  8bit量化 |  声道0(左)  |  声道1(右)  |  声道0(左)  |  声道1(右)  |
    ---------------------------------------------------------------------
    |           |          取样1            |           取样2           |
    |   单声道  |--------------------------------------------------------
    | 16bit量化 |    声道0    |  声道0      |    声道0    |  声道0      |
    |           | (低位字节)  | (高位字节)  | (低位字节)  | (高位字节)  |
    ---------------------------------------------------------------------
    |           |                         取样1                         |
    |   双声道  |--------------------------------------------------------
    | 16bit量化 |  声道0(左)  |  声道0(左)  |  声道1(右)  |  声道1(右)  |
    |           | (低位字节)  | (高位字节)  | (低位字节)  | (高位字节)  |
    ---------------------------------------------------------------------
                         图6 wav数据bit位置安排方式

    Data Chunk头结构定义如下:
    struct DATA_BLOCK
 {
  char szDataID[4]; // 'd','a','t','a'
  DWORD dwDataSize;
 };


三、小结
    因此,根据上述结构定义以及格式介绍,很容易编写相应的wav格式解析代码。
这里具体的代码就不给出了。

 

四、参考资料
    1、李敏, 声频文件格式WAVE的转换, 电脑知识与技术(学术交流), 2005.
    2、http://www.codeguru.com/cpp/g-m/multimedia/audio/article.php/c8935__1/
    3、http://www.smth.org/pc/pcshowcom.php?cid=129276


Tuesday, August 14, 2007

CWaveFile--一个操作和表示WAV数据的类

实现方法

介绍:

我先从简单介绍数字声音和它在计算机中的文档开始。很久很久以前,声音信号,像其他信号一样,用连续波形表示。它们被称作模拟信号。

模拟信号有很多优点,其中一个优点是它和物理变化一一对应。例如:当我们说话,我们的声带发生震动,声波通过空气传播。使用模拟仪器,我们很容易记录和保存声波(例如使用磁带)。但模拟信号也有一个很不好的缺点:抗干扰能力差。

数字信号没有这个缺点,因为数字表示可以有冗余数据。通过冗余数据的信息,即使传输过程中信号发生严重变化,也可以恢复原来的信号。因此数据信号被广泛使用:通讯、领航、医药、声音处理、计算机等。

我知道你更干兴趣的问题是:数字信号在计算机中是怎样存储的?我怎样处理它?我不想深入解释数字信号原理。你,作为一个程序员,必须知道的只有一件事:数字信号是一个数组(你会得到你自己的数组,如果你读完这篇文章的话)。对于声音数字信号,它可以是8位或16位的数字。

现在有大量的声音数字信号存储的标准(AU, VOC, WAVE, AIFF, AIFF-C, and IFF/8VX),但是实际上,微软的WAV文件使用得最广泛。

WAVE文件格式:

所有的WAVE文件符合RIFF规范。因此,WAVE文件满足以下条件:

由独立的数据块(称为chunk)组成,这些数据块组织称树状结构。

每个数据块由一个块头和数据组成。

RIFF文件的第一块(也是主要的块)是一个RIFF块,它像树的根。

通常的WAVE PCM文件是这样的:

文件的开始是RIFF头,然后是FMT块和DATA块。RIFF头有三个元素:RIFF_ID,RIFF_SIZE,RIFF_FORMAT:

  1. struct RIFF    
  2. {    
  3.   _TCHAR riffID[4];         //RIFF标识    
  4.   DWORD riffSIZE;           //文件长度减8 字节    
  5.   _TCHAR riffFORMAT[4];     //WAVE标识:"WAVE"    
  6. };  

RIFF头之后,是格式描述块format descriptor block (FMT):

  1. struct FMT    
  2. {    
  3.   _TCHAR fmtID[4];          //FMT标识: "fmt " (含空格)    
  4.   DWORD fmtSIZE;            //块大小(对于PCM16而言)                               
  5.   WAVEFORM fmtFORMAT;       //WAVEFORMATEX结构(但是没有cbSize)    
  6. };   

WAVRFORMAT机构是理解WAVE文件的关键所在。它包含我们处理WAVE文件中的所需要的信息。

  1. struct WAVEFORM    
  2. {    
  3.   WORD wFormatTag;          //数字声音的格式    
  4.   WORD nChannels;           //声道的数量(1为单声道、2为立体声)    
  5.   DWORD nSamplesPerSec;     //每秒样本数    
  6.   DWORD nAvgBytesPerSec;    //每秒平均字节数    
  7.   WORD nBlockAlign;         //播放的最小字节数    
  8.   WORD wBitsPerSample;      //每样本位数(8 或16)    
  9. };  

最后是数据块:

  1. struct DATA    
  2. {    
  3.   _TCHAR dataID[4];         //DATA块表示: "data"    
  4.   DWORD dataSIZE;           //数据大小    
  5. };  

这就是你所需要知道的WAVE文件头;文件头之后是数据。让我们看看CWaveFile接口:

  1. class CWaveFile : protected CFileMap, public  CObject {    
  2. public:    
  3.   CWaveFile( LPCTSTR fileName );    
  4.     ~CWaveFile() {}    
  5.     WAVEFORM* GetWaveFormat() { return &pFMT->fmtFORMAT; }    
  6.     DATA* GetWaveData() { return pDATA; }    
  7.     LPVOID GetData() { return reinterpret_castLPVOID >    
  8.                      ( dataAddress ); }    
  9.     BOOL DrawData( CDC *pDC, RECT *pRect, CSize *pNewSize );    
  10. protected:    
  11.   PBYTE dataAddress;    
  12.   RIFF* pRIFF;    
  13.   FMT* pFMT;    
  14.   DATA* pDATA;    
  15. private:    
  16.   BOOL CheckID(_TCHAR* idPar,_TCHAR A, _TCHAR B, _TCHAR C,    
  17.                _TCHAR D);    
  18.     void ReadWave();    
  19.     void ReadRIFF();    
  20.     void ReadFMT();    
  21.     void ReadDATA();    
  22.     void DrawByte( CDC *pDC );    
  23.     void DrawWord( CDC *pDC );    
  24. };   

正如你所看到的,CWaveFile从CObject和CFileMap继承。

内存映射文件:

内存映射文件是一个windows系统中非常有用的特性。我第一次实现CWaveFile类的时候,我不知道内存映射文件,我的代码使用缓冲区,从缓冲区中拷贝内容并...产生很多问题(虽然它可以使用)。内存映射文件是通过指针将操作磁盘文件变成如操作内存一样方便的技术。内存映射文件的操作快速而容易;另外,你不需要缓冲区。我在网上找到了Vitali Brusetsev的对内存映射文件封状的类(感谢Vitali!)。他的类封装了你需要的所有函数。因此,我问他在我的程序中使用他的类,并得到了肯定的回答。我选择他的类作为我的CWaveFile类的基类。

使用CWaveFile:

在你的工程中很容易使用CWaveFile。CWaveFile只有一个构造器,并且它只有一个参数--WAVE文件的路径。如果出错,CWaveFile会产生C++异常,所有的异常组织在下面的名字空间:

  1. namespace WaveErrors {    
  2.   class FileOperation {};    //文件错误    
  3.   class RiffDoesntMatch {};    
  4.   class WaveDoesntMatch {};    
  5.   class FmtDoesntMatch {};    
  6.   class DataDoesntMatch {};    
  7. }   

还有另外一些标识符号不匹配的异常会发生。顺便说说,我在微软的"录音机"写入的WAVE文件中发现了一些有趣的特性:数据在这些文件中被转换称6位,它从50字节开始。因此我这样做:

  1. inline void CWaveFile::ReadDATA()    
  2. {    
  3.   try {   
  4.     pDATA = reinterpret_cast> DATA* >( dataAddress );    
  5.     if( !CheckID( pDATA->dataID, 'd''a''t''a') ) {    
  6.       throw WaveErrors::DataDoesntMatch();    
  7.     }   
  8.   }catch( WaveErrors::DataDoesntMatch & ) {    
  9.     //奇怪的事情:在微软的WAVE文件中DATA表示可以是偏移量(可能是因为地址对齐)    
  10.     //手工寻找DATA_ID    
  11.     PBYTE b = Base();    
  12.     BOOL foundData = FALSE;    
  13.     while(  (dataAddress - b) !=  dwSize ) {    
  14.       if( *dataAddress == 'd' ) {    
  15.         //It can be DATA_ID, check it!    
  16.         pDATA = reinterpret_cast< DATA * >( dataAddress );    
  17.         if( CheckID( pDATA->dataID, 'd','a','t','a' ) ) {    
  18.           //DATA_ID was found    
  19.           foundData = TRUE;    
  20.           break;    
  21.         }    
  22.       }    
  23.       dataAddress++;    
  24.     }    
  25.     if( !foundData ) {    
  26.       //这个文件可能不完整    
  27.       throw WaveErrors::DataDoesntMatch();    
  28.     }    
  29.   }    
  30. }  

如果DATA标识不匹配,函数产生一个异常,并自己catch它。然后试图手工寻找DATA标识,如果找到了,一切OK,如果找不到,sorry,文件可能不完整。

ReadDATA()是三个负责读取文件头,并效验所有的标识的私有函数之一。它们组织在ReadWave函数中:

  1. void CWaveFile::ReadWave()    
  2. {    
  3.   ReadRIFF();    
  4.   //移动到下一块    
  5.     dataAddress += sizeof( *pRIFF );    
  6.   ReadFMT();    
  7.   //移动到下一块    
  8.   dataAddress += sizeof( *pFMT );    
  9.   ReadDATA();    
  10.   dataAddress += sizeof( *pDATA );    
  11.   //Wave has been read!    
  12. }  

正如你所看到,我们开始的时候读取RIFF块,如果一切顺利,我们移动到下一块(移动dataAddress指针)。不要忘记我们使用内存映射文件,

操作磁盘文件就像操作内存数据一样,酷吧?然后,我们读取FMT和DATA块,当我们离开程序,指针指向声音数据。我使用一个类型定义:

typedef short          AudioWord;

typedef unsigned char  AudioByte;

现在是时候使用简单的例子来检验我们的CWaveFile了。让我们打开一个WAVE文件,然后从中读出所有声音信息。

  1. #include <iostream>    
  2. using namespace std;   
  3. #include "CWaveFile.h"   
  4. int main()    
  5. {    
  6.   try {   
  7.     CWaveFile wave("noise.wav");    
  8.     WAVEFORM *format = wave.GetWaveFormat();    
  9.     cout << "Format: " << format->wFormatTag << endl;    
  10.     cout << "Samples per second: " << format->nSamplesPerSec    
  11.          << endl;    
  12.     cout << "Channels: " << format->nChannels << endl;    
  13.     cout << "Bit per sample: " << format->wBitsPerSample << endl;    
  14.     if( format->wBitsPerSample == 16 ) {    
  15.       AudioWord *buffer = reinterpret_cast< AudioWord * >    
  16.                           ( wave.GetData() );    
  17.       DATA *data = wave.GetWaveData();    
  18.       DWORD samples = data->dataSIZE / sizeof(AudioData);    
  19.       cout << "Samples number: " << samples << endl;    
  20.       cin.get();    
  21.       forDWORD p = 0; p < samples; p++ ) {    
  22.         cout << p << ": " << buffer[p] << endl;    
  23.       }    
  24.     }   
  25.   }catch(WaveErrors::FileOperation & ) {    
  26.     cout << "File operation error!\n";    
  27.   }catch(WaveErrors::RiffDoesntMatch & ) {    
  28.     cout << "Riff doesn't match!\n";    
  29.   }catch(WaveErrors::WaveDoesntMatch & ) {    
  30.     cout << "Wave doesn't match!\n";    
  31.   }catch(WaveErrors::DataDoesntMatch & ) {    
  32.     cout << "Data doesn't match!\n";    
  33.   }    
  34.   return 0;    
  35. }  

这是一个简单的控制台程序,但它做了大量的工作。在我的计算机,我得到下面的结果:

  Format: 1

  Samples per second: 22050

  Channels: 1

  Bits per sample: 16

  Samples number: 174680

首先,是检测"noise.wav"的有效性,如果一切顺利,接着进行下面的工作。(注意格式描述=1;这是最简单的未经压缩的PCM格式。你也很容易使用CWaveFile操作其它格式的文件,但是你必须自己关心数据怎样去解释。)Samples per second : 22050. Channels: 1 = mono sound.

Bits per sample: 16。我想知道它们是因为我需要利用它们去解释声音数据。我使用reinterpret_cast转换由GetData()返回的LPVOID。这里最重要的部分是数据的长度。

  1. DATA *data = wave.GetWaveData();    
  2. DWORD samples = data->dataSIZE / sizeof(AudioData);  

你必须使用上面的代码去获取数据大小的信息;dataSIZE包含数据大小的字节数,但我们知道当前处理的是16位的声音。

  1. if( format->wBitsPerSample == 16 ) {  

因此我们将dataSIZE除以sizeof(AudioData)(或者简单地除以2,16位是两字节)。你可能只想要声音数据,我只是将它输出到控制台。

显示数据:

毫无疑问,程序运行良好,然而它只是一个控制台程序。现在是使用windows GUI的时候了。这些数据看起来像什么?现在,我们将回答这个问题。

正如你所看到的,CWaveFile从CObject继承,是因为我想在MFC中使用它。

CWaveFile有成员函数:

BOOL DrawData( CDC *pDC, RECT *pRect, CSize *pNewSize )

这个函数负责在设备上下文中描绘数据。为了你能更好地使用它,我准备了如下例子:

  1. void CAnalyseView::OnDraw(CDC* pDC )    
  2. {    
  3.   CAnalyseDoc* pDoc = GetDocument();    
  4.   ASSERT_VALID(pDoc);   
  5.   // TODO: add draw code for native data here    
  6.   pDC->SaveDC();    
  7.   CRect rect;    
  8.   CBrush brush( RGB( 150, 200, 230 ) );    
  9.   GetClientRect( &rect );    
  10.   FillRect( *pDC, &rect, brush );   
  11.   pDC->MoveTo( rect.left, rect.bottom/2 );    
  12.   CWaveFile wave(pDoc->m_fileName);    
  13.   wave.DrawData( pDC, &rect, &m_szSize );   
  14.   pDC->MoveTo( rect.left, rect.bottom/2 );    
  15.   pDC->LineTo(rect.right, rect.bottom/2 );    
  16.   pDC->RestoreDC(-1);    
  17. }   

DrawData函数有三个参数:指向CDC的指针、指向CRect的指针,指向CSize的指针。你可以在OnSize中加入下面的代码:

  1. void CAnalyseView::OnSize(UINT nType, int cx, int cy)    
  2. {    
  3.   CView::OnSize(nType, cx, cy);   
  4.   // TODO: Add your message handler code here    
  5.   if( cx == 0 || cy == 0 ) return;    
  6.   m_szSize = CSize( cx, cy );    
  7. }   

就是这样。但我忘记告诉你DrawData方法的缺点。它只正确显示单声道数据。立体声和单声道不同,立体声样本是左右声道交替的(左、右、左、右...)。

最后:

我想在这多谢所有读到这里的人。我知道CWaveFile还未完成;如果你在这上面添加了一些函数,或者有什么Bug,请让我知道。网上见。

by:Alexander Beletsky 2003.2.3

from:codeGuru

翻译:snoopy

环境:VC6 SP4, VC.NET