-
Notifications
You must be signed in to change notification settings - Fork 7
/
ch03-04.htm
1184 lines (765 loc) · 70.9 KB
/
ch03-04.htm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="content-type">
<title>ch03-04</title>
<link href="css/style.css" rel="stylesheet" type="text/css">
<link rel="stylesheet" href="thumbnailviewer.css" type="text/css">
<script src="thumbnailviewer.js" type="text/javascript">
/***********************************************
* Image Thumbnail Viewer Script- © Dynamic Drive (www.dynamicdrive.com)
* This notice must stay intact for legal use.
* Visit http://www.dynamicdrive.com/ for full source code
***********************************************/
</script> </head>
<body>
<div class="os1">3.4 使用 QByteArray </div>
<br>
本节学习 QByteArray 的两种用法,第一种作为字符串处理类,类似 QString ,但 QByteArray
内部字符编码不确定,所以要慎用。第二种是作为纯的字节数组,里面可以包含多个 '\0' ,经常用于网络数据的接收和发送。本节示例代码下载地址在末尾小节
3.4.5 里。<br>
<br>
<div class="os2">3.4.1 QByteArray和char</div>
<br>
Qt 最常用的字符串类是内码固定的 QString,而针对传统类似 C 语言 char* 的字符串,Qt 提供了 QByteArray
类来处理。QString 的字符单元是 QChar,QByteArray 的字节单元是 char。头文件 <QByteArray>
不仅自身以类的形式提供,它还针对传统 C 语言的字符串函数做了安全版本的封装,都加了 q 字母前缀,如
qstrlen、qstrncmp、qstrcpy,这些是全局函数,专门处理传统 C 语言的 char* 字符串,用法与 C
语言风格完全类似,比较简单,本节就不介绍了。本节主要介绍 QByteArray 类的使用。<br>
<br>
QByteArray 类可以处理以 '\0' 结尾的传统字符串,包括 UTF-8 编码和其他如 GBK、Big5
等多字节编码的字符串,在作为字符串使用时,QByteArray
内部字符编码格式是不限定的,可以是任意编码的,所以程序员自己必须要事先确定程序会用到哪些编码的 QByteArray 。因为 Qt5 源文件规定是
UTF-8 编码的,所以 QByteArray 内部使用 UTF-8 编码的字符串居多。QByteArray
在赋值、传参数、返回值时也是使用隐式共享机制提高运行效率,只有字符串发生修改时才会执行深拷贝。<br>
<br>
在文件处理、网络数据收发等场景,QByteArray 类是作为纯字节数组来使用的,里面可以包含任意数据,比如一堆
'\0',这时不要拿它当字符串看,它的存储长度与 qstrlen 计算的长度经常不一致。对于网络数据收发,QByteArray 经常配合
QDataStream 使用,对 Qt 数据类型做串行化(Serializing)。<br>
<br>
<div class="os2">3.4.2 QByteArray作为字符串使用</div>
<br>
QByteArray 类作为字符串使用时,它会自动在字符串末尾添加 '\0' ,末尾的 '\0' 不计入字符串长度。QByteArray
字符串的内部编码是不固定的,比如前面 QString 的 toLocal8Bit 和 toUtf8 函数返回的对象全是 QByteArray
类型。QByteArray 字符串的数据来源可能有:<br>
<ul>
<li>①源代码里的字符串,这时 QByteArray 内码与源文件的编码有关,UTF-8 编码源文件生成的很可能就是 UTF-8 编码的字符串。</li>
<li>②本地文本文件,从文件读取的字符串与该文件使用的字符编码有关,Linux 上常用 UTF-8,而 Windows 经常使用 ANSI
多字节编码,简体 Windows 系统一般是 GBK,而繁体默认是 Big5。</li>
<li>③网页数据,网页本身也是文本文件,有它自己的文本编码格式,这时网页文件编码格式决定 QByteArray 字符串的编码格式。</li>
</ul>
我们这里示范的是第一种,全部用 UTF-8 编码的 QByteArray 字符串。QByteArray 类关于字符串处理的成员函数基本和 QString
类的一样,函数名和参数都是类似的。但注意因为 QByteArray 内码不确定,它没有 arg 函数,也没有字符编码转换的函数。QByteArray
关于字符串处理的函数就不枚举了,和上一节 QString 的差不多,下面直接看示例代码:<br>
<div class="code"> <span style=" color:#808000;">void</span><span style=" color:#c0c0c0;">
</span><span style=" color:#000000;">TestStr</span><span style=" color:#000000;">()</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//内码</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">UTF-8</span>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//数值与字符串转换</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">int</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nDec</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000080;">800</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QByteArray</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">basDec</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">basDec</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">setNum</span><span
style=" color:#000000;">(</span><span style=" color:#000000;">nDec</span><span style=" color:#000000;">);</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//数值转字符串</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()<<</span><span style=" color:#000000;">basDec</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QByteArray</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">basReal</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">"125.78999"</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">double</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">dblReal</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">basReal</span><span style=" color:#000000;">.</span><span
style=" color:#000000;">toDouble</span><span style=" color:#000000;">();</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//字符串转数值</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()<<</span>fixed<span style=" color:#000000;"><<</span><span
style=" color:#000000;">dblReal</span><span style=" color:#000000;">;</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//运算符</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QByteArray</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">basABCD</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">"ABCD"</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QByteArray</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">basXYZ</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">"XYZ"</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()<<(</span><span style=" color:#000000;">basABCD</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;"><</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">basXYZ</span><span style=" color:#000000;">);</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//二者字符编码一致才能比较!</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()<<(</span><span style=" color:#000000;">basABCD</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">==</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">basXYZ</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()<<(</span><span style=" color:#000000;">basABCD</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">>=</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">basXYZ</span><span
style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()<<(</span><span style=" color:#000000;">basABCD</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">+</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">basXYZ</span><span style=" color:#000000;">);</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//子串处理</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QByteArray</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">basHanzi</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">"1234打印汉字"</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//作为字符串时</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">QByteArray::length()</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">和</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">qstrlen()</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">一致</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()<<</span><span style=" color:#000000;">basHanzi</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">length</span><span
style=" color:#000000;">()<<</span><span style=" color:#008000;">"\t"</span><span
style=" color:#000000;"><<</span><span style=" color:#000000;">qstrlen</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">basHanzi</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">data</span><span style=" color:#000000;">()</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//重复</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QByteArray</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">basMoreHanzi</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">basHanzi</span><span style=" color:#000000;">.</span><span
style=" color:#000000;">repeated</span><span style=" color:#000000;">(</span><span
style=" color:#000080;">2</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()<<</span><span style=" color:#000000;">basMoreHanzi</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">count</span><span
style=" color:#000000;">(</span><span style=" color:#008000;">"1234"</span><span
style=" color:#000000;">);</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//统计次数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()<<</span><span style=" color:#000000;">basMoreHanzi</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">startsWith</span><span
style=" color:#000000;">(</span><span style=" color:#008000;">"1234"</span><span
style=" color:#000000;">);</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//开头判断</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()<<</span><span style=" color:#000000;">basMoreHanzi</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">endsWith</span><span
style=" color:#000000;">(</span><span style=" color:#008000;">"汉字"</span><span style=" color:#000000;">);</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//结尾判断</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()<<</span><span style=" color:#000000;">basMoreHanzi</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">indexOf</span><span
style=" color:#000000;">(</span><span style=" color:#008000;">"1234"</span><span
style=" color:#000000;">);</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//从左边查出现位置</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()<<</span><span style=" color:#000000;">basMoreHanzi</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">lastIndexOf</span><span
style=" color:#000000;">(</span><span style=" color:#008000;">"1234"</span><span
style=" color:#000000;">);</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//从右边查出现位置</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//替换</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">basMoreHanzi</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">replace</span><span
style=" color:#000000;">(</span><span style=" color:#008000;">"1234"</span><span
style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">"一二三四"</span><span
style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()<<</span><span style=" color:#000000;">basMoreHanzi</span><span
style=" color:#000000;">;</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//切割字符串</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QByteArray</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">basComplexFile</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">"</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">/home/user/somefile.txt</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">\t\t</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">"</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QByteArray</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">basFileName</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">basComplexFile</span><span style=" color:#000000;">.</span><span
style=" color:#000000;">trimmed</span><span style=" color:#000000;">();</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//剔除两端空白</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()<<</span><span style=" color:#000000;">basFileName</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//分隔得到新的</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">QByteArray</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">对象列表</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QList</span><span
style=" color:#000000;"><</span><span style=" color:#800080;">QByteArray</span><span
style=" color:#000000;">></span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">baList</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">basFileName</span><span style=" color:#000000;">.</span><span
style=" color:#000000;">split</span><span style=" color:#000000;">(</span><span
style=" color:#008000;">'/'</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//打印</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">for</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">i</span><span style=" color:#000000;">=</span><span style=" color:#000080;">0</span><span
style=" color:#000000;">;</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">i</span><span
style=" color:#000000;"><</span><span style=" color:#000000;">baList</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">length</span><span
style=" color:#000000;">();</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">i</span><span
style=" color:#000000;">++)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()<<</span><span style=" color:#000000;">i</span><span
style=" color:#000000;"><<</span><span style=" color:#008000;">"\t"</span><span
style=" color:#000000;"><<</span><span style=" color:#000000;">baList</span><span
style=" color:#000000;">[</span><span style=" color:#000000;">i</span><span style=" color:#000000;">];</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//没有段落函数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre>
</div>
<br>
上面测试函数第一段是数值与字符串互相转换的,比较简单,打印结果是:<br>
<span style=" font-family:'Courier'; font-size:10pt; color:#aa00aa;">"800"</span>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" font-family:'Courier'; font-size:10pt; color:#aa00aa;">125.789990</span></p>
<br>
浮点数转换时,定点计数法和科学计数法都是可以接受的,上面示范的是定点数。这些函数声明和功能都可以查阅 QByteArray 类的帮助文档。<br>
<br>
第二段代码是运算符函数的,需要注意的是一定要在确定字符串内部字符编码的情况下,才能进行比较和拼接,上面用的全是 UTF-8
。不能将不同编码格式的字符串比较,因为得到的结果没意义,反而会造成误导。上面比较运算符的打印结果为:<br>
<span style=" font-family:'Courier'; font-size:10pt; color:#aa00aa;">true</span>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" font-family:'Courier'; font-size:10pt; color:#aa00aa;">false</span></p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" font-family:'Courier'; font-size:10pt; color:#aa00aa;">false</span></p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" font-family:'Courier'; font-size:10pt; color:#aa00aa;">"ABCDXYZ"</span></p>
<br>
第三段是子串查询处理的,注意只有当 QByteArray 作为字符串处理时,它的 length() 函数计算的长度才会和全局函数 qstrlen()
计算的结果一致。子串部分打印的结果为:<br>
<span style=" font-family:'Courier'; font-size:10pt; color:#aa00aa;">16
16</span>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" font-family:'Courier'; font-size:10pt; color:#aa00aa;">2</span></p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" font-family:'Courier'; font-size:10pt; color:#aa00aa;">true</span></p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" font-family:'Courier'; font-size:10pt; color:#aa00aa;">true</span></p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" font-family:'Courier'; font-size:10pt; color:#aa00aa;">0</span></p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" font-family:'Courier'; font-size:10pt; color:#aa00aa;">16</span></p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" font-family:'Courier'; font-size:10pt; color:#aa00aa;">"一二三四打印汉字一二三四打印汉字" </span></p>
<br>
上面示范的 basMoreHanzi.replace("1234", "一二三四") ,这种形式的替换函数会对所有匹配的子串进行替换,它的声明是:<br>
<div class="code"> QByteArray & replace(const char *
before, const char * after)</div>
如果要对指定位置的子串替换,需要换一个声明形式的 replace 函数,比如:<br>
<div class="code"> QByteArray & replace(int pos, int
len, const char * after)</div>
这个函数会对指定位置 pos 开始的长度为 len 的子串进行替换,这个函数声明只做一次替换。<br>
对于 replace 函数,必须注意字符编码的问题,UTF-8 的英文字符占用 1 字节,汉字通常是 3
字节,这种不确定性在替换函数和其他分隔子串函数时尤其需要注意,因为 3 字节的汉字如果被截断,就成错误的字符,造成信息损失。因此尽量不要用
QByteArray 类来处理字符串,尤其是涉及分割和替换的。QString 类的字符长度是固定的,所以最适合做字符串处理。<br>
<br>
最后一段代码是子串分隔的,trimmed 函数功能也是去除两端的空白区域,split 函数将字符串分隔为多个子串之后按照
QList<QByteArray> 类型返回,QList 是一个模板类,QList<QByteArray> 就是存储多个
QByteArray 对象的列表,可以直接用中括号 [] 访问里面的各个对象。最后一段代码打印的结果如下:<br>
<span style=" font-family:'Courier'; font-size:10pt; color:#aa00aa;">"/home/user/somefile.txt"</span>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" font-family:'Courier'; font-size:10pt; color:#aa00aa;">0 ""</span></p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" font-family:'Courier'; font-size:10pt; color:#aa00aa;">1 "home"</span></p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" font-family:'Courier'; font-size:10pt; color:#aa00aa;">2 "user"</span></p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" font-family:'Courier'; font-size:10pt; color:#aa00aa;">3 "somefile.txt"</span></p>
<br>
分隔结果与上一节 QString 是一样的,对于开头 '/' 左边没有字符的情况,一样会分出来一个空字符串对象。因为一般用 QString
来处理文本字符串,QByteArray 类没有 section 函数,所以字符串处理时优先用 QString 类。<br>
<br>
<div class="os2">3.4.3 QByteArray作为字节数组使用</div>
<br>
在读写文件、网络数据收发过程中经常将 QByteArray 作为缓冲区存储字节数据,这时候 QByteArray 就是纯的字节数组,里面可以包含任意个
'\0' 字节。下面以网络数据传输为例讲解,比如网络传输过程中既要传输数值类型 int、double,又要传输字符串类型 char*,对于普通的 C++
,最常用的是自定义一个结构体:<br>
<div class="code"><span style=" color:#808000;">struct</span><span style=" color:#c0c0c0;">
</span><span style=" color:#800080;">NetData</span>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">int</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">nVersion</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">double</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">dblValue</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">char</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">strName</span><span
style=" color:#000000;">[</span><span style=" color:#000080;">256</span><span style=" color:#000000;">];</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">};</span></pre>
</div>
发数据时就将数值赋值给结构体对象的成员变量,字符串就用 strcpy
函数塞进去。这种方式可行,但缺乏灵活性,下次如果要传个不同的数据组合,就得重新定义。<br>
Qt 对这类组合数据的打包方法就叫串行化(Serializing),在 Qt 帮助文档的索引里输入关键词 Serializing 就可以看到关于 Qt
串行化的帮助主题(Serializing Qt Data Types),除了 C++ 基本数值类型,Qt
还对大量自身的类对象做了串行化。串行化得到一个字节数组 QByteArray ,可以直接用于发送。Qt 串行化数据接收就是发送的逆过程,都是通过
QDataStream 流实现。下面简单示范一对函数,首先是串行化输出:<br>
<div class="code"><span style=" color:#800080;">QByteArray</span><span style=" color:#c0c0c0;">
</span><span style=" color:#000000;">TestSerialOut</span><span style=" color:#000000;">()</span>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//数据</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">int</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nVersion</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">1</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">double</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">dblValue</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">125.78999</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QString</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strName</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">QObject</span><span style=" color:#000000;">::</span><span
style=" color:#000000;">tr</span><span style=" color:#000000;">(</span><span style=" color:#008000;">"This</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">an</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">example."</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//字节数组保存结果</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QByteArray</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">baResult</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//串行化的流</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QDataStream</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">dsOut</span><span
style=" color:#000000;">(&</span><span style=" color:#000000;">baResult</span><span
style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QIODevice</span><span
style=" color:#000000;">::</span><span style=" color:#800080;">ReadWrite</span><span
style=" color:#000000;">);</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//做输出,构造函数用指针</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//设置Qt串行化版本</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">dsOut</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">setVersion</span><span
style=" color:#000000;">(</span><span style=" color:#800080;">QDataStream</span><span
style=" color:#000000;">::</span><span style=" color:#800080;">Qt_5_0</span><span
style=" color:#000000;">);</span><span style=" color:#008000;">//使用Qt 5.0 版本流</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//串行化输出</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">dsOut</span><span
style=" color:#000000;"><<</span><span style=" color:#000000;">nVersion</span><span
style=" color:#000000;"><<</span><span style=" color:#000000;">dblValue</span><span
style=" color:#000000;"><<</span><span style=" color:#000000;">strName</span><span
style=" color:#000000;">;</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//显示长度</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()<<</span><span style=" color:#000000;">baResult</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">length</span><span
style=" color:#000000;">()<<</span><span style=" color:#008000;">"\t"</span><span
style=" color:#000000;"><<</span><span style=" color:#000000;">qstrlen</span><span
style=" color:#000000;">(</span><span style=" color:#000000;">baResult</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">data</span><span style=" color:#000000;">());</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//返回对象</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">return</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">baResult</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre>
</div>
该函数里给定了三个数据:整数、浮点数和字符串对象,通过流 dsOut 将三个数据打包存到字节数组 baResult
里。对于串行化输出,QDataStream 的构造函数是以字节数组的指针和读写模式 QIODevice::ReadWrite 为参数,其构造函数声明为:<br>
<div class="code">QDataStream(QByteArray * a, QIODevice::OpenMode mode)</div>
然后设置串行化流的版本兼容,上面代码使用的是 Qt 5.0 版本的流格式;流格式设置好之后,就可以用 <<
将数据输出到流里面,QDataStream 类的函数会将数据打包好存到字节数组里面,最后返回这个字节数组对象就行了。<br>
以字节数组方式使用的 QByteArray 对象,它的长度是不能用 qstrlen 之类的函数计算的,上面函数打印的结果如下:<br>
<span style=" font-family:'Courier'; font-size:10pt; color:#aa00aa;">48
0</span><br>
<br>
字节数组实际占用 48 字节空间,而 qstrlen 函数计算的是 0,因为该字节数组第一个字节就是 '\0' 。<br>
该函数返回的 baResult 就包含了三个要发送的数据,baResult 里面具体的数据格式不需要关心,收发两端 setVersion
的版本号一致就可以了。使用串行化就不再需要自定义结构体,所以用起来很方便。<br>
网络收发过程到后面网络专题的学习再讲,现在仅学习一下串行化输出和输入的函数,baResult 数据的解析函数如下:<br>
<div class="code"> <span style=" color:#808000;">void</span><span style=" color:#c0c0c0;">
</span><span style=" color:#000000;">TestSerialIn</span><span style=" color:#000000;">(</span><span
style=" color:#808000;">const</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">QByteArray</span><span style=" color:#000000;">&</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">baIn</span><span
style=" color:#000000;">)</span>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//输入流</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QDataStream</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">dsIn</span><span style=" color:#000000;">(</span><span
style=" color:#000000;">baIn</span><span style=" color:#000000;">);</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//只读的流,构造函数用常量引用</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//设置Qt串行化版本</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">dsIn</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">setVersion</span><span
style=" color:#000000;">(</span><span style=" color:#800080;">QDataStream</span><span
style=" color:#000000;">::</span><span style=" color:#800080;">Qt_5_0</span><span
style=" color:#000000;">);</span><span style=" color:#008000;">//使用Qt</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">5.0</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">版本流</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//变量</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">int</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nVersion</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">double</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">dblValue</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QString</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strName</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//串行化输入</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">dsIn</span><span
style=" color:#000000;">>></span><span style=" color:#000000;">nVersion</span><span
style=" color:#000000;">>></span><span style=" color:#000000;">dblValue</span><span
style=" color:#000000;">>></span><span style=" color:#000000;">strName</span><span
style=" color:#000000;">;</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//打印</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()<<</span><span style=" color:#000000;">nVersion</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()<<</span>fixed<span style=" color:#000000;"><<</span><span
style=" color:#000000;">dblValue</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()<<</span><span style=" color:#000000;">strName</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre>
</div>
对于输入流的构造,参数是常量引用,其声明如下:<br>
<div class="code">QDataStream(const QByteArray & a)</div>
这个声明是针对只读的输入流。输入流定义好之后,同样是设置流的版本号,要与输出端的一致。然后使用 >> 从输入流提取数据即可。上面函数打印的结
果如下:<br>
<span style=" font-family:'Courier'; font-size:10pt; color:#aa00aa;">1</span>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" font-family:'Courier'; font-size:10pt; color:#aa00aa;">125.789990</span></p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" font-family:'Courier'; font-size:10pt; color:#aa00aa;">"This an example."</span></p>
<br>
可见与输出函数里的完全一样。对于 Qt 程序的网络通信,都可以类似上面方法对数据进行打包和解析,是比较方便的。<br>
<br>
QByteArray 有针对数据处理的一些函数,比如基 64
转换和压缩解压函数:fromBase64、toBase64、qCompress、qUncompress 等,这些函数可以到使用的时候再查帮助文档。<br>
<br>
<div class="os2">3.4.4 QByteArray和QString合理的使用方式</div>
<br>
因为 QByteArray 既可以用作字符串,又可以用作字符数组,它的使用方式比较多。而且作为字符串时,它内部的字符编码格式又是不固定的,所以
QByteArray 有诸多的不确定性。Qt 帮助文档里面明确说了,如果要做字符串方面的处理,都应当使用 QString
,除非是嵌入式系统里面内存有限,不得不用 QByteArray 的情况。对于本地化编码的字符串,可以用 QString::fromLocal8Bit
函数将字符串源转为 QString 对象;对于 UTF-8 编码的字符串,可以用 QString::fromUtf8 函数实现转换。如果要反过来转换,就
用对应的 to*** 函数。通常情况下有这些函数就够用了。<br>
<br>
对于文件读写和网络数据收发,这些一般都是用 QByteArray 对象作为输入输出缓冲区,并且可以利用 QDataStream
做串行化,将多个数据打包成 QByteArray 。通常情况下,对于纯字节数据的处理使用 QByteArray 。<br>
<br>
在有些情况下,需要 QString 和 QByteArray 对多种编码格式字符串进行转换,需要二者协作,下面给个协作的示例:<br>
<div class="code"> <span style=" color:#808000;">void</span><span style=" color:#c0c0c0;">
</span><span style=" color:#000000;">TestCooperation</span><span style=" color:#000000;">()</span>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//源字符串</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QString</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strSrc</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">QObject</span><span style=" color:#000000;">::</span><span
style=" color:#000000;">tr</span><span style=" color:#000000;">(</span><span style=" color:#008000;">"1234abcd</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">千秋萬載</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">壹統江湖"</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//转为</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">UTF-8</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()<<</span><span style=" color:#000000;">strSrc</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">toUtf8</span><span
style=" color:#000000;">();</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//明确地转为</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">GB18030</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QTextCodec</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span><span style=" color:#000000;">codecGB</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">QTextCodec</span><span style=" color:#000000;">::</span><span
style=" color:#000000;">codecForName</span><span style=" color:#000000;">(</span><span
style=" color:#008000;">"GB18030"</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QByteArray</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strGB</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">codecGB</span><span style=" color:#000000;">-></span><span
style=" color:#000000;">fromUnicode</span><span style=" color:#000000;">(</span><span
style=" color:#000000;">strSrc</span><span style=" color:#000000;">);</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//转为GB18030</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()<<</span><span style=" color:#000000;">strGB</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()<<</span><span style=" color:#000000;">codecGB</span><span
style=" color:#000000;">-></span><span style=" color:#000000;">toUnicode</span><span
style=" color:#000000;">(</span><span style=" color:#000000;">strGB</span><span
style=" color:#000000;">);</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//转回QString</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//明确地转为</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">Big5</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QTextCodec</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span><span style=" color:#000000;">codecBig5</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">QTextCodec</span><span style=" color:#000000;">::</span><span
style=" color:#000000;">codecForName</span><span style=" color:#000000;">(</span><span
style=" color:#008000;">"Big5"</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QByteArray</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strBig5</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">codecBig5</span><span style=" color:#000000;">-></span><span
style=" color:#000000;">fromUnicode</span><span style=" color:#000000;">(</span><span
style=" color:#000000;">strSrc</span><span style=" color:#000000;">);</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//转为Big5</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()<<</span><span style=" color:#000000;">strBig5</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()<<</span><span style=" color:#000000;">codecBig5</span><span
style=" color:#000000;">-></span><span style=" color:#000000;">toUnicode</span><span
style=" color:#000000;">(</span><span style=" color:#000000;">strBig5</span><span
style=" color:#000000;">);</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">//转回QString</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre>
</div>
除了 QString 自带的 to*** 等函数实现不同字符编码的转换,更为专业的是 QTextCodec
类,专门用于不同文本编码格式的转换。上面示例函数以源字符串 strSrc 为起点,首先实现与 GB18030 编码互相转换,然后实现与 Big5
编码互相转换。<br>
获取编码器的语法格式是:<br>
<div class="code">QTextCodec *codecGB =
QTextCodec::codecForName("GB18030");</div>
codecGB 是保存编码器的指针,静态函数 QTextCodec::codecForName 根据指定的编码名称获取相应的编码器,示例的是
"GB18030"。如果要将 QString 转成其他编码的 QByteArray,就用 fromUnicode 函数,反过来就用 toUnicode
函数。<br>
上面对 GB18030 和 Big5 都做了示范,打印的结果如下图所示:<br>
<center><img src="images/ch03/ch03-04-01.png"></center>
<br>
qDebug 打印 QString 对象和 UTF-8 字符串时汉字不会乱码,而 GB18030 和 Big5 等编码的汉字会乱码,只有数字、英文字符等
ASCII 码是正常显示的。<br>
<br>
<div class="os2">3.4.5 QByteArray示例代码</div>
<br>
本节 QByteArray 示例就是以上 4 个测试函数的合集,下载地址:<br>
<a href="https://lug.ustc.edu.cn/sites/qtguide/QtProjects/ch03/testqbytearray/testqbytearray.7z">
https://lug.ustc.edu.cn/sites/qtguide/QtProjects/ch03/testqbytearray/testqbytearray.7z
</a> <br> 下载之后解压到比如 D:\QtProjects\ch03\testqbytearray
文件夹里面,然后打开项目文件,阅读源代码。<br>
这里主要把包含的头文件和 main 函数贴出来,4 个测试函数内容不重复贴了:<br>
<div class="code"> <span style=" color:#008000;">//testqbytearray.cpp</span>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;"><QApplication></span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span