场景
fopen函数还是fstream类对象中的open函数在打开文件时,没有指定任何的打开方式,保存的视频流无法播放。使用Elecard StreamEye Tools查看视频流的时候,MB窗口显示:incorrect block info。使用VLC播放,花屏。
原因
在Unix或者Linux系统中,没有文本方式和二进制方式。Unix文本文件的换行符只有一个字节LF(0x0A)为。在C语言中,也是以LF即'\n'为换行符。 在DOS和Windows系统中使用CRLF(0x0D
0x0A)即\r\n双字节作为文本文件换行符。在以文本方式下,在读文件时,会将换行符号CRLF(0x0D0x0A)全部转换成单个的0x0A,并且当遇到结束符CTRLZ(0x1A)时,就认为文件已经结束。相应的,写文件时,会将所有的0x0A换成0x0D0x0A。因此如果以文本方式读写文件,会造成文件读取不完整,写文件内容添加多余的0x0D字符。
提供一份将视频中的0x0D0x0A中的多余字节0x0D删除的代码段
#include <iostream>
#include <fstream>
#include <string>
int main()
{
std::ifstream ifstreamHandle;
ifstreamHandle.open("F:/video.h264", std::ifstream::in | std::ifstream::binary);
ifstreamHandle.seekg(0, std::ios::end);
int nFileLen = ifstreamHandle.tellg();
ifstreamHandle.seekg(0, std::ios::beg);
char* pszReadBuffer = new char[nFileLen];
memset(pszReadBuffer, 0x00, nFileLen);
ifstreamHandle.read(pszReadBuffer, nFileLen);
ifstreamHandle.close();
std::ofstream ofstreamHanle;
ofstreamHanle.open("F:/videoOutput.h264", std::ofstream::out | std::ofstream::binary);
for (int i = 1; i < nFileLen; i++)
{
if ((0x0d == pszReadBuffer[i - 1]) && (0x0a == pszReadBuffer[i]))
{
//还有多余的0x0d字符,不写文件
}
else
{
ofstreamHanle << pszReadBuffer[i-1];
}
}
//将最后一个字节写文件
ofstreamHanle << pszReadBuffer[nFileLen - 1];
ofstreamHanle.close();
delete pszReadBuffer;
}