QString 与 Qt 文字编码

Unicode Unicode 是国际组织制定的可以容纳世界上所有文字和符号的字符编码方案。目前的 Unicode 字符分为 17 组编排,0x0000 至 0x10FFFF,每组称为平面(Plane),而每平面拥有 65536 个码位,共 1114112 个。 它是方案而不是实际的数据格式,或者说它是一项标准而不是具体编码。旧版本的 Windows 记事本另存中有 Unicode 选项,实际上这里的 Unicode 指的是 UTF-16,一些别的软件中也可能是 UCS-2。也许是微软意识到叫 Unicode 不合适,所以 Win10 中改成了 UTF-16。UTF-32、UTF-16 、UTF-8、UCS-2 等都是 Unicode 编码的实现形式。 UTF-8 UTF(Unicode Transformation Format),通用转换格式。UTF-8 是针对 Unicode 的一种可变长度字符编码。它可以用来表示 Unicode 标准中的任何字符。UTF-8 使用 1 ~ 4 字节为每个字符编码,1 字节的 UTF-8 字符与 ASCII(7 位)是兼容的。 UTF-8 编码规则:如果只有一个字节则其最高二进制位为 0;如果是多字节,其第一个字节从最高位开始,连续的二进制位值为 1 的个数决定了其编码的字节数,其余各字节均以 10 开头。 UTF-8 的编码方法决定了它是有字节序并且字节序是明确的。它是以字节为单位传输和处理的,所以不存在多字节数值大小端的问题。所以也就没有大小端的定义。因为是基于 8 位字节的,所以是 -8。 UTF-8 的特征决定了它适宜用于网络数据传输等业务(不用区分大小端字节序),不太适合做存储、字符串分析等(通过 UTF-8 的字节数不太容易得出实际的字符数量)。 UTF-16 UTF-16 比起 UTF-8,好处在于大部分字符都以固定长度的字节 (2 字节) 储存,但 UTF-16 却无法兼容于 ASCII 编码(因为 ASCII 也用两个字节)。在 Unicode 基本多文种平面定义的字符(无论是拉丁字母、汉字或其他文字或符号),一律使用 2 字节储存。而在辅助平面定义的字符,会以代理对(surrogate pair)的形式,以两个 2 字节的值来储存。所以 UTF-16 是两字节或 4 字节的。 UTF-16 与 UCS-2 的关系 UTF-16 可看成是 UCS-2 的父集。在基本多文种平面(Basic Multilingual Plane),UTF-16 与 UCS-2 是一致的,所以有的软件写的是 UCS-2,有的软件写的是 UTF-16,是一样的。但当引入辅助平面字符后,就称不一样了。 GB18030 兼容了 GBK、GB2312。 Latin1 Latin1 是 ISO-8859-1 的别名,有些环境下写作 Latin-1。ISO-8859-1 编码是单字节编码,向下兼容 ASCII,其编码范围是 0x00 - 0xFF,0x00 - 0x7F 之间完全和 ASCII 一致,0x80 - 0x9F 之间是控制字符,0xA0 - 0xFF 之间是文字符号。 QChar 封装了 16-bit Unicode 字符(UTF-16)。 QString 则是由 QChar 形成的字符串,所以 QString 所存储的字符串就是 UTF-16 编码的。 所以不要说某个 QString 字符串是 GBK 编码还是 UTF-8 编码,都不存在的,只能是 UTF-16 编码。 GBK 与 UTF-8 的转换只能在 QByteArray 之间转换,桥梁是 QString,而不是在 QString 之间转换。 小实验 QString str = "中文"; qDebug() << str; qDebug() << qstr2hex(str, true); //utf-16 4E 2D 65 87 qDebug() << str.toUtf8().toHex(' ').toUpper(); //utf-8 E4 B8 AD E6 96 87 qDebug() << str.toLatin1().toHex(' ').toUpper(); //非Latin1,输出“??” QTextCodec::setCodecForLocale(gbk); qDebug() << str.toLocal8Bit().toHex(' ').toUpper(); //GBK D6 D0 CE C4 QTextCodec::setCodecForLocale(utf8); qDebug() << str.toLocal8Bit().toHex(' ').toUpper(); //utf-8 E4 B8 AD E6 96 87 QTextCodec::setCodecForLocale(nullptr); qDebug() << str.toLocal8Bit().toHex(' ').toUpper(); //默认gbk D6 D0 CE C4 输出: "中文" "4E 2D 65 87" "E4 B8 AD E6 96 87" "3F 3F" "D6 D0 CE C4" "E4 B8 AD E6 96 87" "D6 D0 CE C4"...

