-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathatom.xml
168 lines (101 loc) · 78.7 KB
/
atom.xml
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
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>yao's blog</title>
<link href="https://yaodev.site/atom.xml" rel="self"/>
<link href="https://yaodev.site/"/>
<updated>2023-12-17T12:08:28.977Z</updated>
<id>https://yaodev.site/</id>
<author>
<name>pentonbin</name>
</author>
<generator uri="https://hexo.io/">Hexo</generator>
<entry>
<title>uleb128 编码</title>
<link href="https://yaodev.site/2023/12/16/uleb128%E7%BC%96%E7%A0%81/"/>
<id>https://yaodev.site/2023/12/16/uleb128%E7%BC%96%E7%A0%81/</id>
<published>2023-12-16T05:14:00.000Z</published>
<updated>2023-12-17T12:08:28.977Z</updated>
<content type="html"><![CDATA[<h2 id="1-简介"><a href="#1-简介" class="headerlink" title="1. 简介"></a>1. 简介</h2><p>uleb128(无符号小端变长编码)是一种编码格式,主要用于表示无符号整数。它是一种变长编码,可以有效地表示较小的整数,同时也支持较大的整数。ULEB128是DWARF调试信息格式和WebAssembly二进制格式中使用的一种编码方式。<br>怎么理解uleb128是如何编码的</p><span id="more"></span><h2 id="2-编码方式"><a href="#2-编码方式" class="headerlink" title="2. 编码方式"></a>2. 编码方式</h2><p>uleb128编码的原理是将整数分成7位的分组,从低位到高位进行编码。每个分组会被编码为一个字节,字节的最高位(第8位)用于表示是否还有更多的字节需要解码。如果最高位为1,则表示后面的字节还有更多的数据;如果最高位为0,则表示这是最后一个字节。<br>这样,较小的整数可以用较少的字节表示,从而节省存储空间和传输带宽。<br>举例,假如现在有十六进制数据:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">80 80 01 60</span><br><span class="line">60 28 60 18</span><br></pre></td></tr></table></figure><p>则这十六进制数据对应的二进制数据为:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">10000000 10000000 00000001 01100000</span><br><span class="line">01100000 00101000 01100000 00011000</span><br></pre></td></tr></table></figure><p>由于uleb128 是可变长度的编码,所以需要一边解析直到读到结束标记位为止,每个分组的长度为一个字节,所以可以逐一字节解析:<br>第一个字节数据1000 0000(0x80),其最高位为 1,去掉最高位后为000 0000<br>第二个字节数据 1000 0000(0x80),其最高位为 1,去掉最高位后为000 0000<br>第三个字节数据 0000 0001(0x01),其最高位为 0,去掉最高位后为 000 0001<br>由于已经遇到最高位为 0 的字节,则第一个数据长度便是从第一个字节到第三个字节,总长度为三个字节,在小端模式下,这个数据便是去除高位后的七比特位进行拼接,拼接顺序是先第三个字节、第二个字节、第一个字节:000 0001 000 0000 000 0000,这个二进制表示的数据为:16384</p><p>现在继续进行解析,从第四个字节开始:<br>第四个字节数据 0110 0000(0x60),其最高位为 0,去掉最高位后为 110 0000<br>由于已经遇到最高位为 0 的字节,则第二个数据直接就是第四个字节所表示的数据,表示的数据为: 110 0000,这个二进制表示的数据为:96<br>参考上面的解析流程,则最后这 八个字节解析出来的数据为:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">16384 96 96 40 96 24</span><br></pre></td></tr></table></figure><h2 id="3-uleb128优势"><a href="#3-uleb128优势" class="headerlink" title="3. uleb128优势"></a>3. uleb128优势</h2><p>如果不使用可变长度的编码方式,而是固定长度的编码,则每个数据使用多少个字节取决于最大的那个数据,假如一组数据最大值为16384(0x4000),也就是需要两个字节,则</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">16384 96 96 40 96 24</span><br></pre></td></tr></table></figure><p>这一组数据所需要总共的字节数为 2 * 6 = 12 个字节,而使用 uleb128 所需要的总字节数为 8 个字节,相比于固定长度的编码,总共节省了 33.3% 。</p><h2 id="4-python-解析"><a href="#4-python-解析" class="headerlink" title="4. python 解析"></a>4. python 解析</h2><p>下面提供了从一个 byte数组解析成原来数据的代码:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">_parse_uleb128</span>(<span class="params">self, data_bytes: <span class="built_in">bytes</span>, start_offset: <span class="built_in">int</span>, end_offset: <span class="built_in">int</span></span>) -> <span class="type">List</span>[<span class="built_in">int</span>]:</span><br><span class="line"> <span class="string">"""</span></span><br><span class="line"><span class="string"> 给出一个 byte 数组,解析从[start_offset, end_offset]范围内的数据</span></span><br><span class="line"><span class="string"> """</span></span><br><span class="line"> <span class="keyword">assert</span> <span class="number">0</span> <= start_offset < <span class="built_in">len</span>(data_bytes)</span><br><span class="line"> <span class="keyword">assert</span> start_offset <= end_offset < <span class="built_in">len</span>(data_bytes)</span><br><span class="line"> uleb128_result = []</span><br><span class="line"> current_offset = start_offset</span><br><span class="line"> current_num = <span class="string">''</span></span><br><span class="line"> <span class="keyword">while</span> current_offset < end_offset:</span><br><span class="line"> high_bit = (data_bytes[current_offset] & <span class="number">0x80</span>) >> <span class="number">7</span></span><br><span class="line"> seven_bit = data_bytes[current_offset] & <span class="number">0x7f</span></span><br><span class="line"> current_num = <span class="string">'{:07b}'</span>.<span class="built_in">format</span>(seven_bit) + current_num</span><br><span class="line"> <span class="keyword">if</span> high_bit == <span class="number">0</span>: <span class="comment"># 后续没有数据了</span></span><br><span class="line"> uleb128_result.append(<span class="built_in">int</span>(current_num, <span class="number">2</span>))</span><br><span class="line"> current_num = <span class="string">''</span> <span class="comment"># 清空数据</span></span><br><span class="line"> current_offset += <span class="number">1</span></span><br><span class="line"> <span class="keyword">if</span> <span class="built_in">len</span>(current_num) > <span class="number">0</span>:</span><br><span class="line"> uleb128_result.append(<span class="built_in">int</span>(current_num, <span class="number">2</span>))</span><br><span class="line"> <span class="keyword">return</span> uleb128_result</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html"><h2 id="1-简介"><a href="#1-简介" class="headerlink" title="1. 简介"></a>1. 简介</h2><p>uleb128(无符号小端变长编码)是一种编码格式,主要用于表示无符号整数。它是一种变长编码,可以有效地表示较小的整数,同时也支持较大的整数。ULEB128是DWARF调试信息格式和WebAssembly二进制格式中使用的一种编码方式。<br>怎么理解uleb128是如何编码的</p></summary>
<category term="Encoding" scheme="https://yaodev.site/categories/Encoding/"/>
<category term="Encoding" scheme="https://yaodev.site/tags/Encoding/"/>
<category term="uleb128" scheme="https://yaodev.site/tags/uleb128/"/>
<category term="iOS" scheme="https://yaodev.site/tags/iOS/"/>
</entry>
<entry>
<title>Javaer入门Dart</title>
<link href="https://yaodev.site/2018/12/09/Javaer%E5%85%A5%E9%97%A8Dart/"/>
<id>https://yaodev.site/2018/12/09/Javaer%E5%85%A5%E9%97%A8Dart/</id>
<published>2018-12-09T07:25:00.000Z</published>
<updated>2023-12-17T10:31:59.761Z</updated>
<content type="html"><![CDATA[<p>如果你是一名Java开发人员,可以通过 <span class="exturl" data-url="aHR0cHM6Ly9jb2RlbGFicy5kZXZlbG9wZXJzLmdvb2dsZS5jb20vY29kZWxhYnMvZnJvbS1qYXZhLXRvLWRhcnQvaW5kZXguaHRtbCMw">codelabs<i class="fa fa-external-link-alt"></i></span> 快速入门Dart。</p><h2 id="1-简介"><a href="#1-简介" class="headerlink" title="1. 简介"></a>1. 简介</h2><p>Dart是一门用于Flutter的编程语言,而Flutter是Google开发的移动应用SDK。 </p><p>阅读本文,你将学习到:</p><ul><li>如何编写构造方法</li><li>为对象赋值的多种方式</li><li>如何 & 何时创建getter和setter</li><li>如何处理访问权限</li><li>如何创建工厂模式</li><li>函数式编程</li><li>其他主要的概念</li></ul><p>此外,codelabs提供了 <span class="exturl" data-url="aHR0cHM6Ly9kYXJ0cGFkLmRhcnRsYW5nLm9yZy8=">DartPad<i class="fa fa-external-link-alt"></i></span> 供大家编写Dart代码。</p><span id="more"></span><h2 id="2-创建一个简单的Dart类"><a href="#2-创建一个简单的Dart类" class="headerlink" title="2. 创建一个简单的Dart类"></a>2. 创建一个简单的Dart类</h2><p>我们以一个简单的<code>Bicycle</code>类来进行学习,<code>Bicycle</code>类包含一些私有的成员变量,以及对应的setter和getter。<br>我们尝试编写<code>Bicycle</code>类然后通过<code>main()</code>方法将<code>Bicycle</code>实例打印到控制台。</p><h3 id="2-1-启动DartPad"><a href="#2-1-启动DartPad" class="headerlink" title="2.1 启动DartPad"></a>2.1 启动DartPad</h3><p>现在可以打开 <span class="exturl" data-url="aHR0cHM6Ly9kYXJ0cGFkLmRhcnRsYW5nLm9yZy8=">DartPad<i class="fa fa-external-link-alt"></i></span> ,一边编写Dart代码。</p><h3 id="2-2-定义Bicycle类"><a href="#2-2-定义Bicycle类" class="headerlink" title="2.2 定义Bicycle类"></a>2.2 定义Bicycle类</h3><p>在DartPad定义一个<code>Bicycle</code>类,其中包含三个成员变量:<code>cadence</code>、<code>speed</code>和<code>gear</code>。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">class Bicycle {</span><br><span class="line"> int cadence;</span><br><span class="line"> int speed;</span><br><span class="line"> int gear;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">void main() {</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>在上面的代码中,我们定义了<code>Bicycle</code>类,以及一个<code>main()</code>方法,代码相对比较简单。其中有一些Dart和Java的区别需要留意:</p><table><thead><tr><th>区别</th><th>Dart</th><th>Java</th></tr></thead><tbody><tr><td><code>main()</code>方法</td><td>1. 不带参数则定义为<code>void main()</code>,带参数定义为<code>void main(List<String> args)</code> <br>2. <strong>必须在最外层</strong>,位于类外部</td><td>1. 定义为<code>public static void main(String[] args)</code> <br>2. 位于类内部</td></tr><tr><td>方法、变量定义</td><td>能够位于类外</td><td>面向对象语言,所有变量、方法必须位于类内部</td></tr><tr><td>访问类型</td><td>不支持private、public、protected修饰词,全部类、成员变量和方法默认定义为public</td><td>通过修饰词private、public、protected修饰</td></tr><tr><td>类成员私有化</td><td>成员命名以下划线开始(下一节将学习到)</td><td>通过private修饰</td></tr><tr><td>缩进</td><td>默认使用两个空格</td><td>默认使用四个空格</td></tr></tbody></table><h3 id="2-3-定义构造方法"><a href="#2-3-定义构造方法" class="headerlink" title="2.3 定义构造方法"></a>2.3 定义构造方法</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Bicycle(this.cadence, this.speed, this.gear);</span><br></pre></td></tr></table></figure><p>上面代码便是Dart的构造方法,初次阅读会觉得比较奇怪,但是在Dart:</p><ol><li>构造方法没有函数体是<strong>允许</strong>的!</li><li>如果没函数体的构造方法行末尾漏了分号<code>;</code>,DartPad会提示:<code>A function body must be provided.</code></li><li>在构造方法的参数列表中使用this,是Dart为实例变量赋值的一种快捷方式。也即是等同于以下代码,大家记住可以这么用就可以了。 <figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Bicycle(int cadence, int speed, int gear) {</span><br><span class="line"> this.cadence = cadence;</span><br><span class="line"> this.speed = speed;</span><br><span class="line"> this.gear = gear;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li></ol><h3 id="2-4-实例化并打印"><a href="#2-4-实例化并打印" class="headerlink" title="2.4 实例化并打印"></a>2.4 实例化并打印</h3><p>在我们的<code>main()</code>方法中添加实例化的代码:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">void main() {</span><br><span class="line"> var bike1 = new Bicycle(2, 1, 0); // ①</span><br><span class="line"> Bicycle bike2 = new Bicycle(2, 0, 1); // ②</span><br><span class="line"> var bike3 = Bicycle(2, 0, 1); // ③</span><br><span class="line"> final bike4 = Bicycle(2, 0, 1); // ④</span><br><span class="line"></span><br><span class="line"> print(bike1)</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>以上四种实例化方式都是允许的,其中:第二种方式指明类型会加快编译速度,第一种并没有指明类型;在Dart 2之后new可以省略(也就是第三种方式);如果明确<code>bike4</code>是不变的则可以使用final代替var(第四种方式)。<br><code>print()</code>就如同Java中的<code>System.out.print()</code>,这里打印结果是<code>Instance of 'Bicycle'</code>,如果想要打印具体的信息,需要重写<code>toString()</code>方法(思想与Java一致):</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">@override</span><br><span class="line">String toString() => 'Bicycle: $speed mph';</span><br></pre></td></tr></table></figure><p>这里的重写代码也是有点独特:</p><ol><li><code>@overrid</code>同Java一致,表明这是重写类方法,Java中字母o是大写</li><li>字符串支持单引号或双引号进行表示</li><li>如果要在字符串中插入表达式,则可以使用 <code>${表达式}</code>,如果是插入成员变量值,可以直接使用 <code>$成员变量</code></li><li>上面包含了一个<code>=></code>,该符号表示,<strong>当方法的实现只有一行代码的时候可以使用<code>=></code>简写</strong>。</li></ol><h3 id="2-5-添加只读成员变量"><a href="#2-5-添加只读成员变量" class="headerlink" title="2.5 添加只读成员变量"></a>2.5 添加只读成员变量</h3><p>并不是所有类成员变量都是对外开放的,有时可能会需要一些私有的成员变量,例如将<code>Bicycle</code>的<code>speed</code>属性定义为私有的,在Java的实现方式便是:</p><ol><li>将speed成员变量使用private修饰;</li><li>提供speed的getter方法;</li></ol><p>而Dart并没有访问修饰词(默认都是public),那如何表示私有化呢?答案是<strong>命名使用下划线</strong>,如下:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">int _speed = 0;</span><br><span class="line">## getter</span><br><span class="line">int get speed => _speed;</span><br></pre></td></tr></table></figure><p>注意:</p><ol><li>未初始化的成员变量默认值都为<code>null</code>,即使是表示数值的变量</li><li>Dart编译器会把以下划线开头的成员变量认定为私有private</li><li>默认地,Dart为所有public的成员变量隐式提供了对应的setter和getter方法,我们不需要特地去编写对应的setter和getter,除非将变量强制为只读 or 只写,或者在getter or setter中添加额外的操作等。</li><li>因为默认成员变量为public,例如<code>Bicycle</code>类的<code>cadence</code>和<code>gear</code>,所以直接通过<code>bike.cadence</code>和<code>bike.gear</code>进行访问</li></ol><p>最后,将speed定义为私有后的<code>Bicycle</code>类:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line">class Bicycle {</span><br><span class="line"> int cadence;</span><br><span class="line"> int _speed = 0;</span><br><span class="line"> int get speed => _speed;</span><br><span class="line"> int gear;</span><br><span class="line"></span><br><span class="line"> // 构造方法</span><br><span class="line"> Bicycle(this.cadence, this.gear);</span><br><span class="line"></span><br><span class="line"> // 刹车</span><br><span class="line"> void applyBrake(int decrement) {</span><br><span class="line"> _speed -= decrement;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> // 加速</span><br><span class="line"> void speedUp(int increment) {</span><br><span class="line"> _speed += increment;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> @override</span><br><span class="line"> String toString() => 'Bicycle: $_speed mph';</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">void main() {</span><br><span class="line"> var bike = Bicycle(2, 1);</span><br><span class="line"> print(bike);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="3-可选命名参数(替代重载)"><a href="#3-可选命名参数(替代重载)" class="headerlink" title="3. 可选命名参数(替代重载)"></a>3. 可选命名参数(替代重载)</h2><p>在Java中,经常会重载方法:也就是编写具有相同函数名,但参数列表不同的多个方法。而Dart<strong>不允许重载</strong>,并通过可选命名参数代替了重载。<br>现在定义一个矩形类<code>Rectangle</code>,包含三个成员变量:<code>origin</code>、<code>width</code>和<code>height</code>:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">class Rectangle {</span><br><span class="line"> Point origin;</span><br><span class="line"> int width;</span><br><span class="line"> int height;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>如何通过可选命名参数来代替重载,我们以构造方法为例:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Rectangle({this.origin = const Point(0, 0), this.width = 0, this.height = 0});</span><br></pre></td></tr></table></figure><p>注意可选命名参数必须包含在花括号中<code>{ }</code>,且指定的默认值必须是编译期常量(也就是编译期便可确定值)。又例如:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">// 其中x、y为可选命名参数,r不是</span><br><span class="line">void move(int r, {int x = 10, int y = 20}) {</span><br><span class="line"> this.width += x;</span><br><span class="line"> this.height += y;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>使用可选命名参数的方法,在调用时<strong>可选命名参数必须指明赋值的局部变量</strong>,而非可选命名参数则不需要:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">void main() {</span><br><span class="line"> // origin是可选命名参数,为其赋值必须在前面指明: origin</span><br><span class="line"> // width和height同理</span><br><span class="line"> print(Rectangle(origin: const Point(10, 20), width: 100, height: 200));</span><br><span class="line"> print(Rectangle(origin: const Point(10, 10)));</span><br><span class="line"> print(Rectangle(width: 200));</span><br><span class="line"> print(Rectangle());</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="4-创建工厂模式"><a href="#4-创建工厂模式" class="headerlink" title="4. 创建工厂模式"></a>4. 创建工厂模式</h2><p>这一小节将介绍两种创建Shape的工厂,先介绍一下Shape类:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line">import 'dart:math';</span><br><span class="line">// 抽象类</span><br><span class="line">abstract class Shape {</span><br><span class="line"> // num表示数据类型是数值,可以为int、float或short等</span><br><span class="line"> // 定义一个获取面积的getter方法</span><br><span class="line"> num get area;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">// 圆</span><br><span class="line">class Circle implements Shape {</span><br><span class="line"> final num radius;</span><br><span class="line"> Circle(this.radius);</span><br><span class="line"> num get area => pi * pow(radius, 2);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">// 正方形</span><br><span class="line">class Square implements Shape {</span><br><span class="line"> final num side;</span><br><span class="line"> Square(this.side);</span><br><span class="line"> num get area => pow(side, 2);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">main() {</span><br><span class="line"> final circle = Circle(2);</span><br><span class="line"> final square = Square(2);</span><br><span class="line"> print(circle.area);</span><br><span class="line"> print(square.area);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>上面的代码中:</p><ul><li>Dart支持抽象类(abstract)</li><li>在同一个文件中能够定义多个class</li><li>Dart的核心库包括了:<code>dart.math</code>、<code>dart:core</code>、<code>dart:async</code>、<code>dart:convert</code>和<code>dart:collection</code></li><li>在Dart 1.x版本常量均为大写(例如PI),在Dart 2都改为小写(例如pi)</li></ul><p>接下来介绍一下创建工厂模式两种方式。</p><h3 id="4-1-顶层方法"><a href="#4-1-顶层方法" class="headerlink" title="4.1 顶层方法"></a>4.1 顶层方法</h3><p>在<strong>所有类的外部</strong>创建一个工厂方法:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">Shape shapeFactory(String type) {</span><br><span class="line"> if (type == 'circle') return Circle(2);</span><br><span class="line"> if (type == 'square') return Square(2);</span><br><span class="line"> // 如果参数type不是'circle'或'square'将会抛出异常</span><br><span class="line"> // 如果想在字符串中添加单引号,可以使用反斜杠\,或整个字符串使用双引号表示</span><br><span class="line"> throw 'Can\'t create $type.'; }</span><br><span class="line"></span><br><span class="line">// 前面的main方法就可以改写为:</span><br><span class="line">main() {</span><br><span class="line"> final circle = shapeFactory('circle');</span><br><span class="line"> final square = shapeFactory('square');</span><br><span class="line"> print(circle.area);</span><br><span class="line"> print(square.area);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>说明一下:</p><ol><li>Dart同Java一样能够抛出异常,也定义了很多常用的异常类,我们能够继承、使用这些常用的异常类。</li><li>Dart支持通过throw一个字符串表示遇到的异常信息:<code>throw 'Occurred NPE'</code></li><li>Dart同样使用try/catch来进行异常的捕获: <figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">try {</span><br><span class="line"> // exception occurred</span><br><span class="line">} catch(err) {</span><br><span class="line"> print(err);</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li></ol><h3 id="4-2-工厂构造器"><a href="#4-2-工厂构造器" class="headerlink" title="4.2 工厂构造器"></a>4.2 工厂构造器</h3><p>Dart提供了<code>factory</code>关键字用于创建工厂构造器。下面在<code>Shape</code>的抽象类中添加一个工厂构造器:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">abstract class Shape {</span><br><span class="line"> factory Shape(String type) {</span><br><span class="line"> if (type == 'circle') return Circle(2);</span><br><span class="line"> if (type == 'square') return Square(2);</span><br><span class="line"> throw 'Can\'t create $type.';</span><br><span class="line"> }</span><br><span class="line"> num get area;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">main() {</span><br><span class="line"> // 调用工厂构造器,通过创建Shape对象即可</span><br><span class="line"> final circle = Shape('circle');</span><br><span class="line"> final square = Shape('square');</span><br><span class="line"> print(circle.area);</span><br><span class="line"> print(square.area);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="5-实现接口"><a href="#5-实现接口" class="headerlink" title="5. 实现接口"></a>5. 实现接口</h2><p>Dart同样也有接口的思想,但Dart并没有<code>interface</code>的关键字,因为<strong>每个类都被定义为接口</strong>,也就是一个类,既能被当成父类进行继承extends,也能当做接口进行实现implements:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">class A {</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">// 此时A作为父类被继承</span><br><span class="line">class B extends A {</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">// 此时A作为接口被实现</span><br><span class="line">class C implements A {</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>我们定义一个<code>CircleMock</code>实现我们上面的<code>Circle</code>类:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">class Circle implements Shape {</span><br><span class="line"> final num radius;</span><br><span class="line"> Circle(this.radius);</span><br><span class="line"> num get area => pi * pow(radius, 2);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">class CircleMock implements Circle {}</span><br></pre></td></tr></table></figure><p>此时DartPad会提示编译错误:<code>Error: The non-abstract class 'CircleSub' is missing implementations for these members: 'radius', 'area'.</code>,编译出错可以这么理解:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">// Circle被作为了接口实现</span><br><span class="line">class Circle implements Shape {</span><br><span class="line"> // num radius、num get area被视为接口中的方法,需要被实现</span><br><span class="line"> final num radius;</span><br><span class="line"> num get area => pi * pow(radius, 2);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">class CircleMock implements Circle {</span><br><span class="line"> // 可以通过定义相关的成员变量,编译器也不会报错(这里有点莫名其妙啊)</span><br><span class="line"> num area;</span><br><span class="line"> num radius;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="6-函数式编程"><a href="#6-函数式编程" class="headerlink" title="6. 函数式编程"></a>6. 函数式编程</h2><p>在函数式编程中,可以把方法作为为参数、将方法赋值给变量、支持lambda表达式。<br>Dart支持函数式编程,所以也支持以上提到的特点,此外,Dart中<strong>方法也是一个对象,且具有对应的类型Function</strong>,因此Dart中可以将方法赋值给变量或传递给参数。</p><h3 id="6-1-类实例作为方法调用"><a href="#6-1-类实例作为方法调用" class="headerlink" title="6.1 类实例作为方法调用"></a>6.1 类实例作为方法调用</h3><p>Dart还可以将类实例作为方法一样调用(但该类必须包含<code>call()</code>方法),例如:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">class WannabeFunction {</span><br><span class="line"> // call方法返回值为void,省略了void</span><br><span class="line"> call(String a, String b, String c) => '$a $b $c!';</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">main() {</span><br><span class="line"> var wf = new WannabeFunction();</span><br><span class="line"> // 将WannabeFunction类的实例wf作为方法一样调用,此时调用的是WannabeFunction类中的call方法</span><br><span class="line"> var out = wf("Hi","there,","gang");</span><br><span class="line"> print('$out');</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="6-2-命令式代码(非功能性)"><a href="#6-2-命令式代码(非功能性)" class="headerlink" title="6.2 命令式代码(非功能性)"></a>6.2 命令式代码(非功能性)</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">String scream(int length) => "A${'a' * length}h!";</span><br><span class="line"></span><br><span class="line">main() {</span><br><span class="line"> final values = [1, 2, 3, 5, 10, 50];</span><br><span class="line"> for (var length in values) {</span><br><span class="line"> print(scream(length));</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>打印的结果是:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">Aah!</span><br><span class="line">Aaah!</span><br><span class="line">Aaaah!</span><br><span class="line">Aaaaaah!</span><br><span class="line">Aaaaaaaaaaah!</span><br><span class="line">Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaah!</span><br></pre></td></tr></table></figure><p>上面使用了字符串插值器<code>A${'a' * length}h!</code>,表示将<code>a</code>字母重复<code>length</code>次。</p><h3 id="6-3-将命令式代码转化为功能性代码"><a href="#6-3-将命令式代码转化为功能性代码" class="headerlink" title="6.3 将命令式代码转化为功能性代码"></a>6.3 将命令式代码转化为功能性代码</h3><p>我们将上面的代码的<code>for(){ }</code>循环使用方法链的形式进行替换:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">String scream(int length) => "A${'a' * length}h!";</span><br><span class="line"></span><br><span class="line">main() {</span><br><span class="line"> final values = [1, 2, 3, 5, 10, 50];</span><br><span class="line"> // for (var length in values) {</span><br><span class="line"> // print(scream(length));</span><br><span class="line"> // }</span><br><span class="line"> values.map(scream).forEach(print); // 下面解释该行代码</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>上面的代码挺难理解的,可以这么理解:</p><ol><li><code>map</code>可以理解为一个迭代器,<code>values.map()</code>便是对<code>values</code>中的数值进行迭代,迭代所做的操作就交由<code>map()</code>方法的参数,这里传入的就是<code>scream</code>,也就是<code>scream()</code>方法,用Java代码表示便是: <figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">// for相当于map,进行迭代</span><br><span class="line">for (int val : values) {</span><br><span class="line"> // map()的参数便是对迭代进行的操作</span><br><span class="line"> // 这里便是调用scream()方法,因为函数式编程中方法可以作为参数进行传递</span><br><span class="line"> scream(val);</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li><li><code>forEach()</code>可以理解为对处理结果进行的最后操作,例如打印(传入<code>print</code>方法)。<code>forEach()</code>这个在Java 8也已支持。</li><li>综上,<code>values.map(scream).forEach(print);</code>这行代码意思便是,对<code>values</code>进行遍历,对其中每一个值进行<code>scream()</code>处理,然后调用<code>print()</code>进行处理后的最后操作。</li></ol><h3 id="6-4-集合的新功能点"><a href="#6-4-集合的新功能点" class="headerlink" title="6.4 集合的新功能点"></a>6.4 集合的新功能点</h3><p>Dart在<code>dart:collection</code>库中还包含了一些迭代的新功能点,例如<code>fold</code>、<code>where</code>、<code>join</code>和<code>skip</code>等:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">// values.map(scream).forEach(print);</span><br><span class="line">values.skip(1).take(3).map(scream).forEach(print);</span><br></pre></td></tr></table></figure><p>打印的结果:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Aaah!</span><br><span class="line">Aaaah!</span><br><span class="line">Aaaaaah!</span><br></pre></td></tr></table></figure><p>其中:</p><ul><li><code>skip(1)</code>表示遍历<code>values</code>时跳过第一个</li><li><code>take(3)</code>表示遍历时,获取接下来的三个值,剩下的值忽略掉</li><li><code>map()</code>和<code>forEach()</code>如上面解释,进行遍历和处理</li></ul><h2 id="7-写在最后"><a href="#7-写在最后" class="headerlink" title="7. 写在最后"></a>7. 写在最后</h2><p>以上是关于Java和Dart的一些区别,只要会Java上手Dart应该还是比较简单的。但上面也只讲了一小部分内容,尚未包括异步/同步、方法级联、Null操作。<br>当然,笔者个人觉得,并不需要要完全学习完Dart才能上手Flutter,学习一下基本的Dart,在Flutter中一边摸索中一边学习Dart应该是最合适的。<br>codelabs上面还提供了一些学习的链接:<br>文章:</p><ul><li><span class="exturl" data-url="aHR0cHM6Ly9oYWNrZXJub29uLmNvbS93aHktZmx1dHRlci11c2VzLWRhcnQtZGQ2MzVhMDU0ZWJm">Why Flutter Uses Dart<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly9tZWRpdW0uY29tL2RhcnRsYW5nL2Fubm91bmNpbmctZGFydC0yLTgwYmEwMWY0M2I2">Announcing Dart 2: Optimized for Client-Side Development<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly9oYWNrZXJub29uLmNvbS93aHktaS1tb3ZlZC1mcm9tLWphdmEtdG8tZGFydC04ZjM4MDJiMWQ2NTI=">Why I moved from Java to Dart<i class="fa fa-external-link-alt"></i></span></li></ul><p>资源:</p><ul><li><span class="exturl" data-url="aHR0cHM6Ly93d3cuZGFydGxhbmcub3JnL2d1aWRlcy9sYW5ndWFnZS9sYW5ndWFnZS10b3Vy">A Tour of the Dart Language<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly93d3cuZGFydGxhbmcub3JnL2d1aWRlcy9saWJyYXJpZXMvbGlicmFyeS10b3Vy">A Tour of the Dart Libraries<i class="fa fa-external-link-alt"></i></span></li><li><span class="exturl" data-url="aHR0cHM6Ly93d3cuZGFydGxhbmcub3JnL2d1aWRlcy9sYW5ndWFnZS9lZmZlY3RpdmUtZGFydA==">Effective Dart<i class="fa fa-external-link-alt"></i></span></li></ul><p>网页:</p><ul><li>Dart Language: <span class="exturl" data-url="aHR0cHM6Ly93d3cuZGFydGxhbmcub3JnLw==">www.dartlang.org<i class="fa fa-external-link-alt"></i></span></li><li>Dart for the web, including AngularDart: <span class="exturl" data-url="aHR0cHM6Ly93ZWJkZXYuZGFydGxhbmcub3JnLw==">webdev.dartlang.org<i class="fa fa-external-link-alt"></i></span></li><li>Flutter mobile app SDK: <span class="exturl" data-url="aHR0cHM6Ly9mbHV0dGVyLmlvLw==">flutter.io<i class="fa fa-external-link-alt"></i></span></li></ul>]]></content>
<summary type="html"><p>如果你是一名Java开发人员,可以通过 <span class="exturl" data-url="aHR0cHM6Ly9jb2RlbGFicy5kZXZlbG9wZXJzLmdvb2dsZS5jb20vY29kZWxhYnMvZnJvbS1qYXZhLXRvLWRhcnQvaW5kZXguaHRtbCMw">codelabs<i class="fa fa-external-link-alt"></i></span> 快速入门Dart。</p>
<h2 id="1-简介"><a href="#1-简介" class="headerlink" title="1. 简介"></a>1. 简介</h2><p>Dart是一门用于Flutter的编程语言,而Flutter是Google开发的移动应用SDK。 </p>
<p>阅读本文,你将学习到:</p>
<ul>
<li>如何编写构造方法</li>
<li>为对象赋值的多种方式</li>
<li>如何 &amp; 何时创建getter和setter</li>
<li>如何处理访问权限</li>
<li>如何创建工厂模式</li>
<li>函数式编程</li>
<li>其他主要的概念</li>
</ul>
<p>此外,codelabs提供了 <span class="exturl" data-url="aHR0cHM6Ly9kYXJ0cGFkLmRhcnRsYW5nLm9yZy8=">DartPad<i class="fa fa-external-link-alt"></i></span> 供大家编写Dart代码。</p></summary>
<category term="Dart" scheme="https://yaodev.site/categories/Dart/"/>
<category term="Dart" scheme="https://yaodev.site/tags/Dart/"/>
<category term="Flutter" scheme="https://yaodev.site/tags/Flutter/"/>
<category term="Android" scheme="https://yaodev.site/tags/Android/"/>
</entry>
<entry>
<title>Ubuntu16.04安装VMWare Workstation</title>
<link href="https://yaodev.site/2018/03/07/Ubuntu16.04%E5%AE%89%E8%A3%85VMWare%20Workstation/"/>
<id>https://yaodev.site/2018/03/07/Ubuntu16.04%E5%AE%89%E8%A3%85VMWare%20Workstation/</id>
<published>2018-03-07T08:02:00.000Z</published>
<updated>2023-12-17T03:42:25.707Z</updated>
<content type="html"><![CDATA[<h2 id="一、安装过程"><a href="#一、安装过程" class="headerlink" title="一、安装过程"></a>一、安装过程</h2><h3 id="1-安装开发工具"><a href="#1-安装开发工具" class="headerlink" title="1. 安装开发工具"></a>1. 安装开发工具</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">sudo apt install build-essential</span></span><br></pre></td></tr></table></figure><h3 id="2-下载"><a href="#2-下载" class="headerlink" title="2. 下载"></a>2. 下载</h3><p>从VMWare的官网<span class="exturl" data-url="aHR0cDovL3d3dy52bXdhcmUuY29tL2dvL3RyeXdvcmtzdGF0aW9uLWxpbnV4LTY0">http://www.vmware.com/go/tryworkstation-linux-64<i class="fa fa-external-link-alt"></i></span> 下载,文件类型是<code>.bundle</code>。<br>此时下载的版本是Vmware Workstation 14。</p><span id="more"></span><h3 id="3-安装VMWare"><a href="#3-安装VMWare" class="headerlink" title="3. 安装VMWare"></a>3. 安装VMWare</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash"><span class="built_in">chmod</span> a+x VMware-Workstation-Full-14.1.1-7528167.x86_64.bundle</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">sudo ./VMware-Workstation-Full-14.1.1-7528167.x86_64.bundle</span></span><br></pre></td></tr></table></figure><p>执行后会出现VMWare的安装窗口,需要同意协议、选择是否在启动时检查更新等操作,最后安装完成。</p><h3 id="4-启动VMWare"><a href="#4-启动VMWare" class="headerlink" title="4. 启动VMWare"></a>4. 启动VMWare</h3><p>在终端启动,或者在菜单启动</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">vmware</span></span><br></pre></td></tr></table></figure><h3 id="5-激活密钥"><a href="#5-激活密钥" class="headerlink" title="5. 激活密钥"></a>5. 激活密钥</h3><p>网上找的VMware workstation 14永久激活密钥:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">CG54H-D8D0H-H8DHY-C6X7X-N2KG6</span><br><span class="line">ZC3WK-AFXEK-488JP-A7MQX-XL8YF</span><br><span class="line">AC5XK-0ZD4H-088HP-9NQZV-ZG2R4</span><br><span class="line">ZC5XK-A6E0M-080XQ-04ZZG-YF08D</span><br><span class="line">ZY5H0-D3Y8K-M89EZ-AYPEG-MYUA8</span><br><span class="line">FF590-2DX83-M81LZ-XDM7E-MKUT4</span><br><span class="line">FF31K-AHZD1-H8ETZ-8WWEZ-WUUVA</span><br><span class="line">CV7T2-6WY5Q-48EWP-ZXY7X-QGUWD</span><br><span class="line">AALYG-20HVE-WHQ13-67MUP-XVMF3</span><br></pre></td></tr></table></figure><h3 id="6-卸载VMWare"><a href="#6-卸载VMWare" class="headerlink" title="6. 卸载VMWare"></a>6. 卸载VMWare</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">sudo vmware-installer --uninstall-product vmware-workstation</span></span><br></pre></td></tr></table></figure><hr><h2 id="二、解决could-not-open-dev-vmmon-no-such-file-or-directory问题"><a href="#二、解决could-not-open-dev-vmmon-no-such-file-or-directory问题" class="headerlink" title="二、解决could not open /dev/vmmon no such file or directory问题"></a>二、解决could not open /dev/vmmon no such file or directory问题</h2><h3 id="1-方法1"><a href="#1-方法1" class="headerlink" title="1. 方法1"></a>1. 方法1</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash"><span class="built_in">cd</span> /tmp</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">tar -xzvf /usr/lib/vmware/modules/source/vmmon.tar</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash"><span class="built_in">cd</span> vmmon-only/</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">make</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">sudo <span class="built_in">cp</span> vmmon.ko /lib/modules/4.4.0-116-generic/misc/vmmon.ko</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">sudo modprobe vmmon</span></span><br></pre></td></tr></table></figure><p>如果执行tar解压时候出现:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">gzip: stdin: not in gzip format</span><br><span class="line">tar: Child returned status 1</span><br><span class="line">tar: Error is not recoverable: exiting now</span><br></pre></td></tr></table></figure><p>则将上面<code>tar -xzvf /usr/lib/vmware/modules/source/vmmon.tar</code>命令改为:<code>tar xvf /usr/lib/vmware/modules/source/vmmon.tar</code></p><p>执行完上面的步骤之后,启动虚拟机,看是否解决了问题。</p><p><strong>参考:</strong><span class="exturl" data-url="aHR0cHM6Ly9jb21tdW5pdGllcy52bXdhcmUuY29tL21lc3NhZ2UvMjQ0Mjc4Mw==">https://communities.vmware.com/message/2442783<i class="fa fa-external-link-alt"></i></span></p><h3 id="2-方法2"><a href="#2-方法2" class="headerlink" title="2. 方法2"></a>2. 方法2</h3><p>可能出现的原因和gcc版本有关,所以查看自己gcc的版本:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">gcc --version</span></span><br><span class="line">gcc (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609</span><br><span class="line">Copyright (C) 2015 Free Software Foundation, Inc.</span><br><span class="line">This is free software; see the source for copying conditions. There is NO</span><br><span class="line">warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.</span><br></pre></td></tr></table></figure><p>如果gcc版本太低,例如4.5(4.6及以上应该没问题),则安装新版本的gcc,例如:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">sudo apt install gcc-5</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">sudo <span class="built_in">rm</span> /usr/bin/gcc</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">sudo <span class="built_in">ln</span> -s /usr/bin/gcc-5 /usr/bin/gcc</span></span><br></pre></td></tr></table></figure><p>确认更新gcc版本之后,执行:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">sudo vmware-modconfig --console --install-all</span></span><br></pre></td></tr></table></figure><p>如果最后出现以下结果则表示成功。</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">Starting VMware services:</span><br><span class="line"> Virtual machine monitor done</span><br><span class="line"> Virtual machine communication interface done</span><br><span class="line"> VM communication interface socket family done</span><br><span class="line"> Blocking file system done</span><br><span class="line"> Virtual ethernet done</span><br><span class="line"> VMware Authentication Daemon done</span><br><span class="line"> Shared Memory Available done</span><br></pre></td></tr></table></figure><p>如果最后执行结果中出现了如下的failed,则<strong>关闭BIOS中的secure boot</strong>,然后再执行:<code>sudo vmware-modconfig --console --install-all</code></p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">Starting VMware services:</span><br><span class="line"> Virtual machine monitor failed</span><br><span class="line"> Virtual machine communication interface done</span><br><span class="line"> VM communication interface socket family done</span><br><span class="line"> Blocking file system done</span><br><span class="line"> Virtual ethernet failed</span><br><span class="line"> VMware Authentication Daemon done</span><br><span class="line"> Shared Memory Available done</span><br></pre></td></tr></table></figure><p><strong>参考:</strong><span class="exturl" data-url="aHR0cHM6Ly9jb21tdW5pdGllcy52bXdhcmUuY29tL21lc3NhZ2UvMjYxMTUxNyMyNjExNTE3">https://communities.vmware.com/message/2611517#2611517<i class="fa fa-external-link-alt"></i></span></p>]]></content>
<summary type="html"><h2 id="一、安装过程"><a href="#一、安装过程" class="headerlink" title="一、安装过程"></a>一、安装过程</h2><h3 id="1-安装开发工具"><a href="#1-安装开发工具" class="headerlink" title="1. 安装开发工具"></a>1. 安装开发工具</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">sudo apt install build-essential</span></span><br></pre></td></tr></table></figure>
<h3 id="2-下载"><a href="#2-下载" class="headerlink" title="2. 下载"></a>2. 下载</h3><p>从VMWare的官网<span class="exturl" data-url="aHR0cDovL3d3dy52bXdhcmUuY29tL2dvL3RyeXdvcmtzdGF0aW9uLWxpbnV4LTY0">http://www.vmware.com/go/tryworkstation-linux-64<i class="fa fa-external-link-alt"></i></span> 下载,文件类型是<code>.bundle</code>。<br>此时下载的版本是Vmware Workstation 14。</p></summary>
<category term="Ubuntu" scheme="https://yaodev.site/categories/Ubuntu/"/>
<category term="Ubuntu" scheme="https://yaodev.site/tags/Ubuntu/"/>
<category term="VMWare Workstation" scheme="https://yaodev.site/tags/VMWare-Workstation/"/>
</entry>
<entry>
<title>Ubuntu搭载Android开发环境(无需翻墙)</title>
<link href="https://yaodev.site/2017/11/27/Ubuntu%E6%90%AD%E8%BD%BDAndroid%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%EF%BC%88%E6%97%A0%E9%9C%80%E7%BF%BB%E5%A2%99%EF%BC%89/"/>
<id>https://yaodev.site/2017/11/27/Ubuntu%E6%90%AD%E8%BD%BDAndroid%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%EF%BC%88%E6%97%A0%E9%9C%80%E7%BF%BB%E5%A2%99%EF%BC%89/</id>
<published>2017-11-27T11:27:00.000Z</published>
<updated>2023-12-17T12:08:16.016Z</updated>
<content type="html"><![CDATA[<h2 id="一、相关下载的地址"><a href="#一、相关下载的地址" class="headerlink" title="一、相关下载的地址"></a>一、相关下载的地址</h2><ol><li>sdk下载</li></ol><ul><li>郑州大学:<span class="exturl" data-url="aHR0cHM6Ly9taXJyb3JzLnp6dS5lZHUuY24vYW5kcm9pZC9yZXBvc2l0b3J5Lw==">https://mirrors.zzu.edu.cn/android/repository/<i class="fa fa-external-link-alt"></i></span></li><li>大连东软信息学院:<span class="exturl" data-url="aHR0cDovL21pcnJvcnMubmV1c29mdC5lZHUuY24vYW5kcm9pZC9yZXBvc2l0b3J5Lw==">http://mirrors.neusoft.edu.cn/android/repository/<i class="fa fa-external-link-alt"></i></span></li></ul><ol start="2"><li>Android studio</li></ol><ul><li>Android Studio 中文社区(官网):<span class="exturl" data-url="aHR0cDovL3d3dy5hbmRyb2lkLXN0dWRpby5vcmcv">http://www.android-studio.org/<i class="fa fa-external-link-alt"></i></span></li></ul><span id="more"></span><hr><h2 id="二、下载SDK相关包"><a href="#二、下载SDK相关包" class="headerlink" title="二、下载SDK相关包"></a>二、下载SDK相关包</h2><p>新建SDK目录,SDK的目录下面用<code>$SDK</code>表示:</p><ol><li>在<code>$SDK</code>下新建**<code>build-tools</code>、<code>tools</code>、<code>platform-tools</code>、<code>platforms</code>**四个文件夹。</li><li>下载**<code>build-tools</code>**</li></ol><ul><li>找到对应的平台,例如linux、macosx、windows等</li><li>解压下载的zip包,解压后得到<code>android-6.0</code>或<code>23.0.1</code>,<strong>放到<code>$SDK/build-tools/</code>目录下</strong></li></ul><ol start="3"><li>下载**<code>sdk tools</code>**</li></ol><ul><li>找到对应的平台,例如linux、macosx、windows等</li><li>解压下载的zip包,解压后得到<code>tools</code>,<strong>直接放到<code>$SDK/</code>目录下</strong></li></ul><ol start="4"><li>下载**<code>platform-tools</code>**</li></ol><ul><li>找到对应的平台,例如linux、macosx、windows等</li><li>解压下载的zip包,解压后得到<code>platform-tools</code>,<strong>直接放到<code>$SDK/</code>目录下</strong></li></ul><ol start="5"><li>下载**<code>sdk</code>**</li></ol><ul><li>找到对应API的zip包,例如<code>android-23_r02.zip</code>(23_r03之前名字)或<code>platform-23_r03.zip</code>(23_r03及之后的名字),不分平台</li><li>解压下载的zip包,解压后得到<code>android-6.0</code>,<strong>放到<code>$SDK/platforms/</code>目录下</strong></li></ul><hr><h2 id="三、安装Android-Studio"><a href="#三、安装Android-Studio" class="headerlink" title="三、安装Android Studio"></a>三、安装Android Studio</h2><ol><li>解压Android Studio的压缩包,Studio的目录下面用<code>$STUDIO</code>表示</li><li>cd到<code>$STUDIO/bin</code>目录,通过<code>./studio.sh</code>启动Studio</li></ol><ul><li>如果启动Studio的时出现<code>Unable to access android sdk add-on list</code>的问题,在<code>$STUDIO/bin/idea.properties</code>文件末尾添加:<code>disable.android.first.run=true</code>即可。</li></ul><ol start="3"><li>进入Studio。</li></ol><hr><h2 id="四、其他问题"><a href="#四、其他问题" class="headerlink" title="四、其他问题"></a>四、其他问题</h2><p>说明:Studio的log文件在用户目录下<code>$HOME/.AndroidStudio2.3/system/log</code>中,其中目录可能因为Studio的版本不同而名字不同,例如<code>.AndroidStudioPreview3.1</code>。有问题均可查看该日志文件。</p><ol><li><code>Error:Failed to find target with hash string 'android-26' in $SDK</code>的问题<br> 这个问题很可能是因为<code>compileSdkVersion</code>设置为26,也就是<code>platforms</code>目录下缺少Android8.0(API 26)。下载API 26并解压到<code>platforms</code>目录下即可。</li><li><code>Error:Failed to find Build Tools revision 27.0.1</code><br> 缺少build-tools 27.0.1的版本,下载对应的zip包,解压到<code>build-tools</code>即可</li></ol>]]></content>
<summary type="html"><h2 id="一、相关下载的地址"><a href="#一、相关下载的地址" class="headerlink" title="一、相关下载的地址"></a>一、相关下载的地址</h2><ol>
<li>sdk下载</li>
</ol>
<ul>
<li>郑州大学:<span class="exturl" data-url="aHR0cHM6Ly9taXJyb3JzLnp6dS5lZHUuY24vYW5kcm9pZC9yZXBvc2l0b3J5Lw==">https://mirrors.zzu.edu.cn/android/repository/<i class="fa fa-external-link-alt"></i></span></li>
<li>大连东软信息学院:<span class="exturl" data-url="aHR0cDovL21pcnJvcnMubmV1c29mdC5lZHUuY24vYW5kcm9pZC9yZXBvc2l0b3J5Lw==">http://mirrors.neusoft.edu.cn/android/repository/<i class="fa fa-external-link-alt"></i></span></li>
</ul>
<ol start="2">
<li>Android studio</li>
</ol>
<ul>
<li>Android Studio 中文社区(官网):<span class="exturl" data-url="aHR0cDovL3d3dy5hbmRyb2lkLXN0dWRpby5vcmcv">http://www.android-studio.org/<i class="fa fa-external-link-alt"></i></span></li>
</ul></summary>
<category term="Ubuntu" scheme="https://yaodev.site/categories/Ubuntu/"/>
<category term="Android" scheme="https://yaodev.site/tags/Android/"/>
<category term="Ubuntu" scheme="https://yaodev.site/tags/Ubuntu/"/>
<category term="开发环境" scheme="https://yaodev.site/tags/%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83/"/>
</entry>
<entry>
<title>wine安装最新版QQ</title>
<link href="https://yaodev.site/2017/11/26/wine%E5%AE%89%E8%A3%85%E6%9C%80%E6%96%B0%E7%89%88QQ/"/>
<id>https://yaodev.site/2017/11/26/wine%E5%AE%89%E8%A3%85%E6%9C%80%E6%96%B0%E7%89%88QQ/</id>
<published>2017-11-26T11:27:00.000Z</published>
<updated>2023-12-17T12:08:40.307Z</updated>
<content type="html"><![CDATA[<p><strong>注意:无需继续使用该方法在 Linux 上安装 QQ 了,官方已经正式支持 LinuxQQ:<span class="exturl" data-url="aHR0cHM6Ly9pbS5xcS5jb20vbGludXhxcS9pbmRleC5zaHRtbA==">QQ Linux版下载<i class="fa fa-external-link-alt"></i></span></strong></p><span id="more"></span><h2 id="1-安装wine"><a href="#1-安装wine" class="headerlink" title="1. 安装wine"></a>1. 安装wine</h2><p>本次教程只需要安装最新版本的wine,并不需要<code>winetricks</code>、<code>wine-mono</code>、<code>wine-gecko</code>等其他插件,目前经实际测试发现只运行WineQQ可以不需要<code>wine-mono</code>、<code>wine-gecko</code>、<code>W2KSP4.exe</code>、<code>InstMsiW.exe</code>等。</p><p>安装wine步骤如下:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">sudo dpkg --add-architecture i386</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">wget https://dl.winehq.org/wine-builds/Release.key</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">sudo apt-key add Release.key</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">sudo apt-add-repository https://dl.winehq.org/wine-builds/ubuntu/</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">sudo apt-get update</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">sudo apt-get install --install-recommends winehq-stable</span></span><br></pre></td></tr></table></figure><p>至此wine安装完成,可以通过<code>wine --version</code>查看版本号(此时安装的是wine2.0.3)。</p><p>接下来需要执行<code>winecfg</code>来配置wine,接着会弹出安装<code>wine-mono</code>和<code>wine-gecko</code>的窗口,可以不用安装,关掉即可。</p><hr><h2 id="2-配置wine"><a href="#2-配置wine" class="headerlink" title="2. 配置wine"></a>2. 配置wine</h2><ol><li>执行<code>winecfg</code>打开wine的配置窗口</li><li>点击<code>Libraries</code><br><br> <img src="/images/wine%E5%AE%89%E8%A3%85%E6%9C%80%E6%96%B0%E7%89%88QQ/winecfg%E9%85%8D%E7%BD%AE.png" alt="winecfg配置"></li><li>在<code>New override for library</code>中分别输入<code>*ntoskrnl.exe</code>、<code>*riched20</code>、<code>*txplatform.exe</code>,然后回车(名字前的<code>*</code>号可以省略)。</li><li>在<code>Existing_overrides</code>新出现的<code>*ntoskrnl.exe</code>和<code>*txplatform.exe</code>,分别点击<code>Edit</code>,均选择<code>Disable</code>;<code>*riched20</code>点击<code>Edit</code>,选择<code>native then builtin</code></li></ol><ul><li>如果不配置riched20的话则安装好QQ后无法输入用户名</li><li>不停用txplatform.exe则WineQQ无法完整退出,导致关掉重开后提示QQ文件被占用</li><li>禁用ntoskrnl.exe是为了规避可能出现QQ无法启动的bug。</li></ul><hr><h2 id="3-解决乱码问题"><a href="#3-解决乱码问题" class="headerlink" title="3. 解决乱码问题"></a>3. 解决乱码问题</h2><ol><li>初始配置<br> 运行<code>winecfg</code>,在<code>Applications</code>标签下把模拟的windows系统设置为windows xp</li><li>准备字体<br> 把Windows目录下的字体<code>simsun.ttc</code>复制到<code>/usr/share/fonts/windows</code>里面</li><li>在<code>~/.wine/drive_c/windows/Fonts</code>目录中创建两个符号链接: <figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash"><span class="built_in">ln</span> -s /usr/share/fonts/windows/simsun.ttc simsun.ttc</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash"><span class="built_in">ln</span> -s /usr/share/fonts/windows/simsun.ttc simfang.ttc</span></span><br></pre></td></tr></table></figure></li><li>修改<code>~/.wine/system.reg</code></li></ol><ul><li>查找<code>LogPixels</code>,找到的行内容应该是:<code>[System\\CurrentControlSet\\Hardware Profiles\\Current\\Software\\Fonts]</code><br> 将其中的<code>"LogPixels"=dword:00000060</code>改为:<code>"LogPixels"=dword:00000070</code></li><li>查找<code>FontSubstitutes</code>,找到的行应该是:<code>[Software\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes]</code><br> 将其中的:<code>"MS Shell Dlg"="Tahoma" "MS Shell Dlg 2″="Tahoma"</code>改为:<code>"MS Shell Dlg"="SimSun" "MS Shell Dlg 2″="SimSun"</code></li></ul><ol start="5"><li>修改<code>~/.wine/drive_c/windows/win.ini</code><br> 在末尾添加如下内容: <figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">[Desktop]</span><br><span class="line">menufontsize=13</span><br><span class="line">messagefontsize=13</span><br><span class="line">statusfontsize=13</span><br><span class="line">IconTitleSize=13</span><br></pre></td></tr></table></figure></li><li>把以下代码保存为<code>zh.reg</code>,然后执行<code>regedit zh.reg</code> <figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">REGEDIT4</span><br><span class="line">[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\FontSubstitutes]</span><br><span class="line">"Arial"="simsun"</span><br><span class="line">"Arial CE,238"="simsun"</span><br><span class="line">"Arial CYR,204"="simsun"</span><br><span class="line">"Arial Greek,161"="simsun"</span><br><span class="line">"Arial TUR,162"="simsun"</span><br><span class="line">"Courier New"="simsun"</span><br><span class="line">"Courier New CE,238"="simsun"</span><br><span class="line">"Courier New CYR,204"="simsun"</span><br><span class="line">"Courier New Greek,161"="simsun"</span><br><span class="line">"Courier New TUR,162"="simsun"</span><br><span class="line">"FixedSys"="simsun"</span><br><span class="line">"Helv"="simsun"</span><br><span class="line">"Helvetica"="simsun"</span><br><span class="line">"MS Sans Serif"="simsun"</span><br><span class="line">"MS Shell Dlg"="simsun"</span><br><span class="line">"MS Shell Dlg 2"="simsun"</span><br><span class="line">"System"="simsun"</span><br><span class="line">"Tahoma"="simsun"</span><br><span class="line">"Times"="simsun"</span><br><span class="line">"Times New Roman CE,238"="simsun"</span><br><span class="line">"Times New Roman CYR,204"="simsun"</span><br><span class="line">"Times New Roman Greek,161"="simsun"</span><br><span class="line">"Times New Roman TUR,162"="simsun"</span><br><span class="line">"Tms Rmn"="simsun"</span><br></pre></td></tr></table></figure></li></ol><hr><h2 id="4-安装QQ"><a href="#4-安装QQ" class="headerlink" title="4. 安装QQ"></a>4. 安装QQ</h2><ol><li>官网下载最新版QQ</li><li>使用wine进行安装: <figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">wine QQ8.9.3.exe</span></span><br></pre></td></tr></table></figure></li><li>运行QQ <figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">wine <span class="variable">$HOME</span>/.wine/drive_c/Program\ Files\ \(x86\)/Tencent/QQ/Bin/QQ.exe</span></span><br></pre></td></tr></table></figure> 注意上面的<code>$HOME</code>为自己home目录。</li></ol><hr><h2 id="5-创建桌面图标"><a href="#5-创建桌面图标" class="headerlink" title="5. 创建桌面图标"></a>5. 创建桌面图标</h2><p>创建以下内容的desktop文件:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">[Desktop Entry]</span><br><span class="line">Version=1.0</span><br><span class="line">Type=Application</span><br><span class="line">Name=Tencent QQ</span><br><span class="line">Icon=$HOME/Pictures/qq.png</span><br><span class="line">Exec=wine $HOME/.wine/drive_c/Program\ Files\ \(x86\)/Tencent/QQ/Bin/QQ.exe</span><br><span class="line">Comment=QQ</span><br><span class="line">Categories=Network;InstantMessaging;</span><br><span class="line">Terminal=false</span><br></pre></td></tr></table></figure><p>注意:上面的<code>$HOME</code>改为自己的home目录路径,<code>Icon</code>的图标需要自己下载并放到本地。</p><p>将上面的文件名保存为<code>QQ.desktop</code>(文件后缀为desktop),修改权限为664,然后<strong>放到:<code>$HOME/.local/share/applications/</code>目录下</strong>,也可以直接将该文件拖到启动栏。</p><hr><h2 id="6-存在的问题"><a href="#6-存在的问题" class="headerlink" title="6. 存在的问题"></a>6. 存在的问题</h2><ol><li>无法保存密码;</li><li>页面部分字体会乱码(变成方框);</li><li>无法输入中文(fcitx输入法,包括搜狗):<strong>这一点很蛋疼</strong>,但有的人不会出现。可能解决方案:</li></ol><ul><li>卸载ibus,但亲测卸载ibus会把unity也一同卸载,所以不可行;</li><li>把要输入的文字在其他软件中(如gedit)编写,然后粘贴到聊天框;</li></ul><hr><h2 id="7-参考"><a href="#7-参考" class="headerlink" title="7. 参考"></a>7. 参考</h2><p><span class="exturl" data-url="aHR0cHM6Ly93d3cudWJ1bnR1a3lsaW4uY29tL3VreWxpbi9mb3J1bS5waHA/bW9kPXZpZXd0aHJlYWQmdGlkPTMwNTEx">https://www.ubuntukylin.com/ukylin/forum.php?mod=viewthread&tid=30511<i class="fa fa-external-link-alt"></i></span></p>]]></content>
<summary type="html"><p><strong>注意:无需继续使用该方法在 Linux 上安装 QQ 了,官方已经正式支持 LinuxQQ:<span class="exturl" data-url="aHR0cHM6Ly9pbS5xcS5jb20vbGludXhxcS9pbmRleC5zaHRtbA==">QQ Linux版下载<i class="fa fa-external-link-alt"></i></span></strong></p></summary>
<category term="Ubuntu" scheme="https://yaodev.site/categories/Ubuntu/"/>
<category term="Ubuntu" scheme="https://yaodev.site/tags/Ubuntu/"/>
<category term="wine" scheme="https://yaodev.site/tags/wine/"/>
<category term="QQ" scheme="https://yaodev.site/tags/QQ/"/>
</entry>
</feed>