此文已由作者郑博授权网易云社区发布。

欢迎访问网易云社区,了解更多网易技术产品运营经验

#endif  // _WIN32
}class FileStream::FileStreamPrivate
{
public:FileStreamPrivate(const FileName &fileName): file(InvalidFileHandle), name(fileName), readOnly(true){}FileHandle file;FileNameHandle name;bool readOnly;
};// public membersFileStream::FileStream(FileName fileName, bool openReadOnly): d(new FileStreamPrivate(fileName))
{// First try with read / write mode, if that fails, fall back to read only.if(!openReadOnly)d->file = openFile(fileName, false);if(d->file != InvalidFileHandle)d->readOnly = false;elsed->file = openFile(fileName, true);if(d->file == InvalidFileHandle){
# ifdef _WIN32debug("Could not open file " + fileName.toString());
# elsedebug("Could not open file " + String(static_cast(d->name)));
# endif}
}FileStream::~FileStream()
{if(isOpen())closeFile(d->file);delete d;
}FileName FileStream::name() const
{return d->name;
}ByteVector FileStream::readBlock(ulong length)
{if(!isOpen()) {debug("FileStream::readBlock() -- invalid file.");return ByteVector::null;}if(length == 0)return ByteVector::null;const ulong streamLength = static_cast(FileStream::length());if(length > bufferSize() && length > streamLength)length = streamLength;ByteVector buffer(static_cast(length));const size_t count = readFile(d->file, buffer);buffer.resize(static_cast(count));return buffer;
}void FileStream::writeBlock(const ByteVector &data)
{if(!isOpen()) {debug("FileStream::writeBlock() -- invalid file.");return;}if(readOnly()) {debug("FileStream::writeBlock() -- read only file.");return;}writeFile(d->file, data);
}void FileStream::insert(const ByteVector &data, ulong start, ulong replace)
{if(!isOpen()) {debug("FileStream::insert() -- invalid file.");return;}if(readOnly()) {debug("FileStream::insert() -- read only file.");return;}if(data.size() == replace) {seek(start);writeBlock(data);return;}else if(data.size() < replace) {seek(start);writeBlock(data);removeBlock(start + data.size(), replace - data.size());return;}// Woohoo!  Faster (about 20%) than id3lib at last.  I had to get hardcore// and avoid TagLib's high level API for rendering just copying parts of// the file that don't contain tag data.//// Now I'll explain the steps in this ugliness:// First, make sure that we're working with a buffer that is longer than// the *differnce* in the tag sizes.  We want to avoid overwriting parts// that aren't yet in memory, so this is necessary.ulong bufferLength = bufferSize();while(data.size() - replace > bufferLength)bufferLength += bufferSize();// Set where to start the reading and writing.long readPosition = start + replace;long writePosition = start;ByteVector buffer = data;ByteVector aboutToOverwrite(static_cast(bufferLength));while(true){// Seek to the current read position and read the data that we're about// to overwrite.  Appropriately increment the readPosition.seek(readPosition);const size_t bytesRead = readFile(d->file, aboutToOverwrite);aboutToOverwrite.resize(bytesRead);readPosition += bufferLength;// Check to see if we just read the last block.  We need to call clear()// if we did so that the last write succeeds.if(bytesRead < bufferLength)clear();// Seek to the write position and write our buffer.  Increment the// writePosition.seek(writePosition);writeBlock(buffer);// We hit the end of the file.if(bytesRead == 0)break;writePosition += buffer.size();// Make the current buffer the data that we read in the beginning.buffer = aboutToOverwrite;}
}void FileStream::removeBlock(ulong start, ulong length)
{if(!isOpen()) {debug("FileStream::removeBlock() -- invalid file.");return;}ulong bufferLength = bufferSize();long readPosition = start + length;long writePosition = start;ByteVector buffer(static_cast(bufferLength));for(size_t bytesRead = -1; bytesRead != 0;){seek(readPosition);bytesRead = readFile(d->file, buffer);readPosition += bytesRead;// Check to see if we just read the last block.  We need to call clear()// if we did so that the last write succeeds.if(bytesRead < buffer.size()) {clear();buffer.resize(bytesRead);}seek(writePosition);writeFile(d->file, buffer);writePosition += bytesRead;}truncate(writePosition);
}bool FileStream::readOnly() const
{return d->readOnly;
}bool FileStream::isOpen() const
{return (d->file != InvalidFileHandle);
}void FileStream::seek(long offset, Position p)
{if(!isOpen()) {debug("FileStream::seek() -- invalid file.");return;}#ifdef _WIN32DWORD whence;switch(p) {case Beginning:whence = FILE_BEGIN;break;case Current:whence = FILE_CURRENT;break;case End:whence = FILE_END;break;default:debug("FileStream::seek() -- Invalid Position value.");return;}#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM)LARGE_INTEGER distance = { 0 };distance.QuadPart = offset;if (!SetFilePointerEx(d->file, distance, NULL, whence))
#elseSetLastError(NO_ERROR);SetFilePointer(d->file, offset, NULL, whence);const int lastError = GetLastError();if(lastError != NO_ERROR && lastError != ERROR_NEGATIVE_SEEK)
#endifdebug("FileStream::seek() -- Failed to set the file pointer.");#elseint whence;switch(p) {case Beginning:whence = SEEK_SET;break;case Current:whence = SEEK_CUR;break;case End:whence = SEEK_END;break;default:debug("FileStream::seek() -- Invalid Position value.");return;}fseek(d->file, offset, whence);#endif
}void FileStream::clear()
{
#ifdef _WIN32// NOP#elseclearerr(d->file);#endif
}long FileStream::tell() const
{
#ifdef _WIN32#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM)LARGE_INTEGER distance = { 0 };LARGE_INTEGER position = { 0 };if (SetFilePointerEx(d->file, distance, &position, FILE_CURRENT)) {return static_cast(position.QuadPart);}
#elseSetLastError(NO_ERROR);const DWORD position = SetFilePointer(d->file, 0, NULL, FILE_CURRENT);if(GetLastError() == NO_ERROR) {return static_cast(position);}
#endifelse {debug("FileStream::tell() -- Failed to get the file pointer.");return 0;}#elsereturn ftell(d->file);#endif
}long FileStream::length()
{if(!isOpen()) {debug("FileStream::length() -- invalid file.");return 0;}#ifdef _WIN32#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM)LARGE_INTEGER fileSize = { 0 };if (GetFileSizeEx(d->file, &fileSize)) {return static_cast(fileSize.QuadPart);}
#elseSetLastError(NO_ERROR);const DWORD fileSize = GetFileSize(d->file, NULL);if (GetLastError() == NO_ERROR) {return static_cast(fileSize);}
#endifelse {debug("FileStream::length() -- Failed to get the file size.");return 0;}#elseconst long curpos = tell();seek(0, End);const long endpos = tell();seek(curpos, Beginning);return endpos;#endif
}// protected membersvoid FileStream::truncate(long length)
{
#ifdef _WIN32const long currentPos = tell();seek(length);SetLastError(NO_ERROR);SetEndOfFile(d->file);if(GetLastError() != NO_ERROR) {debug("FileStream::truncate() -- Failed to truncate the file.");}seek(currentPos);#elseconst int error = ftruncate(fileno(d->file), length);if(error != 0) {debug("FileStream::truncate() -- Coundn't truncate the file.");}#endif
}TagLib::uint FileStream::bufferSize()
{return 1024;
}

为了便于调试,还需要修改taglib\toolkit\tdebuglistener.cpp,以便在调试直接在Output窗口输出调试信息,完整代码如下:

/***************************************************************************copyright            : (C) 2013 by Tsuda Kageyuemail                : tsuda.kageyu@gmail.com***************************************************************************//****************************************************************************   This library is free software; you can redistribute it and/or modify  **   it under the terms of the GNU Lesser General Public License version   **   2.1 as published by the Free Software Foundation.                     **                                                                         **   This library is distributed in the hope that it will be useful, but   **   WITHOUT ANY WARRANTY; without even the implied warranty of            **   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     **   Lesser General Public License for more details.                       **                                                                         **   You should have received a copy of the GNU Lesser General Public      **   License along with this library; if not, write to the Free Software   **   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA         **   02110-1301  USA                                                       **                                                                         **   Alternatively, this file is available under the Mozilla Public        **   License Version 1.1.  You may obtain a copy of the License at         **   http://www.mozilla.org/MPL/                                           ****************************************************************************/#include "tdebuglistener.h"#include
#include #ifdef _WIN32
# include
#endifusing namespace TagLib;namespace
{class DefaultListener : public DebugListener{public:virtual void printMessage(const String &msg){
#ifdef _WIN32const wstring wstr = msg.toWString();
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM)OutputDebugStringW(wstr.c_str());
#elseconst int len = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, NULL, 0, NULL, NULL);if(len != 0) {std::vector buf(len);WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, &buf[0], len, NULL, NULL);std::cerr << std::string(&buf[0]);}
#endif#elsestd::cerr << msg;#endif }};DefaultListener defaultListener;
}namespace TagLib
{DebugListener *debugListener = &defaultListener;DebugListener::DebugListener(){}DebugListener::~DebugListener(){}void setDebugListener(DebugListener *listener){if(listener)debugListener = listener;elsedebugListener = &defaultListener;}
}

最后,编译吧,骚年!!!

免费领取验证码、内容安全、短信发送、直播点播体验包及云服务器等套餐

更多网易技术、产品、运营经验分享请点击。

相关文章:
【推荐】 Spring Boot 学习系列(11)—tomcat参数配置建

UWP平台Taglib编译(2)相关推荐

  1. UWP平台Taglib编译(1)

    此文已由作者郑博授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验 最近开始开发UWP平台的App,项目需要用到Taglib进行音视频文件的标签信息读写,Google并没有现成的B ...

  2. 为什么unity 安装完模块还是找不到sdk_Unity填坑笔记(四)——移植UWP平台

    0. 絮絮念 本来不想写这篇文章,一来做完这一波之后我再也不想做WSA平台--二来我觉得会做这个平台的人并不多,所以写下来意义也不大.不过在移植过程中ToLua的作者蒙哥给了我不少帮助,也说断断续续有 ...

  3. mysql windows编译_Windows平台下编译Mysql源码 | 学步园

    最近由于项目的关系,需要使用到Mysql数据库,而我的工作任务与数据库有很大的关系,所以,决定好好学学Mysql,同时,也把Mysql的源码下载了,希望能有利于对它的学习.这里记录一下windows平 ...

  4. windows平台下载编译好的webrtc代码vs2015

    windows平台下载编译好的webrtc代码vs2015 编译好的源码工程地址:  https://github.com/hujianhua888/webrtc_vs2015,工程目录如下,包含所有 ...

  5. ubuntu平台下编译vlc-android视频播放器实践

    音视频实践学习 android全平台编译ffmpeg以及x264与fdk-aac实践 ubuntu下使用nginx和nginx-rtmp-module配置直播推流服务器 android全平台编译ffm ...

  6. 【Jpeg】不同平台如何编译 jpeg-turbo 库文件

    本文介绍不同平台下如何编译 jpeg-turbo 库文件. Mac/Linux 平台 Mac/Linux 平台编译 jpeg-turbo 库文件(libturbojpeg)的流程如下: 下载 jpeg ...

  7. 微软应用商店_微软:关于UWP平台,我们知道错了

    早些时候我们提到知名科技网站编辑保罗认为微软 UWP 已经游戏结束,接下来这个平台可能会因此而停滞. 不过针对这些传闻微软似乎从某些方面是认同的但是也有不同,不同的主要是微软暂时不会放弃 UWP 平台 ...

  8. UWP平台和PC平台有什么区别

    UWP平台和PC平台有什么区别 什么是UWP平台 定义不同 运行不同 起源不同 转载链接 什么是UWP平台     Universal Windows Platform(UWP)直译过来就是通用Win ...

  9. 使用VS在64位平台下编译代码,生成64位dll

    最近要把一个之前在32位平台下编译的项目改成64位平台,之前从来没搞过关于64位的东西,所以到处查资料,所幸搞成功了,把过程记录一下,防止以后忘记. 首先声明:64位平台无法直接调用32位dll,32 ...

最新文章

  1. 中学计算机课 打字教案,初中信息技术《打字练习—易语言应用》教案
  2. 浅析正则表达式模式匹配的 String 方法
  3. Android开发 - 解决DialogFragment在全屏时View被状态栏遮住的问题
  4. XCode 6 出现 no identity found: Command /usr/bin/codesign failed with exit code 1 解决方法汇总...
  5. MOCTF-Web-我想要钱
  6. groovy 字符串截取最后一个_python数据类型总结——数字和字符串
  7. 高性价比手持机有哪些
  8. linux 查看进程启动路径
  9. python查找字符串数量_python如何实现从字符串中找出字符1的位置以及个数的示例...
  10. C#判断检测网络是否连接
  11. 服务提供者框架讲解 之 myJDBC
  12. 京东云,走进产业数字化深处
  13. KubeCon 上海 SOFAStack Cloud Native Workshop 报名中
  14. RN Error: 无法获取此包的编译时间戳。请更新react-native-update到最新版本后重新打包上传。
  15. CentOS 6.8安装Docker V1.0
  16. SVG——入门,路径变形动画
  17. 20个国内Android平台移动应用市场
  18. 大学计算机学院操行表个人小结,大学生操行鉴定表个人总结
  19. 【通信系统仿真系列】基于Matlab的汉明码(Hamming Code)纠错传输以及交织编码(Interleaved coding)仿真
  20. nvidia jetson nano 操作指南

热门文章

  1. 阿里平头哥数字IC验证笔试题
  2. 让世界爱上中国原创!
  3. Esper-技术简介
  4. 天哪又要搬家啦qvq
  5. 光模块,光纤,linux
  6. 基于MATLAB的无人机遥感数据预处理与农林植被性状估算
  7. 给MYSQL账号充值的软件_MYSQL数据库指定数据库表给会员充值充值教程
  8. 连接池在java中的使用
  9. Docker学习笔记5——DockerFile(幕布笔记)
  10. jstl-sql使用