CentOS 安装远程桌面服务

1、安装 tigervncserver yum install tigervnc-server tigervnc-server-module 2、拷贝配置文件 cp /lib/systemd/system/vncserver@.service /etc/systemd/system/vncserver@:1.service 3、进入到配置文件目录 cd /etc/systemd/system 4、修改配置文件 vim vncserver@:1.service 配置文件内容为: [Unit] Description=Remote desktop service (VNC) After=syslog.target network.target [Service] Type=forking User=root ExecStart=/usr/bin/vncserver :1 -geometry 1280x1024 -depth 16 -securitytypes=none -fp /usr/share/X11/fonts/misc ExecStop=/usr/bin/vncserver -kill :1 [Install] WantedBy=multi-user.target 5、启用配置文件 systemctl enable vncserver@:1.service 6、设置登陆密码 vncpasswd 7、启动 vncserver systemctl start vncserver@:1.service 8、启动状态查看 systemctl status vncserver@:1.service 9、查看端口状态 netstat -lnt | grep 590* 10、查看报错信息 grep vnc /var/log/message...

Ubuntu 16.04 FTP 服务程序 vsftpd

安装: sudo apt install vsftpd 其配置文件为 /etc/vsftpd.conf write_enable=YES #允许写文件操作 useradd -M -s /sbin/nologin ftp1 #创建一个本地 ftp 用户 ftp1 sudo passwd ftp1 sudo service vsftpd restart 530 Login incorrect : 修改 /etc/pam.d/vsftpd: 将 auth required pam_shells.so 修改为 auth required pam_nologin.so 或者将 auth required pam_shells.so 注释 创建虚拟用户: 虚拟用户的文件读写需要一个真实用户配合,先创建一个真实用户(在配置文件中关联guest_username) sudo useradd -m -d /home/vsftpd vsftpd sudo usermod -s /sbin/nologin vsftpd 启用匿名用户 anonymous 匿名用户使用的是系统的 ftp 用户 sudo vim /etc/vsftpd.conf write_enable=YES #允许写文件操作 anonymous_enable=YES anon_upload_enable=YES #匿名用户上传使能 anon_mkdir_write_enable=YES #匿名用户创建文件夹使能 #anon_root=/home/ftp #匿名用户根目录,默认为/srv/ftp sudo service vsftpd restart 关于根目录写权限: 从 2.3.5 之后,vsftpd 增强了安全检查,如果用户被限定在了其主目录下,则该用户的主目录不能再具有写权限了!如果检查发现还有写权限,就会报错误: vsftpd: refusing to run with writable root inside chroot () 解决方法:去除用户主目录的写权限 chmod a-w /srv/ftp 在根目录创建一个ftp用户可以写的目录 sudo mkdir /srv/ftp/public sudo chmod 777 /srv/ftp/public 或者修改配置 allow_writeable_chroot=YES #允许根目...

CentOS 安装 VirtualBox

1、添加源 wget -P /etc/yum.repos.d http://download.virtualbox.org/virtualbox/rpm/el/virtualbox.repo 2、安装 yum install VirtualBox yum install dkms kernel-devel kernel-headers /sbin/vboxconfig #重新编译 VirtualBox 内核 3、将用户加入 vboxusers 组 sudo groupadd -G vboxusers -a root 4、开机自启动: vi /etc/rc.d/rc.local VBoxManage startvm 虚拟机名字 -type vrdp & chmod +x /etc/rc.d/rc.local 5、其他命令 VBoxManage list vms #列出虚拟机 VBoxManage list runningvms #列出运行中的虚拟机 VBoxManage controlvm 虚拟机名字 acpipowerbutton # 关闭虚拟机,等价于点击系统关闭按钮,正常关机 VBoxManage controlvm 虚拟机名字 poweroff # 关闭虚拟机,等价于直接关闭电源,非正常关...

Linux SMB 服务 Samba

