Xen 是一种开源的、属于类型1(裸金属虚拟化,Baremetal Hypervisor)的虚拟化技术,它使多个同样操作系统或不同操作系统的虚拟机运行在同一个物理主机节点上成为可能并实现。
Xen 是唯一的属于类型1(裸金属虚拟化,Baremetal Hypervisor)并且开源的虚拟化技术,它被作为商业应用或开源应用的基础而加以使用,如服务器虚拟化、Infrastructure as a service(Iaas)、桌面虚拟化、安全应用、嵌入式和硬件设备等。
Xen 虚拟化技术的关键特性:
1) 轻便小型的设计:核心代码有1MB左右,它使用了微小内核设计,占用极少内存,加上有限的接口设计,使得它比其他虚拟化技术更健壮、更安全。
2) 操作系统无关性:Domain0 一般安装在Linux 操作系统中,也可以使用其他操作系统代替。如NetBSD、OpenSolaris等。
3) 驱动分离:Xen 虚拟化技术允许主要的硬件设备驱动运行与虚拟机内部,当驱动出现 crash(宕机)或者报错时,包含该驱动的虚拟机可以重启,该驱动也可以重启,这样不会影响其他的虚拟机。
4) 半虚拟化技术:运行在半虚拟化技术上的虚拟机已经经过优化,它们可以运行得更加流畅,比运行在需要硬件扩展支持的全虚拟化管理程序(HVM)上的虚拟机更快。
Xen 虚拟化关键技术有3点(包括类型、Domain0、Toolstacks)
类型:Xen 虚拟机技术支持半虚拟化(Para-Virtualization,PV)和全虚拟化(Hardware-assisted Virtualization,HVM)两种类型。
Domain0:Xen 虚拟化架构中包含一个特殊的域(Domain0),其包括硬件设备驱动和控制虚拟机的Toolstack。
Toolstacks:其涵盖各种不同的Toolstack。
普及知识点:
裸金属虚拟化(Baremetal Hypervisor),类型1:该类型的虚拟化技术直接运行在物理主机节点硬件上设备上,并且管理虚拟机操作系统。
可托管的虚拟化(Hosted Hypervisor),类型2:该类型的虚拟化技术允许运行在普通的操作系统上,和普通的计算机程序类似。
Xen 架构的重点:
1) Xen 虚拟化管理程序是一个极小的软件程序,包含大概15万行代码。Xen 虚拟化管理程序本没有I/O功能。
2) 虚拟机是一个虚拟化的环境,每个虚拟机都运行着自己的操作系统和应用程序。Xen 支持两种虚拟化模式:半虚拟化和全虚拟化模式。在同一个虚拟化管理程序上可以同时并行使用两种虚拟化模式,也可以串行在全虚拟化模式上使用半虚拟化模式,以此保证半虚拟化和全虚拟化的连续性。虚拟机与硬件之间的完全隔离的,它们没有任何权限可以访问底层的硬件和I/O设备等,因此它们也被叫做DomainU(Unprivileged Domain)。
3) Domain0:是一个特殊的虚拟机,其具备特殊的、足够的权限直接访问底层的硬件设备,处理所有底层的I/O设备请求,并与其他虚拟机(DomainU)进行交互通信。Domain0对外部开放一个接口,使用户可以控制整个系统。没有Domain0,Xen 虚拟化管理程序是无法使用的,它是整个系统启动后加载的第一个虚拟机。
4) Toolstack:包含在Domain0中,也叫作控制栈,其允许用户管理虚拟机,包括虚拟机创建、删除和配置等。
5) 终端是Toolstack 对外部开放的一个接口,用户可以通过命令行或图形化界面控制整个系统,OpenStack 和CloudStack 中的编排服务也被支持。
6) Domain0 要求一个支持 Xen 虚拟化管理程序的内核,半虚拟化的虚拟机(DomainU)要求一个支持半虚拟化的内核。比较新的Linux 操作系统基本都支持,也包括Toolstack。
虚拟化类型
半虚拟化(PV):
半虚拟化是由 Xen 虚拟化管理程序引入的一个轻量级、高效的虚拟化模式,之后被其他虚拟化平台所被采用。半虚拟化不要求物理主机节点CPU具备扩展性,但是其需要支持半虚拟化的内核和驱动。因此,虚拟机能够感知到虚拟化管理程序;同时,因为没有硬件仿真,所以运行非常高效。支持半虚拟化的内核包括Linux、FreeBSD、NetBSD和OpenSolaris。
全虚拟化(HVM):
全虚拟化需要物理主机节点CPU扩展特性的支持,为此,Intel和AMD厂商提供了Intel VT和AMD-V技术。Xen 虚拟化管理程序使用QEMU 仿真硬件设备,包括BIOS、IDE磁盘控制器、VGA图形适配器、USB控制器和网络适配器等。硬件的扩展特性提高了仿真性能,同时,全虚拟化模式下的虚拟机不再需要特殊内核的支持,这也意味着Windows 操作系统在基于Xen全虚拟化的平台也是被支持的。一般情况下,半虚拟化的虚拟机比全虚拟化的虚拟机性能表现更好,因为全虚拟化的虚拟机需要硬件仿真,会消耗一部分性能。在某些情况下,可以使用半虚拟化驱动加速全虚拟化虚拟机的I/O性能。在Windows 虚拟机中,需要安装合适的虚拟化驱动。
vue-resource系列之request.headers.set设置的问题 为什么设置请求头的过程中出现了问题? 为什么设置请求头的过程中出现了问题? 问题如下:
Vue.http.interceptors.push((request, next) => { request.headers.set('lanId', 100); }) 项目运行的过程中,每个页面都会报如下错误:
后来在调试过程中才发现
设置这个方法会对字符串去除空格,而整数,没有这个方法。
有错就改掉:
Vue.http.interceptors.push((request, next) => { request.headers.set('lanId', ‘100’); })
不加密的视频
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:8
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:4,
/20180726/po0ip4HR/800kb/hls/x77F9N8626000.ts
#EXTINF:4,
/20180726/po0ip4HR/800kb/hls/x77F9N8626001.ts
#EXTINF:4,
/20180726/po0ip4HR/800kb/hls/x77F9N8626002.ts
#EXTINF:4,
/20180726/po0ip4HR/800kb/hls/x77F9N8626003.ts
#EXTINF:4,
/20180726/po0ip4HR/800kb/hls/x77F9N8626004.ts
#EXTINF:4,
/20180726/po0ip4HR/800kb/hls/x77F9N8626005.ts
#EXTINF:4,
/20180726/po0ip4HR/800kb/hls/x77F9N8626006.ts
#EXTINF:4,
/20180726/po0ip4HR/800kb/hls/x77F9N8626007.ts
#EXTINF:4,
…
…
#EXT-X-ENDLIST
加密的视频
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:302
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-KEY:METHOD=AES-128,URI=“http://192.168.10.200/item2/key.key”,IV=0xf23c8acc7bf326b866ca3dba4a39ccf9
#EXTINF:302.000000,
movie-0.ts
#EXTINF:300.000000,
movie-1.ts
#EXTINF:300.000000,
movie-2.ts
#EXTINF:300.000000,
movie-3.ts
#EXTINF:300.000000,
movie-4.ts
#EXTINF:300.000000,
movie-5.ts
#EXTINF:300.000000,
movie-6.ts
#EXTINF:300.000000,
movie-7.ts
#EXTINF:300.000000,
movie-8.ts
#EXTINF:300.000000,
movie-9.ts
#EXTINF:300.000000,
movie-10.ts
#EXTINF:300.000000,
movie-11.ts
#EXTINF:300.000000,
movie-12.ts
#EXTINF:300.000000,
movie-13.ts
#EXTINF:300.000000,
movie-14.ts
#EXTINF:195.440000,
movie-15.ts
#EXT-X-ENDLIST
不加密的ts是可以直接播放的,例如 PotPlayer 播放器,或者把后缀.ts改成.mp4,使用一般的播放器也能播放。
加密的ts文件则不能直接播放,只能播放m3u8,且密钥要匹配上。
并且,m3u8可以嵌套,比如:index.m3u8
gradlew compileDebugSources --stacktrace -info
转载于:https://my.oschina.net/wfy94/blog/3089439
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <script type="text/javascript" src="js/jquery-3.3.1.min.js"></script> <script type="text/javascript" src="js/jquery-migrate-1.4.1.min.js"> </script> <head> <meta charset="UTF-8"> <title></title> </head> <form id="form"> 测试<input type="text" onblur="show()" name="ajax" id="ajxa1" value="11" /><span id="test"></span> </form> <script> function show(){ /* var formData = new FormData(); */ var ajax1=$("#ajxa1").val(); /* formData.append("ajax",ajax1); */ $.ajax({ //请求类型 type:"post", //传参的地址(servlet地址) url:"test", //传整个表单 /* data:$('#form').serialize(), */ //传参的数据 data:"ajax="+ajax1, //返回的值 success:function(result){ $("#test").text(result) } }); } </script> <body> </body> </html> package test.
Leaks 内存泄漏检测工具使用 网址:https://github.com/square/leakcanary 在你的module中添加依赖
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.4-beta2' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta2' testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta2' 在Application中添加
LeakCanary.install(this); 并且确保你的app处于调试模式,如下图 当切换到release版本的时候,leakcanary-debug不会被打包.所以切换到release之后不用对leakcanary做注释或者删除等操作. 现在就可以开始使用了,重新编译你的工程,运行在模拟器或真机上. 在各个页面中测试,如果存在内存泄漏的情况,leaks会弹出通知提醒你查看. 在leaks中会有详细的泄漏说明,如产生内存泄漏的大小,产生内存泄漏的页面和相关的信息。 内存泄漏详情: 最后有一些关于内存泄漏的建议: 为了避免上下文相关的内存泄漏,记住以下几点: 不要长期引用context-activity(引用一个活动应该有相同的生命周期活动本身) 使用getApplicationContext而不是context或activity试试 避免非静态内部类的一个活动如果你不控制自己的生命周期,使用静态内部类,让一个弱引用来传递,并且记住,垃圾收集器对于内存泄漏并不保险。
下面说几个作者遇到的内存泄漏的情况以及解决方案: 使用百度地图LocationClient.在Activity被销毁时调用
if (mLocClient != null){ mLocClient.unRegisterLocationListener(myListener); mLocClient.stop(); } 使用友盟分享登录时, 传递getApplicationContext
第三方库如果需要传入Activity的时候,传递一个弱引用进去, 可以避免内存泄漏,如下:
Reference<HomeActivity> reference = new WeakReference(getActivity()); new ShareAction(reference.get()).setDisplayList(displaylist); 在Handler中容易造成内存泄漏,最好使用弱引用方式,要么,在Activity销毁的时候清空所有的handler栈。
在使用WebView的时候也可能出现内存泄漏,解决办法,我的另一篇博客里有详细讲解。 http://blog.csdn.net/fancy_xty/article/details/51595697
在使用RxJava的时候也可能会出现内存泄漏,可以使用RxLifecycler来解决。
往往我们在启动一个应用,比如web应用。外部却不能访问。
对于新手来说是很焦虑的。
1.首先检查是否是0.0.0.0:port,如果不是请设置。
2.检查端口号是否开启
这里提供一个在线检查服务器的端口号的网址:http://coolaf.com/tool/port
以百度为例:输入域名或者IP地址
如果没有开放提供以下命令进行操作:
(1)查看已经开放的端口:
firewall-cmd --list-ports
(2)开启端口: firewall-cmd --zone=public --add-port=80/tcp --permanent 命令含义: –zone #作用域 –add-port=80/tcp #添加端口,格式为:端口/通讯协议 –permanent #永久生效,没有此参数重启后失效 (3)防火墙设置: firewall-cmd --reload #重启firewall systemctl stop firewalld.service #停止firewall systemctl disable firewalld.service #禁止firewall开机启动 3.端口还是无法检测出开放,虽然你已经开放了那么有可能是安全组没开放这个端口。自行登陆安全组然后设置。
具体可以参考这篇文章
https://blog.csdn.net/wxb880114/article/details/82219594
#include <iostream> #include <pcl/common/common_headers.h> #include <pcl/io/pcd_io.h> #include <pcl/visualization/pcl_visualizer.h> #include <pcl/point_cloud.h> #include <pcl/octree/octree.h> #include <vector> #include <ctime> //pcl::PointCloud<pcl::PointXYZ>::points是vector类型,可以使用push_back添加随机点 const float R = 5; //半径内近邻搜索的半径 int main() { std::cout << "Hello, World!" << std::endl; srand((unsigned int) time(NULL)); pcl::PointCloud<pcl::PointXYZ>::Ptr pCloud_in (new pcl::PointCloud<pcl::PointXYZ>); //读入点云 if(pcl::io::loadPCDFile<pcl::PointXYZ>("room_scan1.pcd",*pCloud_in) == -1) { PCL_ERROR("ERROR Load..."); return -1; } std::cout<<"load succeed"<<std::endl; float resolution = 128.0f; pcl::octree::OctreePointCloudSearch<pcl::PointXYZ> octree(resolution); octree.setInputCloud(pCloud_in); octree.addPointsFromInputCloud(); //指定搜索中心 pcl::PointXYZ searchPoint; //searchPoint.x = 1024.0f * rand()/(RAND_MAX + 1.0f); //searchPoint.
DHCP是Dynamic Host Configuration Protocol的缩写,即动态主机配置协议。DHCP是一个很重要的局域网的网络协议,使用UDP协议工作,主要有以下用途:
1、为内部网络或网络服务供应商自动分配IP地址;
2、为用户或者内部网络管理员作为对所有计算机作中央管理的手段;
3、为内部网络用户接受IP租约。
而DHCP服务器就是专门承载和运行DHCP服务,并帮助我们管理IP的专用服务器,是运行MicrosoftTCP/IP、DHCP服务器软件和Windows NT Server的计算机。
在网络中配置DHCP服务器有如下优点:
1、大部分路由器可以转发DHCP配置请求,因此,互联网的每个子网并不都需要DHCP服务器;
2、客户机不需手工配置TCP/IP;
3、使用DHCP服务器能大大减少配置花费的开销和重新配置网络上计算机的时间,服务器可以在指派地址租约时配置所有的附加配置值;
4、提供安全可信的配置。DHCP避免了在每台计算机上手工输入数值引起的配置错误,还能防止网络上计算机配置地址的冲突;
5、客户机在子网间移动时,旧的IP地址自动释放以便再次使用。在再次启动客户机时,DHCP服务器会自动为客户机重新配置TCP/IP;
6、管理员可以集中为整个互联网指定通用和特定子网的TCP/IP参数,并且可以定义使用保留地址的客户机的参数。
利用DHCP服务器,我们可以灵活的利用手工分配、自动分配及动态分配3种分配方式,为DHCP客户机分配TCP/IP地址。从而做到更为方便的管理和维护DHCP客户机,同时也可以有效解决IP不够用的问题。
对于需要建站的朋友来说,首选需要一台服务器;其次服务器的稳定和速度。以及考虑服务器的价格成本;做seo的都明白,一台稳定的服务器,速度快的服务器对排名是很有帮助的。所以我选择购买服务器,稳定和速度是基础。个别服务器虽然便宜但是动不动就打不开,这样服务器上的网站排名好算我输。
做网站有好几种选择,比如,选择虚拟主机,或者选择vps,或者独立服务器,或者云服务器;虽然都可以使用但是效果相差比较大,虚拟空间是多用户共享硬件资源,其他网站受攻击会受到牵连。vps要比虚拟主机好一些,比起独立服务器就差了很多。云服务采用多台电脑集群,一条电脑坏了,不会影响网站访问,网站数据安全,不易丢失,
对于国内的服务器租用商而言,除了本身的机房环境不同之外,再者就是服务器租用价格的差别了,而服务器租用的价格一般都是按配置来分,服务器配置不一样,收费也不一样, 但通常的国内的要比国外的廉价。其主要原因是电信、联通的问题,就像双线贵过单线,而多线又贵过双线。
所以,如果网站需求配置高,可以选择独立的服务器,比如服务器托管、服务器租用。
虚拟主机是服务器分出来的很多空间,所有空间都共享一台设备,一台空间受影响会影响服务器上的其他空间;云服务器是多台服务器的云集分配出来的,独立的操作系统,独立的配置;一台服务器受损对空间不受影响,数据更安全,性能更稳定。
iview-Weapp 本项目中使用的UI为iview-Weapp,可在百度自行进入官网并根据文档下载并引入至项目,此处就不多说了。
具体实现 主要实现了在微信小程序下使用地图的marker点击弹出画圆,并根据圆的大小实现地图缩放的问题。
注意!!!:目前半径不可超过60KM,过大会导致进入死循环卡死,如有需要请自行更改代码。
实现的效果如下:
目录如下:
map.js代码:
注意:代码中 drawingnumber 的单位是m(米),drawingnumberKM所代表的的是KM(千米), getCrlcle()方法所计算出的当前缩放半径单位为KM
// pages/map/map.js // pages/map/map.js const { $Message } = require('../../dist/base/index'); var QQMapWX = require('../../lib/qqmap-wx-jssdk.js'); var qqmapsdk; var mapapp; const app = getApp(); var EARTH_RADIUS = 6378.137; //地球半径 function rad(d) { return d * Math.PI / 180.0; } function getDistance(lng1, lat1, lng2, lat2) { var radLat1 = rad(lat1); var radLat2 = rad(lat2); var a = radLat1 - radLat2; var b = rad(lng1) - rad(lng2); var s = 2 * Math.
链接:https://pan.baidu.com/s/1VovIRGPpimWRCRAfkO8S8A 提取码:k5zm
二叉树的遍历方式一般有前序、中序、后序三种方式。其中每种方式都可以由递归和非递归实现,非递归主要借助于栈来实现,还可以借助队列实现层级遍历。下面的代码在vs2019编译通过,其中的栈和队列是自己简单实现的。实现思路和代码如下:
#include <iostream> #define _CRT_SECURE_NO_WARNINGS #define STACK_SIZE 100 #define QUEUE_SIZE 100 typedef struct Btree { char data; struct Btree* lChild; struct Btree* rChild; }Btree, *PBtree; //循环队列 class Myqueue { private: PBtree queue[QUEUE_SIZE]; int front, rear; public: Myqueue() { rear = front = 0; } bool IsEmpty() { return rear == front ? true : false; } bool enQueue(const PBtree T) { if ((rear + 1) % QUEUE_SIZE == front) { return false; } queue[rear] = T; rear = (rear + 1) % QUEUE_SIZE; return true; } PBtree deQueue() { if ( rear == front) { return NULL; } PBtree p = queue[front]; front = (front + 1) % QUEUE_SIZE; return p; } }; //栈 class MyStack { private: PBtree stack[STACK_SIZE]; int top; public: MyStack() { top = -1; } bool IsEmpty() { return -1 == top ?
此方法依赖于lib-flexible,直接替换其中的字符串就可以了
transformHtmlStr(str) { let vm = this; const ZPXRegExp = /(\d+)px/; let pxGlobalRegExp = new RegExp(ZPXRegExp.source, 'ig') if (pxGlobalRegExp.test(str)) { // px转换vw,核心部分 let dataDpr = document.documentElement.getAttribute("data-dpr"); let rootSize = parseFloat(document.documentElement.style.fontSize) ; let $_source = str.replace(pxGlobalRegExp, vm.createPxReplace(dataDpr,rootSize)) // 转换之后替换回source中,返回函数值 return str.replace(str, $_source) } else { //没有就不转,直接返回 return source } }, createPxReplace (dataDpr,rootSize) { return function ($0, $1) { if (!$1) return var pixels = parseFloat($1) return (pixels*dataDpr/rootSize).toFixed(2)+'rem'; } },
package java.lang;
public class Exception extends Throwable {
static final long serialVersionUID = -3387516993124229948L;
public Exception() {
super();
}
public Exception(String message) {
super(message);
}
public Exception(String message, Throwable cause) {
super(message, cause);
}
public Exception(Throwable cause) {
super(cause);
}
protected Exception(String message, Throwable cause,
boolean enableSuppression,
boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
本文来自「心谭博客」的《动画设计·按钮特效》,更多文章放在了Github
欢迎交流和Star
特效一览 滑箱:
果冻:
脉冲:
闪光:
气泡:
滑箱特效 效果图 原理 因为 button 元素可以使用 before/after 伪元素,所以借助伪元素,可以实现动态图中的遮盖层。
为了避免回流重绘,滑箱的运动方向是垂直方向,所以使用scaleY属性。对于动画的方向,需要借助transform-origin改变动画原点。
代码实现 html:
<button>xin-tan.com</button> css:
button { outline: none; border: none; z-index: 1; position: relative; color: white; background: #40a9ff; padding: 0.5em 1em; } button::before { content: ""; z-index: -1; position: absolute; top: 0; bottom: 0; left: 0; right: 0; background-color: #fa541c; transform-origin: center bottom; transform: scaleY(0); transition: transform 0.4s ease-in-out; } button:hover { cursor: pointer; } button:hover::before { transform-origin: center top; transform: scaleY(1); } 果冻特效 效果图 原理和代码 果冻特效可以分割成 5 个部分,所以无法简单通过 transition 来实现,要借助animation。并且动画触发的时间点是鼠标移入的时候,因此 animation 要在:hvoer中声明。
比如:int *a[5]是指针数组,int (*a)[5]是数组指针,前者表示一个数组,数组元素都是指向int型变量的指针,后者表示一个指针,该指针指向一个int型有5个元素的数组。
第一个a是个数组名,里面保存的是int指针。
第二个a是个指针名,它指向一个包含5个数据的int数组。
新的Visual Studio 2019出来已经有一段时间了,博主也是一开始就从vs2017换到了vs2019,发现整体的操作流程还是有一定的改变,因为之前发表过一个vs2017的博客,对Visual Studio IDE和风格确实非常喜欢,博主在vs2019中使用的字体为Fira code,接下来是编写c程序。
1 选择创建新项目
2 选择空项目,单击下一步
3 填写项目名称(生成的文件夹名称和工程名都是这个),我这里填入hello,保存位置选择为桌面,此时应该在工程建立ok后,桌面会生成一个hello的文件夹,勾选解决方案和项目放在同一目录中,便于调试。全部勾选完成后,单击创建。注意,此时电脑可能会短暂卡死,正常现象稍等几秒就好。
4 添加c文件
上一步创建完成后,会得到如下界面,接下来添加源文件
在左侧的解决方案目录下,选中源文件,右键单击,选择添加->新建项,如下图所示
注意,如果左侧没有解决资源管理器,或者不小心关掉了,如下图
单击视图->项目资源管理器就可以调出来
添加新建项的默认页面如下,这里有几个地方值得注意:1 选择C++文件(不管是写c还是c++);2 底下名称的后缀是.cpp,我们写c代码时需要修改为.c;3 这里只管添加.c文件,如果要添加.h文件,在后面介绍。
选中C++文件,名称修改为hello.c,点击添加
5 在hello.c中进行测试
按Ctrl+F5直接编译运行,结果如下,打印正确。
6 正常新建工程到这里已经ok了,在一些项目中,可能需要移植别人的代码,通常是每个.c文件对应一个.h文件,添加过程如下
首先是添加头文件.h,过程:选中头文件->右键单击->添加->现有项
这里我事先创建了max.h和max.c两个文件,用于求两数的最大值,添加如下
一样的,选中源文件,右键单击->添加->现有项,选择max.c
7 在主函数中调用添加文件,并进行测试
测试代码:
#include <stdio.h> void author_log(void); int main(void) { int max_value; max_value = max(555, 666); printf("%d\n", max_value); author_log(); getchar(); return 0; } /* 打印博主log信息 */ void author_log(void) { printf("author name: dingyc \n"); printf("author email: dingyc_ee@yeah.net \n"); } 测试结果:
QString类提供一个unicode字符串。在QT软件开发平台中常用到的一种变量类型,其提供了很多方便的应用方法。下面介绍一些关于QString的常见用法。
1.字符串末尾追加
//example 1 QString str="hello"; str.append("world"); qDebug() <<str; //str=hello world //example 2 QString str="hello"; str=str+"world"; qDebug() <<str; //str=hello world //example 3 QString str="hello"; str+="world"; qDebug() <<str; //str=hello world 2.取出字符串中指定位置的字符
QString str="hello world"; char ch; ch=str.at(1).unicode(); qDebug() <<ch; //ch=e 3.从字符串末尾删除若干个字符
QString str="hello world"; str.chop(2); qDebug() <<str; //str= hello wor 4.清空字符串
//example 1 QString str="hello world"; str.clear(); qDebug() <<str.size(); //str="" //example 2 QString str="hello world"; str=""; qDebug() <<str.size(); //str="" 5.字符串比较
一、本例实现的功能与使用场景 本例实现了把内存中的rgb数组图像导出为标准的mp4文件,以及把标准的mp4视频文件解码并导入到内存中。从而获取到RAW视频,方便对视频做图像处理。
支持的格式为mp4,avi,mov
支持的平台有MacOS,windows
用qt做一个视频剪辑软件。剪辑之前需要导入标准的视频文件到内存,以及剪辑好的视频需要导出为标准的mp4文件。用qt做一个图像或视频处理类的软件,需要导出为标准的mp4文件。(本例子就是在这个需求下写的) 二、使用环境 Qt Creater + FFmpeg, 本例子在macos下开发并测试。由于Qt和FFmpeg都是跨平台的库,因此本工程适用于所有支持Qt的平台。
FFmpeg下载安装:
http://ffmpeg.org/download.html#build-mac
https://ffmpeg.zeranoe.com/builds/
由于FFmpeg是在GNU GPL 3.0 和 LGPL 协议下开发的。
建议使用动态库+ LGPL的方案来使用FFmpeg的库。
把下载好的dev和shareLib 两个文件夹合并,就获得了开发FFmpeg所需要的所有文件了。新建Qt Creater 工程并添加FFmpeg库
用Qt Creater创建好工程之后,在Qt Creater内选择新建的工程,点击右键,选择导入库。就会弹出导入库的引导对话框引导你导入需要的库。本例子的FFmpeg目录与Qt工程目录同在一个父目录下,如下图所示:
导入库之后,在工程文件*.pro文件中有关FFmpeg的配置如下,你也可以直接复制如下配置(只要目录布局和以上提到的相同即可)。 macx { INCLUDEPATH += $$PWD/../ffmpeg-macos64-shared/include DEPENDPATH += $$PWD/../ffmpeg-macos64-shared/include macx: LIBS += -L$$PWD/../ffmpeg-macos64-shared/bin/ -lavcodec.58 macx: LIBS += -L$$PWD/../ffmpeg-macos64-shared/bin/ -lavdevice.58 macx: LIBS += -L$$PWD/../ffmpeg-macos64-shared/bin/ -lavfilter.7 macx: LIBS += -L$$PWD/../ffmpeg-macos64-shared/bin/ -lavformat.58 macx: LIBS += -L$$PWD/../ffmpeg-macos64-shared/bin/ -lavutil.56 macx: LIBS += -L$$PWD/../ffmpeg-macos64-shared/bin/ -lpostproc.55 macx: LIBS += -L$$PWD/.