对于一个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 文件的更多相关文章

  1. 读取SD卡文件夹下的MP3文件和播放MP3文件

    首先获取SD卡path路径下的所有的MP3文件,并将文件名和文件大小存入List数组(此代码定义在FileUtils类中): /** * 读取目录中的Mp3文件的名字和大小 */ public Lis ...

  2. Linux音频编程--使用ALSA库播放wav文件

    在UBUNTU系统上使用alsa库完成了对外播放的wav文件的案例. 案例代码: /** *test.c * *注意:这个例子在Ubuntu 12.04.1环境下编译运行成功. * */ #inclu ...

  3. Opencv 播放mp4文件和读取摄像头图以及可能会发生的一些异常问题解决方法

    学习内容 学习Opencv 读取并播放本地视频和打开摄像头图像以及可能会发生的一些异常问题解决方法 代码演示 电脑环境信息: OpenCV版本:4.5.2 ,vs2017 1.视频文件读取与播放 加载 ...

  4. python 播放 wav 文件

    未使用其他库, 只是使用 pywin32 调用系统底层 API 播放 wav 文件. # Our raison d'etre - playing sounds import pywintypes im ...

  5. 【转】C# 视频监控系列(12):H264播放器——播放录像文件

    原文地址:http://www.cnblogs.com/over140/archive/2009/03/23/1419643.html?spm=5176.100239.blogcont51182.16 ...

  6. VC++中MCI播放音频文件 【转】

    MCI播放mp3音频文件例程 源文件中需要包含头文件 Mmsystem.h,在Project->Settings->Link->Object/libray module中加入库 Wi ...

  7. 如何播放 WAV 文件?

    from http://www.vckbase.com/index.php/wv/434 平时,你在多媒体软件的设计中是怎样处理声音文件的呢?使用Windows 提供的API函数 sndPlaySou ...

  8. ffmpeg和opencv 播放视频文件和显示器

    ffmpeg它是基于最新版本,在官网下载http://ffmpeg.zeranoe.com/builds/.编译时VS2010配置相关头文件及库的路径就可以.opencv的搭建參考上一个博客. 首先简 ...

  9. STM32音乐播放器,文件查找的实现

    使用FATFS只是完成了一个基本的文件读写,有时候我们需要扩展一些功能,比如MP3实验,需要上一曲下一曲的切换,扩展的代码如下 //显示目录下所有文件 u8 ShowFileList(u8* dirP ...

  10. Qt 播放音频文件

    Qt播放音频文件的方法有好多中,简单介绍几种 不过一下几种方式都需要在Qt工程文件中添加 QT       += multimedia 第一 QMediaPlayer类 可以播放MP3文件,同时使用也 ...

随机推荐

  1. 在TFS中通过程序动态创建Bug并感知Bug解决状态

    为便于跟踪问题解决情况,预警引擎产生的比较严重的预警日志,需要在TFS中登记Bug,通过TFS的状态流转,利用TFS Bug的Web挂钩功能,动态感知Bug解决状态,从而跟踪预警问题的解决状态, 整体 ...

  2. Omi新成员omi-router正式发布

    原文链接-https://github.com/AlloyTeam/omi/blob/master/tutorial omi-router omi-router是Omi框架专属的router插件,文件 ...

  3. 使用nginx代理kibana并设置身份验证

    1.在es-sever上安装nginx #wget http://nginx.org/download/nginx-1.8.1.tar.gz #tar xvf nginx-1.8.1.tar.gz # ...

  4. JDK中日期和时间的几个常用类浅析(四)

    java.time.Instant   java.time.Instant类对应的是时间线上的一个时间点.该类通过保存着从格林威治的起始时间(1970年一月一日零点零分)开始计算所经过的纳妙数来表示时 ...

  5. python之列表作为函数的参数

    函数参数为 列表或者字典 传递一个列表,例如 [1, 2, 3] 将此传给函数get_sum() 求出 各个元素之和 传递一个字典,打印出key/value的对应关系表: #!/usr/bin/env ...

  6. 老李分享:HTTP协议之协议头

    老李分享:HTTP协议之协议头   当我们打开一个网页时,浏览器要向网站服务器发送一个HTTP请求头,然后网站服务器根据HTTP请求头的内容生成当次请求的内容发送给浏览器.你明白HTTP请求头的具体含 ...

  7. 微信小程序省市联动

    最近呢刚好做了一个省市联动的功能,今天看到有人问这个怎么做,我就把我做的放上来共享一下: 首先呢,来看看效果,点击文字'点击',弹出选择窗口,点击取消或者确定(取消.确定按钮在选择框上边,截图有些不清 ...

  8. 基于Spring Security 的JSaaS应用的权限管理

    1. 概述 权限管理,一般指根据系统设置的安全规则或者安全策略,用户可以访问而且只能访问自己被授权的资源.资源包括访问的页面,访问的数据等,这在传统的应用系统中比较常见.本文介绍的则是基于Saas系统 ...

  9. 关于block使用的几点注意事项

    1.在使用block前需要对block指针做判空处理. 不判空直接使用,一旦指针为空直接产生崩溃. if (!self.isOnlyNet) { if (succBlock == NULL) { // ...

  10. Servlet(一)基础总结

    一.Servlet概述 1.Java Servlet是基于Java的一种技术和标准,是独立于平台和协议,服务器端的java应用程序.与Applet相比.Applet运行在客户端,而Servlet运行在 ...