Samba 是在 Linux 和 UNIX 系统上实现 SMB 协议的一个免费软件,由服务器及客户端程序构成。Linux 下的 Samba 服务主要用于 Windows 平台和 Linux 平台下载局域网内实现文件共享。 安装: apt-get update apt-get install samba 创建匿名共享文件夹: mkdir /data/share chmod 777 /data/share 配置: vim /etc/samba/smb.conf 在最后加上: [share] comment = share folder browseable = yes path = /data/share public = yes available = yes writable = yes guest ok = yes #重启服务 /etc/init.d/samba restart 或 service samba restart 如果碰巧你的 Win10 账户名与 Linux 中的账户名相同(不分大小写),那么 Win10 在访问 Samba 时会使用你的账户,如果密码不同,则提示你输入凭证,如果密码碰巧相同,则会直接以同名的 Linux 账户登录 samba,你创建的文件或文件夹都属于你的这个账户。要解决这个问题,可以设置 Win10 的 Windows 凭据,添加一个 nobody 空密码的账户...

TortoiseGit 合并过程

将本地的修改 Commit 后,push 到服务器时提示失败。这是可能是因为本地的版本落后于远程版本,服务器上的版本已经被别人抢先一步更新了。这个时候就要做一下合并操作了。所谓的合并可以是合并同一分支(比如上述往 master 分支)的不同版本,也可以是合并不同分支(比如要将 dev 分支合并到 master 分支),查看同一个文件不同版本间的差异并选择两者中的一种或发现新的问题作出新的改动,最后再 commit、push 的过程。 先 Pull,由于我们已经知道本地与服务器两个版本是不同的,所以已经预料到会有问题。 Pull 的时候会自动合并,由于 git 访问不了公司加了密的文件,所以文本文件被当成了二进制文件,自动合并不起作用,只能手动合并。不过即使能正常自动合并,也可能合并出错,毕竟机器还不能完全理解人的意图。 本地文件的图标也会发生变化,感叹号的文件就是有冲突的文件: 点击窗口或菜单中的 Resolve,开始解决冲突的过程。 弹出来冲突文件列表: 由于我使用了 Beyond Compare 做第三方比较/合并工具,所以双击文件就打开了 BC: 同时自动生成了三个文件(应该是 git 生成的,而不是 bc,用内置合并工具时也会生成这几个文件): 编辑器打开冲突文件 .gitignore,可以看到自动合并的痕迹: <<<<<<< HEAD 与 ======= 之间的内容是本地主分支上的内容,>>>>>>> c7877cc893ca1171b829ac7f48187a97befacfdd 是 远程主分支上最新版本 c7877 的内容。两个内容一样,都是相对于上一版本增加的内容。 BC 上面三列分别是 BASE、LOCAL、REMOTE,分别表示上一个版本(感觉可能是共同的祖先),本地版本,远程版本,这三个内容是只读的,改不了。下面的窗口是合并操作的输出,并不是工作区冲突的那个文件的实际内容。 把所有冲突解决掉,commit 然后 push 到服务器。 取消合并: 在 commit 前可以取消合并操作,以使工作区的文件退回到本地最新版本的状态。...

WAV 文件格式简介

