Alsa 读取wave文件,并播放wave 文件
对于一个wave文件,如果需要播放,涉及到几个方面
1.对于wave文件的解析
2.通过解析wave文件,将得到的参数(主要是sampfrequency, bitsperSample,channel)通过alsa api设下去
3.正确找到data的起始点
4.play alsa
1.对于wave文件的解析,需要知道wave文件的格式
注意几点,标准的是44byte的头,但是有些情况下会有additional info, 占据2字节。头信息参见下图,也可以参考wave 文件解析
endian |
field name |
Size |
|
big | ChunkID | 4 | 文件头标识,一般就是" RIFF" 四个字母 |
little | ChunkSize | 4 | 整个数据文件的大小,不包括上面ID和Size本身 |
big | Format | 4 | 一般就是" WAVE" 四个字母 |
big | SubChunk1ID | 4 | 格式说明块,本字段一般就是"fmt " |
little | SubChunk1Size | 4 | 本数据块的大小,不包括ID和Size字段本身 |
little | AudioFormat | 2 | 音频的格式说明 |
little | NumChannels | 2 | 声道数 |
little | SampleRate | 4 | 采样率 |
little | ByteRate | 4 | 比特率,每秒所需要的字节数 |
little | BlockAlign | 2 | 数据块对齐单元 |
little | BitsPerSample | 2 | 采样时模数转换的分辨率 |
big | SubChunk2ID | 4 | 真正的声音数据块,本字段一般是"data" |
little | SubChunk2Size | 4 | 本数据块的大小,不包括ID和Size字段本身 |
little | Data | N | 音频的采样数据 |
2.设置alsa的参数可以详见代码
3.通过解析wave file可以知道我们data的起始位置
4.通过alsa来play,详见代码
- /**
- @file TestAlsaPlayWave.cpp
- @brief This is a short example to play the audio wave, please define the path in the main func
- @par author: jlm
- @par pre env: alsa
- @todo
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string>
- #include <sched.h>
- #include <errno.h>
- #include <getopt.h>
- #include <iostream>
- #include <asoundlib.h>
- #include <sys/time.h>
- #include <math.h>
- using namespace std;
- /*********Type definition***********************/
- typedef unsigned char uint8;
- typedef unsigned short uint16;
- typedef enum EBitsPerSample
- {
- BITS_UNKNOWN = ,
- BITS_PER_SAMPLE_8 = ,
- BITS_PER_SAMPLE_16 = ,
- BITS_PER_SAMPLE_32 =
- }EBitsPerSample_t;
- typedef enum ENumOfChannels
- {
- NUM_OF_CHANNELS_1 = ,
- NUM_OF_CHANNELS_2 =
- }ENumOfChannels_t;
- #if 0
- /** PCM state */
- typedef enum _snd_pcm_state {
- /** Open */
- SND_PCM_STATE_OPEN = ,
- /** Setup installed */
- SND_PCM_STATE_SETUP,
- /** Ready to start */
- SND_PCM_STATE_PREPARED,
- /** Running */
- SND_PCM_STATE_RUNNING,
- /** Stopped: underrun (playback) or overrun (capture) detected */
- SND_PCM_STATE_XRUN,
- /** Draining: running (playback) or stopped (capture) */
- SND_PCM_STATE_DRAINING,
- /** Paused */
- SND_PCM_STATE_PAUSED,
- /** Hardware is suspended */
- SND_PCM_STATE_SUSPENDED,
- /** Hardware is disconnected */
- SND_PCM_STATE_DISCONNECTED,
- SND_PCM_STATE_LAST = SND_PCM_STATE_DISCONNECTED
- } snd_pcm_state_t;
- #endif
- typedef struct ALSA_CONFIGURATION
- {
- std::string alsaDevice;
- std::string friendlyName;
- /// Read: Buffer size should be large enough to prevent overrun (read / write buffer full)
- unsigned int alsaBufferSize;
- /// Chunk size should be smaller to prevent underrun (write buffer empty)
- unsigned int alsaPeriodFrame;
- unsigned int samplingFrequency;//48kHz
- EBitsPerSample bitsPerSample;
- ENumOfChannels numOfChannels;
- bool block; // false means nonblock
- snd_pcm_access_t accessType;
- snd_pcm_stream_t streamType; // Playback or capture
- unsigned int alsaCapturePeriod; // Length of each capture period
- }Alsa_Conf;
- typedef struct Wave_Header
- {
- uint8 ChunkID[];
- uint8 ChunkSize[];
- uint8 Format[];
- uint8 SubChunk1ID[];
- uint8 SubChunk1Size[];
- uint8 AudioFormat[];
- uint8 NumChannels[];
- uint8 SampleRate[];
- uint8 ByteRate[];
- uint8 BlockAlign[];
- uint8 BitsPerSample[];
- uint8 CombineWaveFileExtra2Bytes[];
- uint8 SubChunk2ID[];
- uint8 SubChunk2Size[];
- }Wave_Header_t;
- typedef struct Wave_Header_Size_Info
- {
- uint8 ChunkID[];
- uint8 ChunkSize[];
- uint8 Format[];
- uint8 SubChunk1ID[];
- uint8 SubChunk1Size[];
- }Wave_Header_Size_Info_t;
- typedef struct Wave_Header_Audio_Info
- {
- uint8 AudioFormat[];
- uint8 NumChannels[];
- uint8 SampleRate[];
- uint8 ByteRate[];
- uint8 BlockAlign[];
- uint8 BitsPerSample[];
- }Wave_Header_Audio_Info_t;
- typedef struct Wave_Header_Additional_Info
- {
- uint8 AdditionalInfo_2Bytes[]; //this depends on the SubChunk1Size,normal if SubChunk1Size=16 then match the normal wave format, if SubChunk1Size=18 then 2 more additional info bytes
- }Wave_Header_Additional_Info_t;
- typedef struct Wave_Header_Data_Info
- {
- uint8 SubChunk2ID[];
- uint8 SubChunk2Size[];
- }Wave_Header_Data_Info_t;
- /*********Global Variable***********************/
- snd_pcm_uframes_t g_frames; //just test purpose
- /*********Func Declaration***********************/
- void TestAlsaDevice(snd_pcm_t** phandler);
- bool PrepareAlsaDevice(Alsa_Conf* palsaCfg,snd_pcm_t** phandler);
- bool closeAlsaDevice(snd_pcm_t** phandler);
- bool ParseWaveFile(const string wavepath,Alsa_Conf* palsaCfg);
- uint16 HandleLittleEndian(uint8* arr,int size);
- bool PlayWave(FILE** fp,snd_pcm_t** phandler,Alsa_Conf* palsaCfg);
- uint16 HandleLittleEndian(uint8* arr,int size)
- {
- uint16 value=;
- ;i<size;i++)
- {
- value=value+(arr[i]<<(*i));
- }
- return value;
- }
- #if 0
- //this is the return value
- ChunkID = "RIFF"
- ChunkSize =
- Format = "WAVE"
- fmt = "fmt "
- SubChunk1Size =
- AudioFormat =
- NumChannels =
- SampleRate =
- ByteRate =
- BlockAlign =
- BitsPerSample =
- SubChunk2ID = "data"
- SubChunk2Size =
- #endif
- //parse the wave file
- bool ParseWaveFile(const string wavepath,Alsa_Conf* palsaCfg,FILE** fp)
- {
- ;
- //FILE* fp=NULL;
- *fp=fopen(wavepath.c_str(),"rb");
- if(*fp==NULL)
- {
- cout<<"Can parse the wave file-->need check the file name"<<endl;
- }
- /*********************size info parse begin*************************/
- //read size info
- Wave_Header_Size_Info_t wav_size_info;
- memset(&wav_size_info,,sizeof(Wave_Header_Size_Info_t));
- ret=fread(&wav_size_info,,*fp);
- )
- {
- cout<<"read error"<<endl;
- return false;
- }
- string ChunkID="";
- ;i<;i++)
- {
- ChunkID+=wav_size_info.ChunkID[i];
- }
- string riff="RIFF";
- !=strcmp(ChunkID.c_str(),riff.c_str()))
- {
- cout<<"Invalid the fist Chunk id"<<endl;
- return false;
- }
- uint16 ChunkSize=HandleLittleEndian(wav_size_info.ChunkSize,);
- cout<<"The ChunSize is "<<ChunkSize<<endl;
- string Format="";
- ;i<;i++)
- {
- Format+=wav_size_info.Format[i];
- }
- !=strcmp(Format.c_str(),"WAVE"))
- {
- cout<<"Invalid the format"<<endl;
- return false;
- }
- string SubChunk1ID="";
- ;i<;i++)
- {
- SubChunk1ID+=wav_size_info.SubChunk1ID[i];
- }
- string fmt="fmt ";
- !=strcmp(SubChunk1ID.c_str(),fmt.c_str()))
- {
- cout<<"Invalid the SubChunk1ID "<<endl;
- return false;
- }
- uint16 SubChunk1Size=HandleLittleEndian(wav_size_info.SubChunk1Size,);
- && SubChunk1Size!=)
- {
- cout<<"Invalid the SubChunk1Size"<<endl;
- return false;
- }
- /*********************Audio info parse begin*************************/
- Wave_Header_Audio_Info_t wav_audio_info;
- memset(&wav_audio_info,,sizeof(Wave_Header_Audio_Info_t));
- ret=fread(&wav_audio_info,,*fp);
- )
- {
- cout<<"read error"<<endl;
- return false;
- }
- //fseek(fp,sizeof(Wave_Header_Size_Info_t),0);//文件指针偏移3个字节到'2' because fread will shift the pointer
- uint16 AudioFormat =HandleLittleEndian(wav_audio_info.AudioFormat,);
- uint16 NumChannels =HandleLittleEndian(wav_audio_info.NumChannels,);
- uint16 SampleRate =HandleLittleEndian(wav_audio_info.SampleRate,);
- uint16 ByteRate =HandleLittleEndian(wav_audio_info.ByteRate,);
- uint16 BlockAlign =HandleLittleEndian(wav_audio_info.BlockAlign,);
- uint16 BitsPerSample=HandleLittleEndian(wav_audio_info.BitsPerSample,);
- palsaCfg->numOfChannels=(ENumOfChannels)NumChannels;
- palsaCfg->samplingFrequency=SampleRate;
- palsaCfg->bitsPerSample=(EBitsPerSample)BitsPerSample;
- /*********************Additional info parse begin if needed*************************/
- )
- {
- Wave_Header_Additional_Info_t wav_additional_info;
- memset(&wav_additional_info,,sizeof(Wave_Header_Additional_Info_t));
- fread(&wav_additional_info,,*fp);
- cout<<"read wav_additional_info"<<endl;
- )
- {
- cout<<"read error"<<endl;
- return false;
- }
- uint16 AdditionalInfo=HandleLittleEndian(wav_additional_info.AdditionalInfo_2Bytes,);
- cout<<"read AdditionalInfo value="<<AdditionalInfo<<endl;
- }
- /*********************Data info parse begin *************************/
- Wave_Header_Data_Info_t wave_data_info;
- memset(&wave_data_info,,sizeof(Wave_Header_Data_Info_t));
- fread(&wave_data_info,,*fp);
- )
- {
- cout<<"read error"<<endl;
- return false;
- }
- string SubChunk2ID="";
- ;i<;i++)
- {
- SubChunk2ID+=wave_data_info.SubChunk2ID[i];
- }
- string fact="fact";
- string data="data";
- ==strcmp(SubChunk2ID.c_str(),fact.c_str()))
- {
- cout<<"SubChunk2ID fact"<<endl;
- }
- ==strcmp(SubChunk2ID.c_str(),data.c_str()))
- {
- cout<<"SubChunk2ID data"<<endl;
- }
- else
- {
- cout<<"Invalid SubChunk2ID "<<endl;
- return false;
- }
- uint16 SubChunk2Size=HandleLittleEndian(wave_data_info.SubChunk2Size,);
- cout<<"End Parse"<<endl;
- return true;
- }
- bool PlayWave(FILE** fp,snd_pcm_t** phandler,Alsa_Conf* palsaCfg)
- {
- ;
- bool ret=false;
- snd_pcm_uframes_t frames=palsaCfg->alsaPeriodFrame;
- ; //4bytes
- uint16 audio_data_size=frames*bytesPerFrame;//one period 10ms ,1600*10/1000*(2*16/8)=640bytes one period
- uint8* buffer=new uint8[audio_data_size];
- cout<<"Start play wave"<<endl;
- if(*fp==NULL || *phandler==NULL || palsaCfg==NULL)
- {
- cout<<"End play wave because something is NULL"<<endl;
- return false;
- }
- //fseek(*fp,46,SEEK_SET); //no need to do fseek because already shifted
- cout<<"available frame "<<snd_pcm_avail(*phandler)<<"my frames is "<<frames<<endl;
- while(true)
- {
- if(feof(*fp))
- {
- cout<<"Reach end of the file"<<endl;
- break;
- }
- else
- {
- if(snd_pcm_avail(*phandler)<frames)
- {
- continue;
- }
- else
- {
- memset(reinterpret_cast<,sizeof(uint8)*audio_data_size);
- err=fread(buffer,,*fp);
- )
- {
- cout<<"read error"<<endl;
- }
- if ( NULL != buffer )
- {
- err = snd_pcm_writei(*phandler, buffer, frames);
- )
- {
- cout<<"Fail to write the audio data to ALSA. Reason: "<<(snd_strerror(err));
- // recover ALSA device
- err = snd_pcm_recover(*phandler, err, );
- )
- {
- cout<<"Fail to recover ALSA device. Reason: "<<(snd_strerror(err));
- ret = false;
- }
- else
- {
- cout<<"ALSA device is recovered from error state"<<endl;
- }
- }
- }
- else
- {
- cout<<"Write buffer is NULL!"<<endl;
- }
- }
- }
- usleep(palsaCfg->alsaCapturePeriod / ( * ));
- }
- delete[] buffer;
- buffer=NULL;
- return ret;
- }
- bool PrepareAlsaDevice(Alsa_Conf* palsaCfg,snd_pcm_t** phandler)
- {
- bool ret=false;
- bool success=true;
- ;
- snd_pcm_format_t format;
- snd_pcm_hw_params_t *hw_params = NULL;
- ;
- if(palsaCfg!=NULL)
- {
- // open ALSA device
- error=snd_pcm_open(phandler,palsaCfg->alsaDevice.c_str(),palsaCfg->streamType,palsaCfg->block? :SND_PCM_NONBLOCK);
- ) //0 on success otherwise a negative error code
- {
- success=false;
- cout<<"Open Alsadevice error error code="<<snd_strerror(error)<<endl;
- }
- if(success)
- {
- //allocate hardware parameter structur
- error=snd_pcm_hw_params_malloc(&hw_params);//alsao can use snd_pcm_hw_params_alloca(&hwparams)
- )
- {
- success=false;
- hw_params=NULL;
- cout<<"Set hw params error error code="<<snd_strerror(error)<<endl;
- }
- }
- if(success)
- {
- //Fill params with a full configuration space for a PCM. initialize the hardware parameter
- error=snd_pcm_hw_params_any(*phandler,hw_params);
- )
- {
- success=false;
- cout<<"Broken configuration for PCM: no configurations available: "<<snd_strerror(error)<<endl;
- }
- }
- if(success)
- {
- // set the access type
- error = snd_pcm_hw_params_set_access(*phandler, hw_params, palsaCfg->accessType);
- )
- {
- cout<<"[SG]Fail to set access type. Reason: "<<snd_strerror(error)<<endl;
- success = false;
- }
- }
- if(success)
- {
- switch (palsaCfg->bitsPerSample)
- {
- case BITS_PER_SAMPLE_8:
- {
- format = SND_PCM_FORMAT_U8;
- break;
- }
- case BITS_PER_SAMPLE_16:
- {
- format = SND_PCM_FORMAT_S16_LE; //indicate this was little endian
- break;
- }
- case BITS_PER_SAMPLE_32:
- {
- format = SND_PCM_FORMAT_S32_LE;
- break;
- }
- default:
- {
- format = SND_PCM_FORMAT_S16_LE;
- cout<<"Invalid format"<<endl;
- success=false;
- }
- }
- if(success)
- {
- error=snd_pcm_hw_params_set_format(*phandler,hw_params,format);
- )
- {
- cout<<"set format not available for "<<snd_strerror(error)<<endl;
- success=false;
- }
- }
- }
- if(success)
- {
- error=snd_pcm_hw_params_set_rate_near(*phandler,hw_params,&palsaCfg->samplingFrequency,);
- )
- {
- cout<<"set rate not available for "<<snd_strerror(error)<<endl;
- success=false;
- }
- }
- if(success)
- {
- error=snd_pcm_hw_params_set_channels(*phandler,hw_params,palsaCfg->numOfChannels);
- )
- {
- cout<<"set_channels not available for "<<snd_strerror(error)<<endl;
- success=false;
- }
- }
- if (success)
- {
- // set period size (period size is also a chunk size for reading from ALSA)
- snd_pcm_uframes_t alsaPeriodFrame = static_cast<snd_pcm_uframes_t>(palsaCfg->alsaPeriodFrame); // One frame could be 4 bytes at most
- // set period size
- error = snd_pcm_hw_params_set_period_size_near(*phandler, hw_params, &alsaPeriodFrame, &dir);
- )
- {
- cout<<"[SG]Fail to set period size. Reason: "<<snd_strerror(error)<<endl;
- success = false;
- }
- }
- if (success)
- {
- // set hardware parameters
- error = snd_pcm_hw_params(*phandler, hw_params);
- )
- {
- cout<<"[SG]Fail to set hardware parameter. Reason: "<<snd_strerror(error)<<endl;
- success = false;
- }
- }
- if (success)
- {
- error=snd_pcm_hw_params_get_period_size(hw_params, &g_frames, &dir); //get frame
- cout<<"Frame is "<<g_frames<<endl;
- // free the memory for hardware parameter structure
- snd_pcm_hw_params_free(hw_params);
- hw_params = NULL;
- // Prepare ALSA device
- error = snd_pcm_prepare(*phandler);
- )
- {
- cout<<"Fail to prepare ALSA device. Reason: "<<(snd_strerror(error))<<endl;
- success = false;
- }
- }
- if (success)
- {
- cout<<"ALSA device is ready to use"<<endl;
- }
- else
- {
- // fail to prepare ALSA device ==> un-initialize ALSA device
- if (hw_params != NULL)
- {
- snd_pcm_hw_params_free(hw_params);
- hw_params = NULL;
- }
- closeAlsaDevice(phandler);
- }
- }
- return success;
- }
- bool closeAlsaDevice(snd_pcm_t** phandler)
- {
- bool ret = true;
- snd_pcm_state_t state;
- int snd_ret;
- if (*phandler != NULL)
- {
- // drop the pending audio frame if needed
- state = snd_pcm_state(*phandler);
- cout<<"Alsa handler sate: "<<state<<endl;
- if ((SND_PCM_STATE_RUNNING == state) || (SND_PCM_STATE_XRUN == state) || (SND_PCM_STATE_SUSPENDED == state))
- {
- snd_ret = snd_pcm_drop(*phandler);
- )
- {
- cout<<"Fail to drop ALSA device. Reason: "<<(snd_strerror(snd_ret))<<endl;
- }
- }
- // close ALSA handler
- snd_ret = snd_pcm_close(*phandler);
- )
- {
- cout<<"Fail to close ALSA device. Reason: "<<(snd_strerror(snd_ret))<<endl;
- ret = false;
- }
- *phandler = NULL;
- cout<<"CLOSE ALSA DEVICE"<<endl;
- }
- return ret;
- }
- int main()
- {
- bool ret=false;
- snd_pcm_t* m_phandler=NULL;
- Alsa_Conf* m_palsaCfg=new Alsa_Conf();
- m_palsaCfg->alsaDevice = string("sd_out_16k");
- //m_palsaCfg->samplingFrequency = 16000;
- m_palsaCfg->alsaCapturePeriod = ;
- //m_palsaCfg->numOfChannels = NUM_OF_CHANNELS_1;
- m_palsaCfg->block = true; //block
- m_palsaCfg->friendlyName = "AlsaWave";
- //m_palsaCfg->bitsPerSample = BITS_PER_SAMPLE_16;
- m_palsaCfg->alsaPeriodFrame = m_palsaCfg->samplingFrequency * m_palsaCfg->alsaCapturePeriod / ; // calculate the number of frame in one period
- m_palsaCfg->alsaBufferSize = m_palsaCfg->alsaPeriodFrame * ; //means the whole buffer was perdion*8, e.g. 10ms means every 10ms we will get/send the data
- m_palsaCfg->accessType = SND_PCM_ACCESS_RW_INTERLEAVED;
- m_palsaCfg->streamType = SND_PCM_STREAM_PLAYBACK;
- FILE* fp=NULL;
- const string wavePath="/mnt/hgfs/0_SharedFolder/0_Local_Test_Folder/01_TestFolder/TestALSA/left_1k_right_400hz.wav";
- //parse the wave file
- ret=ParseWaveFile(wavePath,m_palsaCfg,&fp);
- //update the value
- m_palsaCfg->alsaPeriodFrame = m_palsaCfg->samplingFrequency * m_palsaCfg->alsaCapturePeriod / ; // calculate the number of frame in one period
- if(ret)
- {
- //open alsa device
- ret=PrepareAlsaDevice(m_palsaCfg,&m_phandler);
- }
- if(ret)
- {
- PlayWave(&fp,&m_phandler,m_palsaCfg);
- }
- closeAlsaDevice(&m_phandler);
- if(fp!=NULL)
- {
- fclose(fp);
- fp=NULL;
- }
- delete m_palsaCfg;
- m_palsaCfg=NULL;
- ;
- }
Alsa 读取wave文件,并播放wave 文件的更多相关文章
- 读取SD卡文件夹下的MP3文件和播放MP3文件
首先获取SD卡path路径下的所有的MP3文件,并将文件名和文件大小存入List数组(此代码定义在FileUtils类中): /** * 读取目录中的Mp3文件的名字和大小 */ public Lis ...
- Linux音频编程--使用ALSA库播放wav文件
在UBUNTU系统上使用alsa库完成了对外播放的wav文件的案例. 案例代码: /** *test.c * *注意:这个例子在Ubuntu 12.04.1环境下编译运行成功. * */ #inclu ...
- Opencv 播放mp4文件和读取摄像头图以及可能会发生的一些异常问题解决方法
学习内容 学习Opencv 读取并播放本地视频和打开摄像头图像以及可能会发生的一些异常问题解决方法 代码演示 电脑环境信息: OpenCV版本:4.5.2 ,vs2017 1.视频文件读取与播放 加载 ...
- python 播放 wav 文件
未使用其他库, 只是使用 pywin32 调用系统底层 API 播放 wav 文件. # Our raison d'etre - playing sounds import pywintypes im ...
- 【转】C# 视频监控系列(12):H264播放器——播放录像文件
原文地址:http://www.cnblogs.com/over140/archive/2009/03/23/1419643.html?spm=5176.100239.blogcont51182.16 ...
- VC++中MCI播放音频文件 【转】
MCI播放mp3音频文件例程 源文件中需要包含头文件 Mmsystem.h,在Project->Settings->Link->Object/libray module中加入库 Wi ...
- 如何播放 WAV 文件?
from http://www.vckbase.com/index.php/wv/434 平时,你在多媒体软件的设计中是怎样处理声音文件的呢?使用Windows 提供的API函数 sndPlaySou ...
- ffmpeg和opencv 播放视频文件和显示器
ffmpeg它是基于最新版本,在官网下载http://ffmpeg.zeranoe.com/builds/.编译时VS2010配置相关头文件及库的路径就可以.opencv的搭建參考上一个博客. 首先简 ...
- STM32音乐播放器,文件查找的实现
使用FATFS只是完成了一个基本的文件读写,有时候我们需要扩展一些功能,比如MP3实验,需要上一曲下一曲的切换,扩展的代码如下 //显示目录下所有文件 u8 ShowFileList(u8* dirP ...
- Qt 播放音频文件
Qt播放音频文件的方法有好多中,简单介绍几种 不过一下几种方式都需要在Qt工程文件中添加 QT += multimedia 第一 QMediaPlayer类 可以播放MP3文件,同时使用也 ...
随机推荐
- 自动部署Nginx和nfs并架设Nginx集群脚本
本人经过多次尝试,简单完成了自动部署Nginx和nfs脚本,并且能够自动部署web反向代理集群,下面详细的阐述一下本人的思路.(以下脚本本人处于初学阶段,写的并不是很完善,所以需要后期进行整理和修正, ...
- React文档翻译系列(三)JSX简介
# React文档翻译系列(三)JSX简介 先来看一下下面的变量声明: ``` const element = Hello world! ``` 这种有趣的标签语法既不是字符串也不是HTML. 这种形 ...
- 重温Javascript(四)-函数
函数 函数声明提升,在执行代码之前会先读取函数声明 sayHi(); function sayHi(){ alert("Hi!"); } 递归 arguments.callee是指 ...
- Python之路-Linux命令基础(3)
作业一: 1)将用户信息数据库文件和组信息数据库文件纵向合并为一个文件/1.txt(覆盖) 2)将用户信息数据库文件和用户密码数据库文件纵向合并为一个文件/2.txt(追加) 3)将/1.txt./2 ...
- Struts 2 实现登录以及显示信息
---恢复内容开始--- 这个星期主要做了一个项目的开始,基于开始学习Struts2的框架首先要先做好Action的按钮 这是我一个Action的展示,chain中是把一个数据带着去跳转另一个网页中 ...
- 应用程序写Xml文档
主要用到CreateElement.CreateTextNode.CreateComment.AppendChild.InsertAfter方法 代码如下: XmlDocument document ...
- select下拉二级联动
function opt(){ var id = $("#ids").val(); $.ajax({ type: "POST", url: "$ ...
- MongoDB数据库安装及配置环境终极教程(windows10系统)
本文是笔者花时间踩坑踩生气了写出来的!转载请注明出处@http://www.cnblogs.com/tim100/!请尊重我的劳动成果!谢谢! 今天,给大家说说在windows10系统下MongoDB ...
- sql解析xml
我们有时候需要在sql中解析xml,xml解析sql实例如下: DECLARE @params xml DECLARE @customparams xml = null -- 0.解析输入参数 ...
- Jquery Validation 验证控件的使用说明
转载自:http://blog.csdn.net/huang100qi/article/details/52453970,做了一些简化及修改 下载地址:https://jqueryvalidation ...