WAV 为微软公司(Microsoft)开发的一种音频文件格式,它符合 RIFF(Resource Interchange File Format)文件规范,用于保存 Windows 平台的音频信息资源,被 Windows 平台及其应用程序所广泛支持,该格式也支持 MSADPCM,CCITT A LAW 等多种压缩运算法,支持多种音频数字,取样频率和声道,标准格式化的 WAV 文件和 CD 格式一样,也是 44.1K 的取样频率,16 位量化数字,因此在声音文件质量和 CD 相差无几。WAV 格式的音乐通常使用三个参数来表示声音,量化位数,取样频率和声道数。 WAV 文件采用的是 RIFF 格式结构。至少是由 3 个块构成,分别是 RIFF、fmt 和 data。所有基于压缩编码的 WAV 文件必须含有 fact 块。此外所有其它块都是可选的。块 fmt、Data 及 fact 均为 RIFF 块的子块。WAV 文件的文件格式类型标识符为 WAVE。 构成 RIFF 文件的基本单位称之为块(chunk)。每个 RIFF 文档是由若干个块构成。每个块(chunk)由块标识、块长度及数据等三部分所组成。块标识保存的是由 4 个 ASCII 码字符组成的块名字。如不满 4 个字符则在右边以空格充填。块长度字段占 4 个字节,保存的是当前块数据的长度,不包括块标识和块长度字段。所以一个块的实际长度为块长度字段内的数值加 8。RIFF 格式规定,只有 RIFF 及 LIST 块可以含有子块,其它的块不允许包含子块。一个 RIFF 格式文档本身就是一个块。其前 4 个字节为文档标识 RIFF,同时也是 RIFF 的块标识,标明该文档是一个有效的 RIFF 文档;第二部分为文件的数据长度,占 4 个字节,其数值为文件长度 -8;第三部分为 RIFF 块数据,前 4 个字节为文件格式类型标识,如:WAVE、AVI 等,后面其它部分为 RIFF 块的子块。 //WAV的数值均为小端模式 typedef struct WavRiff { char id[4]; //"RIFF" uint32_t size; //块长度,从下一个字段(format)首地址开始到文件末尾的总字节数,该字段的数值加 8 为文件的总长度 char format[4]; //文件格式类型:"WAVE" } wav_riff_t; typedef struct WavFmt { char id[4]; //格式子块标识"fmt " uint32_t size; //格式子块长度,其数值不确定,取决于编码格式,可以是 16、 18 、20、40 等,从下个字段到格式子块结束的字节数 uint16_t format; //编码格式代码,常见的 WAV 文件使用 PCM 脉冲编码调制格式,PCM = 1 uint16_t channels; //通道数,单声道为1,双声道为2 uint32_t sample_rate; //采样频率,单位Hz uint32_t data_rate; //数据传输率 声道数×采样频率×每样本的数据位数/8,播放软件利用此值可以估计缓冲区的大小 uint16_t block_align; //块对齐字节数 = 声道数×位数/8,播放软件需要一次处理多个该值大小的字节数据,用该数值调整缓冲区 uint16_t bps; //bits per sample采样位数,存储每个采样值所用的二进制数位数。常见的位数有 4、8、12、16、24、32 } wav_fmt_t; typedef struct WavData { char id[4]; //"data" uint32_t size; //data size,从下个字段到格式子块结束的字节数 } wav_data_t; typedef struct WavHeader { wav_riff_t riff; wav_fmt_t fmt; wav_data_t data; } wav_header_t; 常见的压缩编码格式: 格式代码 格式名称 fmt 块长度 fact 块 1(0x0001) PCM/非压缩格式 16 2(0x0002 Microsoft ADPCM 18 √ 3(0x0003) IEEE float 18 √ 6(0x0006) ITU G.711 a-law 18 √ 7(0x0007) ITU G.711 μ-law 18 √ 49(0x0031) GSM 6.10 20 √ 64(0x0040) ITU G.721 ADPCM √ 65,534(0xFFFE) 见子格式块中的编码格式 40 当 WAV 文件采用非 PCM 编码时,使用的是扩展格式块,它是在基本格式块 fmt 之后扩充了一个的数据结构。该结构的前两字节为长度字段,指出后面区域的长度。紧接其后的区域称之为扩展区,含有扩充的格式信息,其长度取决于压缩编码类型。当某种编码格式(如 ITU G.711 a-law)使扩展区的长度为 0 时,长度字段还必须保留,只是长度字段的数值为 0。因此,扩展格式块长度的最小值为基本格式块的长度 16 加 ...

Linux 内核常用函数头文件

linux/types.h size_t time_t clock_t uint8_t uint16_t ... linux/stddef.h NULL true false offsetof stdarg.h Linux 内核中没有 stdarg.h 头文件(stdarg 是编译器内建的,所以不包含在内核中),要使用编译工具链中的 stdarg.h 头文件。 linux/ctype.h isdigit、islower、isupper、tolower、toupper ... linux/string.h memcpy memmove memcmp memset strcpy strlen strcat strstr strcmp strchr strncpy strlcpy strnlen strncat strnstr strncmp strnchr linux/printk.h printk、vprintk linux/uaccess.h copy_to_user copy_from_user linux/slab.h kmalloc kzalloc krealloc kfree linux/vmalloc.h vmalloc vfree linux/kernel.h 当包含 linux/kernel.h 时就间接包含了 stdarg.h(不在内核中)、linux/types.h、linux/types.h、linux/printk.h 等头文件 sprintf、snprintf、vsprintf、vsnprintf 也在这里...

VMWare Ubuntu 扩容

1、在虚拟机的配置窗口使用“扩展...”按钮扩展磁盘容量。 注意,如果有快照就不能用了。需要删掉快照。 2、安装 gparted sudo apt install gparted 3、删除交换分区及扩展分区 4、调整分区大小 5、在未使用的磁盘空间创建扩展分区,再创建交换分区。 6、应用所有...

Ubuntu 安装 vsftpd

sudo apt install vsftpd service vsftpd start service vsftpd status 默认系统用户是可以登录的。 编辑配置文件 /etc/vsftpd.conf 取消注释:write_enable=YES service vsftpd restar...