GVKun编程网logo

Tagxp_电脑维修视频教程12(电脑维修视频教程20讲)

16

如果您想了解电脑入门学习-学习汉字输入法1的相关知识,那么本文是一篇不可错过的文章,我们将对电脑入门学打字教学全集视频进行全面详尽的解释,并且为您提供关于CentOS安装中文汉字输入法ibus、Dem

如果您想了解电脑入门学习-学习汉字输入法1的相关知识,那么本文是一篇不可错过的文章,我们将对电脑入门学打字教学全集视频进行全面详尽的解释,并且为您提供关于CentOS安装中文汉字输入法ibus、Demo中学习React-入门学习、django 入门学习(外加 MTV 模式 学习)、Elasticsearch 简单学习 4: 入门学习 - 1的有价值的信息。

本文目录一览:

电脑入门学习-学习汉字输入法1(电脑入门学打字教学全集视频)

电脑入门学习-学习汉字输入法1(电脑入门学打字教学全集视频)

电脑技术网教你学电脑入门学习系列视频教程适合刚学电脑的朋友,讲的很简单易懂。对刚学电脑的朋友是比较有帮助的,能快速引导你学习电脑入门知识。看完这一系列教程,基本上对电脑操作知识有了大概的了解,让你知道可以从哪里入手操作电脑。已经有一定电脑知识的朋友可以跳过此教程。

CentOS安装中文汉字输入法ibus

CentOS安装中文汉字输入法ibus

新安装的CentOS没有默认没有装语言支持(Language Support),因此很不方面。

终于发现了有效的方法:

su root

yum install "@Chinese Support"

exit

然后设置Input Methord即可。

最后一步:logout,注意是注销,然后再次登录此用户。

引用:http://www.cyberciti.biz/faq/linux-install-language-support/

LinuxFAQ / Howtos
Install Language support in CentOS 5 or Red Hat Enterprise Linux
by Vivek Gite on June 15,2007 · 8 comments

Q. How do I install Languages in Linux after installation? I don’t have any language specific support installed but need to install the same. I’m using both RHEL 5 and CentOS 5.

A. Yellow dog Updater,Modified,a package manager for RPM-compatible Linux systems such as CentoS 5/Fedora 7 and RHEL 5. Yum's repository system is quickly becoming the standard for RPM-based repositories.

If the languages were not installed during the installation,the same can be installed by YUM command. Use following command to install hindi and Chinese support.

# yum groupinstall {LANGUAGE-support}

# yum install "@hindi Support"
# yum install "@Chinese Support"

Use yum grouplist list available groups and languages.

[Jeffery@CentOS ~]$ su root
密码:
[root@CentOS Jeffery]# yum install "@Chinese Support"
Loaded plugins: fastestmirror,refresh-packagekit,security
Repository base is listed more than once in the configuration
Repository updates is listed more than once in the configuration
Repository extras is listed more than once in the configuration
Repository centosplus is listed more than once in the configuration
Repository contrib is listed more than once in the configuration
Loading mirror speeds from cached hostfile
base| 3.7 kB00:00
extras| 3.5 kB00:00
google-chrome|951 B00:00
updates| 3.4 kB00:00
updates/primary_db| 4.0 MB00:02
Setting up Install Process
Loading mirror speeds from cached hostfile
Package cjkuni-uming-fonts-0.2.20080216.1-35.el6.noarch already installed and latest version
Package wqy-zenhei-fonts-0.9.45-3.el6.noarch already installed and latest version
Resolving Dependencies
--> Running transaction check
---> Package cjkuni-ukai-fonts.noarch 0:0.2.20080216.1-35.el6 will be installed
---> Package ibus-chewing.i686 0:1.3.5.20100714-4.el6 will be installed
--> Processing Dependency: libchewing >= 0.3.2-16 for package: ibus-chewing-1.3.5.20100714-4.el6.i686
--> Processing Dependency: ibus >= 1.1 for package: ibus-chewing-1.3.5.20100714-4.el6.i686
--> Processing Dependency: libibus.so.2 for package: ibus-chewing-1.3.5.20100714-4.el6.i686
--> Processing Dependency: libchewing.so.3 for package: ibus-chewing-1.3.5.20100714-4.el6.i686
---> Package ibus-pinyin.i686 0:1.3.8-1.el6 will be installed
---> Package ibus-table-cangjie.noarch 0:1.2.0.20100210-1.el6 will be installed
--> Processing Dependency: ibus-table >= 1.2.0.20100111-2 for package: ibus-table-cangjie-1.2.0.20100210-1.el6.noarch
--> Processing Dependency: ibus-table >= 1.2.0.20100111-2 for package: ibus-table-cangjie-1.2.0.20100210-1.el6.noarch
---> Package ibus-table-erbi.noarch 0:1.2.0.20090901-8.el6 will be installed
---> Package ibus-table-wubi.noarch 0:1.2.0.20090715-8.el6 will be installed
--> Running transaction check
---> Package ibus.i686 0:1.3.4-6.el6 will be installed
--> Processing Dependency: ibus-gtk = 1.3.4-6.el6 for package: ibus-1.3.4-6.el6.i686
--> Processing Dependency: im-chooser >= 1.2.5 for package: ibus-1.3.4-6.el6.i686
--> Processing Dependency: pyxdg for package: ibus-1.3.4-6.el6.i686
--> Processing Dependency: notify-python for package: ibus-1.3.4-6.el6.i686
---> Package ibus-libs.i686 0:1.3.4-6.el6 will be installed
---> Package ibus-table.noarch 0:1.2.0.20100111-4.el6 will be installed
---> Package libchewing.i686 0:0.3.2-27.el6 will be installed
--> Running transaction check
---> Package ibus-gtk.i686 0:1.3.4-6.el6 will be installed
---> Package im-chooser.i686 0:1.3.1-3.el6 will be installed
--> Processing Dependency: imsettings >= 0.106.0 for package: im-chooser-1.3.1-3.el6.i686
--> Processing Dependency: libimsettings.so.4 for package: im-chooser-1.3.1-3.el6.i686
---> Package notify-python.i686 0:0.1.1-10.el6 will be installed
---> Package pyxdg.noarch 0:0.18-1.el6 will be installed
--> Running transaction check
---> Package imsettings.i686 0:0.108.0-3.6.el6 will be installed
--> Processing Dependency: libgxim.so.2 for package: imsettings-0.108.0-3.6.el6.i686
---> Package imsettings-libs.i686 0:0.108.0-3.6.el6 will be installed
--> Running transaction check
---> Package libgxim.i686 0:0.3.3-3.1.el6 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

================================================================================
PackageArchVersionRepository
Size
================================================================================
Installing:
cjkuni-ukai-fontsnoarch0.2.20080216.1-35.el6base9.4 M
ibus-chewingi6861.3.5.20100714-4.el6base61 k
ibus-pinyini6861.3.8-1.el6base1.1 M
ibus-table-cangjienoarch1.2.0.20100210-1.el6base4.9 M
ibus-table-erbinoarch1.2.0.20090901-8.el6base2.0 M
ibus-table-wubinoarch1.2.0.20090715-8.el6base2.0 M
Installing for dependencies:
ibusi6861.3.4-6.el6base334 k
ibus-gtki6861.3.4-6.el6base25 k
ibus-libsi6861.3.4-6.el6base96 k
ibus-tablenoarch1.2.0.20100111-4.el6base243 k
im-chooseri6861.3.1-3.el6base144 k
imsettingsi6860.108.0-3.6.el6base189 k
imsettings-libsi6860.108.0-3.6.el6base101 k
libchewingi6860.3.2-27.el6base1.5 M
libgximi6860.3.3-3.1.el6base122 k
notify-pythoni6860.1.1-10.el6base25 k
pyxdgnoarch0.18-1.el6base79 k

Transaction Summary
================================================================================
Install17 Package(s)

Total download size: 22 M
Installed size: 63 M
Is this ok [y/N]: y
Downloading Packages:
(1/17): cjkuni-ukai-fonts-0.2.20080216.1-35.el6.noarch.r | 9.4 MB00:04
(2/17): ibus-1.3.4-6.el6.i686.rpm| 334 kB00:00
(3/17): ibus-chewing-1.3.5.20100714-4.el6.i686.rpm|61 kB00:00
(4/17): ibus-gtk-1.3.4-6.el6.i686.rpm|25 kB00:00
(5/17): ibus-libs-1.3.4-6.el6.i686.rpm|96 kB00:00
(6/17): ibus-pinyin-1.3.8-1.el6.i686.rpm| 1.1 MB00:00
(7/17): ibus-table-1.2.0.20100111-4.el6.noarch.rpm| 243 kB00:00
(8/17): ibus-table-cangjie-1.2.0.20100210-1.el6.noarch.r | 4.9 MB00:01
(9/17): ibus-table-erbi-1.2.0.20090901-8.el6.noarch.rpm| 2.0 MB00:01
(10/17): ibus-table-wubi-1.2.0.20090715-8.el6.noarch.rpm | 2.0 MB00:02
(11/17): im-chooser-1.3.1-3.el6.i686.rpm| 144 kB00:00
(12/17): imsettings-0.108.0-3.6.el6.i686.rpm| 189 kB00:00
(13/17): imsettings-libs-0.108.0-3.6.el6.i686.rpm| 101 kB00:00
(14/17): libchewing-0.3.2-27.el6.i686.rpm| 1.5 MB00:02
(15/17): libgxim-0.3.3-3.1.el6.i686.rpm| 122 kB00:00
(16/17): notify-python-0.1.1-10.el6.i686.rpm|25 kB00:00
(17/17): pyxdg-0.18-1.el6.noarch.rpm|79 kB00:00
--------------------------------------------------------------------------------
Total1.2 MB/s |22 MB00:19
Running rpm_check_debug
Running Transaction Test
Transaction Test Succeeded
Running Transaction
Installing : ibus-libs-1.3.4-6.el6.i6861/17
Installing : libgxim-0.3.3-3.1.el6.i6862/17
Installing : pyxdg-0.18-1.el6.noarch3/17
Installing : imsettings-libs-0.108.0-3.6.el6.i6864/17
Installing : imsettings-0.108.0-3.6.el6.i6865/17
Installing : im-chooser-1.3.1-3.el6.i6866/17
Installing : notify-python-0.1.1-10.el6.i6867/17
Installing : ibus-gtk-1.3.4-6.el6.i6868/17
Installing : ibus-1.3.4-6.el6.i6869/17
Installing : ibus-table-1.2.0.20100111-4.el6.noarch10/17
Installing : libchewing-0.3.2-27.el6.i68611/17
Installing : ibus-table-wubi-1.2.0.20090715-8.el6.noarch12/17
Installing : ibus-table-cangjie-1.2.0.20100210-1.el6.noarch13/17
Installing : ibus-table-erbi-1.2.0.20090901-8.el6.noarch14/17
Installing : cjkuni-ukai-fonts-0.2.20080216.1-35.el6.noarch15/17
Installing : ibus-chewing-1.3.5.20100714-4.el6.i68616/17
Installing : ibus-pinyin-1.3.8-1.el6.i68617/17
Verifying: libgxim-0.3.3-3.1.el6.i6861/17
Verifying: libchewing-0.3.2-27.el6.i6862/17
Verifying: ibus-gtk-1.3.4-6.el6.i6863/17
Verifying: ibus-pinyin-1.3.8-1.el6.i6864/17
Verifying: ibus-table-1.2.0.20100111-4.el6.noarch5/17
Verifying: notify-python-0.1.1-10.el6.i6866/17
Verifying: im-chooser-1.3.1-3.el6.i6867/17
Verifying: ibus-table-wubi-1.2.0.20090715-8.el6.noarch8/17
Verifying: imsettings-libs-0.108.0-3.6.el6.i6869/17
Verifying: ibus-table-cangjie-1.2.0.20100210-1.el6.noarch10/17
Verifying: ibus-libs-1.3.4-6.el6.i68611/17
Verifying: pyxdg-0.18-1.el6.noarch12/17
Verifying: ibus-table-erbi-1.2.0.20090901-8.el6.noarch13/17
Verifying: ibus-1.3.4-6.el6.i68614/17
Verifying: cjkuni-ukai-fonts-0.2.20080216.1-35.el6.noarch15/17
Verifying: ibus-chewing-1.3.5.20100714-4.el6.i68616/17
Verifying: imsettings-0.108.0-3.6.el6.i68617/17

Installed:
cjkuni-ukai-fonts.noarch 0:0.2.20080216.1-35.el6
ibus-chewing.i686 0:1.3.5.20100714-4.el6
ibus-pinyin.i686 0:1.3.8-1.el6
ibus-table-cangjie.noarch 0:1.2.0.20100210-1.el6
ibus-table-erbi.noarch 0:1.2.0.20090901-8.el6
ibus-table-wubi.noarch 0:1.2.0.20090715-8.el6

Dependency Installed:
ibus.i686 0:1.3.4-6.el6
ibus-gtk.i686 0:1.3.4-6.el6
ibus-libs.i686 0:1.3.4-6.el6
ibus-table.noarch 0:1.2.0.20100111-4.el6
im-chooser.i686 0:1.3.1-3.el6
imsettings.i686 0:0.108.0-3.6.el6
imsettings-libs.i686 0:0.108.0-3.6.el6
libchewing.i686 0:0.3.2-27.el6
libgxim.i686 0:0.3.3-3.1.el6
notify-python.i686 0:0.1.1-10.el6
pyxdg.noarch 0:0.18-1.el6

Complete!
[root@CentOS Jeffery]#

Demo中学习React-入门学习

Demo中学习React-入门学习

在搭建的环境基础上进行Demo实现。其中App.jsx用来定义组件,注意一个文件导出一个组件;main.js用来进行组件的渲染。最后利用webpack将源代码构建为index.js并引入index.html页面。


Demo1:界面上显示秒表效果,实时更新

定义组件部分:

import React from 'react';
//定义组件
class Demo1 extends React.Component{
render(){
var elapsed = Math.round(this.props.elapsed  / 100);//获取组件属性值this.props.elapsed
    var seconds = elapsed / 10 + (elapsed % 10 ? '' : '.0' );//计算seconds
    //使用seconds加入组件的message内容
    var message ='React has been successfully running for ' + seconds + ' seconds.';
//返回组件
return(
<p>{message}</p>   //大括号引入js变量
);
}
}
//导出Demo1组件
export default Demo1;

渲染组件部分:

import React from 'react';
import ReactDOM from 'react-dom';
import Demo1 from './App.jsx';
//获取当前时间
var start = new Date().getTime();
setInterval(function() {
ReactDOM.render(
//使用组件,并定义了elapsed属性
  <Demo1 elapsed={new Date().getTime() - start} />,document.getElementById('app')
);
},50);

总结:

1.使用class … extends React.Component的方法进行组件的定义。

2.通过this.props.attr获取定义的组件标签中的属性值

3.在定义组件时,使用{}调用javascript变量

4.ReactDom.render()方法渲染组件,这里使用setInterval每隔50ms就进行一次组件渲染

5.该例中,每次渲染都会更新elapsed值,组件获取新的elapsed值并进行处理,最后作为内容构建组件


Demo2:点击组件,会刷新已点击次数

定义组件部分:

var Demo2 = React.createClass({
  getinitialState: function () {
    return { clickCount: 0 };
  },handleClick: function () {
    this.setState(function(state) {
      return {clickCount: state.clickCount + 1};
    });
  },render: function () {
    return (<h2 onClick={this.handleClick}>点我!点击次数为: {this.state.clickCount}</h2>);
  }
});
export default Demo2;

渲染组件部分:

import Demo2 from './App.jsx';
ReactDOM.render(
  <Demo2 />,document.getElementById('app')
);

总结:

1.getinitialState方法用来初始化state的内容,返回的是一个对象,比如这里初始化了clickCount变量为0,就可以通过this.state.clickCount获取

2.setState方法用来改变state对象的值,比如例子中就修改了this.state.clickCount值将其加1

3.handleClick方法定义了一个点击事件,在下面的组件中通过onClick属性进行调用,这样每次点击都会触发handleClick中的方法


Demo3:实现类似AngularJS中双向数据绑定的功能

定义组件部分

var Content = React.createClass({
render: function(){
return  <div>
            <input type="text" value={this.props.myDataProp} onChange={this.props.updateStateProp} /> 
            <h4>{this.props.myDataProp}</h4>
            </div>;
}
});
var HelloMessage = React.createClass({
  getinitialState: function() {
    return {value: 'Hello Martin’};
  },handleChange: function(event) {
    this.setState({value: event.target.value});
  },render: function() {
    var value = this.state.value;
    return <div>
            <Content myDataProp = {value} 
              updateStateProp = {this.handleChange}></Content>
           </div>;
  }
});
export default Demo3;

渲染组件部分:

import Demo3 from './App.jsx';
ReactDOM.render(
  <Demo3 />,document.getElementById('app')
);

总结:

1.这里使用父组件和子组件。其中HelloMessage是父组件,Content是子组件,HelloMessage组件可以直接使用之前已经定义好的Content子组件

2.为子组件的input标签onChange事件绑定handleChange方法,这样每次input发生变化时都会通过setState修改value的值,然后自动重新渲染组件

django 入门学习(外加 MTV 模式 学习)

django 入门学习(外加 MTV 模式 学习)

项目:Web 应用小程序(以 wblog 为例)

目录:

一、Django 入门

二、用户账户

三、设置应用程序的样式并对其进行部署

一、Django

利用 django 创建工程

新建项目:django-admin  startproject  wblog(mysite 相当于 wblog)

 

修改项目:

根据需要,可自行创建开发小程序。小程序就相当于一个应用 app,就像老师所说的工程里面有应用,好比大学里有各级学院,还有一些教务处,行政处等设置,这里工程有类似功能的 setting.py。

这里利用 MTV 模式开发小程序(MTV)

Model,对数据的存储及组织的模式;

Template,模板,返回 Web 页面的样式;

View,与相关路由对应,返回指定的函数。

 

 

下面是数据模板文件 models.py

 

 

里面的 topic 和 entry 都定义了数据的存储和一些组织形式,具体详情可以查看一下相关 django 库的运用。

 

下面是 Web 页面模板 templates

 

 

这些都是根据需要编写的文件,有兴趣的可以自己编写,还可以设置一些好看的模板来装饰自己的页面,例如 django-bootstrap3。

 

下面是视图函数 views.py

 

 

里面就是定义各种函数。其中的 render 函数的作用是渲染,把数据和模板内容结合渲染成 HTML 字符串。

 

查看全局路由文件 urls.py

 

 

其中,urlpatterns 是 django 指定的变量,不可更改。

url (‘左边’,‘右边’),左边是用户访问的 URL 路径,右边是相对应返回的函数,这两个变量被路由相关联。

Include 函数的作用是添加其他路由(即小程序路由)的 url。

 

下面是相关配置文件 setting.py

 

 

这里设置了一些模板路径。

 

下面是本地路由文件 urls.py

 

 

这个和全局路由是一样的。

 

运行项目:python  manage.py  runserver (可自行选取参数,例如 8001,8002——) 默认 8000 接口

 至此,一个小项目就可以在本地上运行啦!

这是自己琢磨写的,要是哪位大神有觉得不对的,恳请指出!

Elasticsearch 简单学习 4: 入门学习 - 1

Elasticsearch 简单学习 4: 入门学习 - 1

一、基本概念

1. 文档

《1.》Elasticsearch 是面向文档的,文档是所有可搜索数据的最小单位。

       eg: ① 日志文件中的日志项

             ② 一部电影的具体信息 | 一张唱片的详细信息

             ③ MP3 播放器里的一首歌 | 一篇 PDF 文档中的具体内容

《2.》文档会被序列化成 JSON 格式,保存在 Elasticsearch 中

          ① JSON 对象由字段组成

          ② 每个字段都有对应的字段类型 (字符串 | 数值 | 布尔 | 日期 | 二进制 | 范围类型)

《3.》每个文档都有一个 Uinque ID

         ① 你可以自己指定 ID

         ② 或者通过 Elasticsearch 自动生成

2.JSON 文档

《1.》一篇文档包含了一系列的字段。类似数据库表中一条记录

《2.》JSON 文档,格式灵活,不需要预先定义格式

         ① 字段的类型可以指定或者通过 Elasticsearch 自动推算

         ② 支持数组 | 支持嵌套

3. 文档的元数据

4. 索引

5. 索引的不同语意

6. 抽象与类比

为什么不再支持单个 Index 下,多个 Types:

https://www.elastic.co/cn/blog/moving-from-types-to-typeless-apis-in-elasticsearch-7-0

 

7.REST API 

很容易被各种语言调用

8. 一些基本的 API

之前装 Kibana 时,我们导入的有一些测试数据,电子商务订单、监控航线的示例数据、监控 Web 日志的示例数据,

以及装入 Logstash 时,导入的 movie 的测试数据,我们可以通过 kibana 的索引管理看到。

//查看“电子商务订单”索引相关信息
GET kibana_sample_data_ecommerce

//查看“电子商务订单”的文档总数
GET kibana_sample_data_ecommerce/_count

//查看“电子商务订单”前10条文档,了解文档格式
POST kibana_sample_data_ecommerce/_search

//查以kibana开头的索引(通配符查询)
GET /_cat/indices/kibana*?v&s=index

//查看状态为绿的索引
GET /_cat/indices?v&health=green

//按照文档的个数排序
GET /_cat/indices?v&s=docs.count:desc

//查看每个索引占用的内存
GET /_cat/indices?v&h=i,tm&s=tm:desc

CAT Indices:

https://www.elastic.co/guide/en/elasticsearch/reference/7.1/cat-indices.html

二、集群 | 节点 | 分片 | 副本

 

1. 分布式系统的可用性与扩展性

《1.》高可用

        服务可用性:允许有节点停止服务

        数据可用性:部分节点丢失,不会丢失数据

《2.》可扩展性

        请求量提升 | 数据的不断增长(将数据分布到所有节点上)

 

2. 分布式特性

《1.》Elasticsearch 分布式架构的好处

         存储的水平扩容

         提高系统的可用性,部分节点停止服务,整个集群的服务不受影响

《2.》Elasticsearch 的分布式架构

         不同的集群通过不同的名字来区分,默认名字 “elasticsearch

         通过配置文件修改,或者在命令行中 -E cluster.name=beehive 进行设定

        一个集群可以有一个或者多个节点

 

3. 节点

《1.》节点是一个 Elasticsearch 的实例

         本质上就是一个 JAVA 进程

          一台机器上可以运行多个 Elasticsearch 进程,但是,生产环境一般建议一台机器上只运行一个 Elasticsearch 实例

《2.》每一个节点都有名字,通过配置文件配置,或者启动时候 -E node.name=node1 指定

《3.》每一个节点在启动之后,会分配一个 UID,保存在 data 目录下

 

4.Master-eligible nodes 和 Master Node

《1.》每个节点启动后,默认就是一个 Master eligible 节点 

         可以设置 node.master:false 禁止

《2.》Master-eligible 节点可以参加选主流程,成为 Master 节点

《3.》当第一个节点启动时候,它会将自己选举成 Master 节点。

《4.》每个节点上都保存了集群的状态,只有 Master 节点才能修改集群的状态信息

《5.》集群状态(Cluster State) , 维护了一个集群中,必要的信息

          ① 所有的节点信息

          ② 所有的索引和其相关的 Mapping 与 Setting 信息

          ③ 分片的路由信息

          注意事项:只有 Master 节点才能修改集群的状态信息,如果任意节点都能修改信息会导致数据的不一致性

 

 5.Data Node & Coordinating Node

 《1.》Data Node

          可以保存数据的节点,叫做 Data Node 。负责保存分片数据。在数据扩展上起到了至关重要的作用

《2.》Coordinating Node

          ① 负责接受 Client 的请求,将请求分发到合适的节点,最终把结果汇集到一起

          ② 每个节点默认都起到了 Coordinating Node 的职责

6. 其他的节点类型

《1.》Hot & Warm Node

        不同硬件配置的 Data Node , 用来实现 Hot & Warm 架构 ,降低集群部署的成本。

        比如:日志处理时,会设置冷热节点,热节点会有更好的磁盘以及吞吐量。 

《2.》Machine Learning Node

         负责跑机器学习的 Job , 用来做异常检测

《3.》Tribe Node (未来可能会被淘汰)

         【5.3 开始使用 Cross Cluster Search 】,Tribe Node  连接到不同的 Elasticsearch 集群,

          并且支持将这些集群当成一个单独的集群处理。

7. 配置节点类型

《1.》开发环境中一个节点可以承担多种角色

《2.》生产环境中,可以设置单一的角色的节点(dedicated node)

         性能更好,职责明确,不同的节点可以配置不同的机器!

8. 分片 (Primary Shard & Replica Shard)

《1.》主分片 ,用以解决数据水平扩展的问题。通过主分片,可以将数据分布到集群内的所有节点之上。

        ① 一个分片是一个运行的 Lucene 的实例

        ② 主分片数量在索引创建时指定 ,后续不允许修改,除非 Reindex

《2.》副本分片,用以解决数据高可用的问题。分片是主分片的拷贝

        ① 副本分片数目,可以动态的调整

        ② 增加副本数,还可以在一定程度上提高服务的可用性(读取的吞吐量)

《3.》一个三节点的集群中,blogs 索引的分片分布情况

9. 分片的设定

         对于生产环境中分片的设定,需要提前做好容量规划

         ① 分片数目设置过小

              * 导致后续无法增加节点实现水平扩展

              * 单个分片的数据量太大, 导致数据重新分配耗时

        ② 分片数目设置过大

              * 7.0 开始,默认主分片设置成 1 ,解决了 over-sharding 的问题

              * 影响搜索结果的相关性打分,影响统计结果的准确性

              * 单个节点上过多的分片,会导致资源浪费,同时也会影响性能

10. 查看集群的健康状况

http://localhost:9200/_cluster/health

《1.》Green - 主分片与副本都正常分配

《2.》Yellow - 主分片全部正常分配,有副本分片未能正常分配

《3.》Red - 有主分片未能分配

         eg. 当服务器的磁盘容量超过 85% 时,去创建了一个新的索引。

《4.》

//查看集群的健康状况
GET _cluster/health

//查看node的信息
GET _cat/nodes

//查看shards信息
GET _cat/shards

CAT Nodes API : https://www.elastic.co/guide/en/elasticsearch/reference/7.1/cat-nodes.html

Cluster APIS : https://www.elastic.co/guide/en/elasticsearch/reference/7.1/cluster.html

CAT Shards API : https://www.elastic.co/guide/en/elasticsearch/reference/7.1/cat-shards.html

三、文档的基本操作

1.CRUD

2.Create 一个文档

《1.》支持自动生成文档 Id 和指定文档 Id 两种方式

《2.》通过调用 “POST  users/_doc” , 系统会自动生成 document Id

《3.》使用 HTTP PUT  users/_doc/1 创建时,URI 中显示指定_doc, 此时如果该 Id 的文档已经存在,操作失败

《4.》举例:

 

3.GET 一个文档

《1.》找到文档,返回 HTTP 200

          文档元信息:

          ① _index/_type/

          ② 版本信息,同一个 Id 的文档,即使被删除,Version 号也不会不断增加

          ③ _source 中默认包含了文档的所有原始信息

《2.》找不到文档,返回 HTTP 404

 

4.Index 文档

《1.》Index 和 Create 不一样的地方:如果文档不存在,就索引新的文档。

         否则现有的文档会被删除,新的文档被索引。版本信息 +1

 

5.Update 文档

《1.》Update 方法不会删除原来的文档,而是实现真正的数据更新

《2.》注意使用的是 POST 方法,要更新的内容是放在 doc 中。

6.Bulk API

《1.》支持在一次 API 调用中,对不同的索引进行操作

《2.》支持四种类型的操作

          Index Create Update Delete

《3.》操作中单条操作失败,并不会影响其他的操作

《4.》返回结果包含了每一条操作执行的结果

eg.:https://www.elastic.co/guide/en/elasticsearch/reference/7.1/docs-bulk.html

 

《5.》批量读取 - mget

批量读取,可以减少网络连接所产生的开销,提高性能。

《6.》批量查询 - msearch

//msearch 操作
POST kibana_sample_data_ecommerce/_msearch
{}
{"query" : {"match_all" : {}},"size" : 1}
{"index" : "kibana_sample_data_flights"}
{"query" : {"match_all" : {}},"size" : 2}

7. 常见错误返回

Document API : https://www.elastic.co/guide/en/elasticsearch/reference/7.1/docs.html

四、倒排索引介绍

倒排索引理解:

https://my.oschina.net/hanchao/blog/3053367

https://zh.wikipedia.org/wiki/%E5%80%92%E6%8E%92%E7%B4%A2%E5%BC%95

https://www.elastic.co/guide/cn/elasticsearch/guide/current/inverted-index.html

1. 正排索引和倒排索引

2. 倒排索引的核心组成

《1.》单词词典 (Term Dictionary)

          记录所有文档的单词,记录单词到倒排列表的关联关系。

          单词词典一般比较大,可以通过 B + 树或哈希拉链法实现,以满足高性能的插入与查询。

《2.》倒排列表(Posting List)

          - 记录了单词对应的文档结合,由倒排索引项组成

         倒排索引项(Posting)

         ① 文档 Id

         ② 词频 TF - 该单词在文档中出现的次数,用于相关性评分

         ③ 位置(Position) - 单词在文档中分词的位置。用于语句搜索(phrase query)

         ④ 偏移(Offset) - 记录单词的开始结束位置,实现高亮显示

《3.》例子 - Elasticsearch

3. 倒排索引说明

 

 

五、通过 Analyzer 进行分词

1.Analysis 与 Analyzer

《1.》Analysis - 文本分析是把全文本转换成一系列单词(term | token)的过程,也叫分词

《2.》Analysis 是通过 Analyzer 来实现的

         可使用 Elasticsearch 内置的分析器 | 或者按需定制化分析器

《3.》除了在数据写入时转换词条,匹配 Query 语句时候也需要用相同的分析器对查询语句进行分析

eg:

2.Analyzer 的组成

3.Elasticsearch 的内置分词器

4. 使用_analyzer API

《1.》直接指定 Analyzer 进行测试

//直接使用指定的Analyzer进行测试
GET /_analyze
{
  "analyzer": "standard",
  "text" : "Masterting Elasticsearch, elasticsearch in Action"
}

结果:

{
  "tokens" : [
    {
      "token" : "masterting",
      "start_offset" : 0,
      "end_offset" : 10,
      "type" : "<ALPHANUM>",
      "position" : 0
    },
    {
      "token" : "elasticsearch",
      "start_offset" : 11,
      "end_offset" : 24,
      "type" : "<ALPHANUM>",
      "position" : 1
    },
    {
      "token" : "elasticsearch",
      "start_offset" : 26,
      "end_offset" : 39,
      "type" : "<ALPHANUM>",
      "position" : 2
    },
    {
      "token" : "in",
      "start_offset" : 40,
      "end_offset" : 42,
      "type" : "<ALPHANUM>",
      "position" : 3
    },
    {
      "token" : "action",
      "start_offset" : 43,
      "end_offset" : 49,
      "type" : "<ALPHANUM>",
      "position" : 4
    }
  ]
}

《2.》指定索引的字段进行测试

//指定索引的字段进行测试
POST users/_analyze
{
  "field": "message",
  "text" : "Mastering Elasticsearch"
}

结果:

{
  "tokens" : [
    {
      "token" : "mastering",
      "start_offset" : 0,
      "end_offset" : 9,
      "type" : "<ALPHANUM>",
      "position" : 0
    },
    {
      "token" : "elasticsearch",
      "start_offset" : 10,
      "end_offset" : 23,
      "type" : "<ALPHANUM>",
      "position" : 1
    }
  ]
}

《3.》自定义分词器进行测试

//使用自定义分词器进行测试
POST /_analyze
{
  "tokenizer": "standard",
  "filter": ["lowercase"],
  "text" : "Mastering Elastcisearch HANCHAO"
}

结果:

{
  "tokens" : [
    {
      "token" : "mastering",
      "start_offset" : 0,
      "end_offset" : 9,
      "type" : "<ALPHANUM>",
      "position" : 0
    },
    {
      "token" : "elastcisearch",
      "start_offset" : 10,
      "end_offset" : 23,
      "type" : "<ALPHANUM>",
      "position" : 1
    },
    {
      "token" : "hanchao",
      "start_offset" : 24,
      "end_offset" : 31,
      "type" : "<ALPHANUM>",
      "position" : 2
    }
  ]
}

5.Standard Analyzer

举例:

#standard
GET _analyze
{
  "analyzer": "standard",
  "text": "2 running Quick brown-foxes leap over lazy dogs in the summer evening."
}

结果:

{
  "tokens" : [
    {
      "token" : "2",
      "start_offset" : 0,
      "end_offset" : 1,
      "type" : "<NUM>",
      "position" : 0
    },
    {
      "token" : "running",
      "start_offset" : 2,
      "end_offset" : 9,
      "type" : "<ALPHANUM>",
      "position" : 1
    },
    {
      "token" : "quick",
      "start_offset" : 10,
      "end_offset" : 15,
      "type" : "<ALPHANUM>",
      "position" : 2
    },
    {
      "token" : "brown",
      "start_offset" : 16,
      "end_offset" : 21,
      "type" : "<ALPHANUM>",
      "position" : 3
    },
    {
      "token" : "foxes",
      "start_offset" : 22,
      "end_offset" : 27,
      "type" : "<ALPHANUM>",
      "position" : 4
    },
    {
      "token" : "leap",
      "start_offset" : 28,
      "end_offset" : 32,
      "type" : "<ALPHANUM>",
      "position" : 5
    },
    {
      "token" : "over",
      "start_offset" : 33,
      "end_offset" : 37,
      "type" : "<ALPHANUM>",
      "position" : 6
    },
    {
      "token" : "lazy",
      "start_offset" : 38,
      "end_offset" : 42,
      "type" : "<ALPHANUM>",
      "position" : 7
    },
    {
      "token" : "dogs",
      "start_offset" : 43,
      "end_offset" : 47,
      "type" : "<ALPHANUM>",
      "position" : 8
    },
    {
      "token" : "in",
      "start_offset" : 48,
      "end_offset" : 50,
      "type" : "<ALPHANUM>",
      "position" : 9
    },
    {
      "token" : "the",
      "start_offset" : 51,
      "end_offset" : 54,
      "type" : "<ALPHANUM>",
      "position" : 10
    },
    {
      "token" : "summer",
      "start_offset" : 55,
      "end_offset" : 61,
      "type" : "<ALPHANUM>",
      "position" : 11
    },
    {
      "token" : "evening",
      "start_offset" : 62,
      "end_offset" : 69,
      "type" : "<ALPHANUM>",
      "position" : 12
    }
  ]
}

6.Simple Analyzer

按照非字母切分(符号被过滤),小写处理。

#simpe analyzer
GET _analyze
{
  "analyzer": "simple",
  "text": "2 running Quick brown-foxes leap over lazy dogs in the summer evening."
}

结果:

{
  "tokens" : [
    {
      "token" : "running",
      "start_offset" : 2,
      "end_offset" : 9,
      "type" : "word",
      "position" : 0
    },
    {
      "token" : "quick",
      "start_offset" : 10,
      "end_offset" : 15,
      "type" : "word",
      "position" : 1
    },
    {
      "token" : "brown",
      "start_offset" : 16,
      "end_offset" : 21,
      "type" : "word",
      "position" : 2
    },
    {
      "token" : "foxes",
      "start_offset" : 22,
      "end_offset" : 27,
      "type" : "word",
      "position" : 3
    },
    {
      "token" : "leap",
      "start_offset" : 28,
      "end_offset" : 32,
      "type" : "word",
      "position" : 4
    },
    {
      "token" : "over",
      "start_offset" : 33,
      "end_offset" : 37,
      "type" : "word",
      "position" : 5
    },
    {
      "token" : "lazy",
      "start_offset" : 38,
      "end_offset" : 42,
      "type" : "word",
      "position" : 6
    },
    {
      "token" : "dogs",
      "start_offset" : 43,
      "end_offset" : 47,
      "type" : "word",
      "position" : 7
    },
    {
      "token" : "in",
      "start_offset" : 48,
      "end_offset" : 50,
      "type" : "word",
      "position" : 8
    },
    {
      "token" : "the",
      "start_offset" : 51,
      "end_offset" : 54,
      "type" : "word",
      "position" : 9
    },
    {
      "token" : "summer",
      "start_offset" : 55,
      "end_offset" : 61,
      "type" : "word",
      "position" : 10
    },
    {
      "token" : "evening",
      "start_offset" : 62,
      "end_offset" : 69,
      "type" : "word",
      "position" : 11
    }
  ]
}

7.Whitespace Analyzer

#whitespace
GET _analyze
{
  "analyzer": "whitespace",
  "text": "2 running Quick brown-foxes leap over lazy dogs in the summer evening."
}

结果:

{
  "tokens" : [
    {
      "token" : "2",
      "start_offset" : 0,
      "end_offset" : 1,
      "type" : "word",
      "position" : 0
    },
    {
      "token" : "running",
      "start_offset" : 2,
      "end_offset" : 9,
      "type" : "word",
      "position" : 1
    },
    {
      "token" : "Quick",
      "start_offset" : 10,
      "end_offset" : 15,
      "type" : "word",
      "position" : 2
    },
    {
      "token" : "brown-foxes",
      "start_offset" : 16,
      "end_offset" : 27,
      "type" : "word",
      "position" : 3
    },
    {
      "token" : "leap",
      "start_offset" : 28,
      "end_offset" : 32,
      "type" : "word",
      "position" : 4
    },
    {
      "token" : "over",
      "start_offset" : 33,
      "end_offset" : 37,
      "type" : "word",
      "position" : 5
    },
    {
      "token" : "lazy",
      "start_offset" : 38,
      "end_offset" : 42,
      "type" : "word",
      "position" : 6
    },
    {
      "token" : "dogs",
      "start_offset" : 43,
      "end_offset" : 47,
      "type" : "word",
      "position" : 7
    },
    {
      "token" : "in",
      "start_offset" : 48,
      "end_offset" : 50,
      "type" : "word",
      "position" : 8
    },
    {
      "token" : "the",
      "start_offset" : 51,
      "end_offset" : 54,
      "type" : "word",
      "position" : 9
    },
    {
      "token" : "summer",
      "start_offset" : 55,
      "end_offset" : 61,
      "type" : "word",
      "position" : 10
    },
    {
      "token" : "evening.",
      "start_offset" : 62,
      "end_offset" : 70,
      "type" : "word",
      "position" : 11
    }
  ]
}

8.Stop Analyzer

小写处理:停用词过滤(the , a  , is)

# stop analyzer
GET _analyze
{
  "analyzer": "stop",
  "text": "2 running Quick brown-foxes leap over lazy dogs in the summer evening."
}

结果:

{
  "tokens" : [
    {
      "token" : "running",
      "start_offset" : 2,
      "end_offset" : 9,
      "type" : "word",
      "position" : 0
    },
    {
      "token" : "quick",
      "start_offset" : 10,
      "end_offset" : 15,
      "type" : "word",
      "position" : 1
    },
    {
      "token" : "brown",
      "start_offset" : 16,
      "end_offset" : 21,
      "type" : "word",
      "position" : 2
    },
    {
      "token" : "foxes",
      "start_offset" : 22,
      "end_offset" : 27,
      "type" : "word",
      "position" : 3
    },
    {
      "token" : "leap",
      "start_offset" : 28,
      "end_offset" : 32,
      "type" : "word",
      "position" : 4
    },
    {
      "token" : "over",
      "start_offset" : 33,
      "end_offset" : 37,
      "type" : "word",
      "position" : 5
    },
    {
      "token" : "lazy",
      "start_offset" : 38,
      "end_offset" : 42,
      "type" : "word",
      "position" : 6
    },
    {
      "token" : "dogs",
      "start_offset" : 43,
      "end_offset" : 47,
      "type" : "word",
      "position" : 7
    },
    {
      "token" : "summer",
      "start_offset" : 55,
      "end_offset" : 61,
      "type" : "word",
      "position" : 10
    },
    {
      "token" : "evening",
      "start_offset" : 62,
      "end_offset" : 69,
      "type" : "word",
      "position" : 11
    }
  ]
}

9.Keyword Analyzer★

10.Pattern Analyzer

#pattern analyzer
GET _analyze
{
  "analyzer": "pattern",
  "text": "2 running Quick brown-foxes leap over lazy dogs in the summer evening."
}

结果:

{
  "tokens" : [
    {
      "token" : "2",
      "start_offset" : 0,
      "end_offset" : 1,
      "type" : "word",
      "position" : 0
    },
    {
      "token" : "running",
      "start_offset" : 2,
      "end_offset" : 9,
      "type" : "word",
      "position" : 1
    },
    {
      "token" : "quick",
      "start_offset" : 10,
      "end_offset" : 15,
      "type" : "word",
      "position" : 2
    },
    {
      "token" : "brown",
      "start_offset" : 16,
      "end_offset" : 21,
      "type" : "word",
      "position" : 3
    },
    {
      "token" : "foxes",
      "start_offset" : 22,
      "end_offset" : 27,
      "type" : "word",
      "position" : 4
    },
    {
      "token" : "leap",
      "start_offset" : 28,
      "end_offset" : 32,
      "type" : "word",
      "position" : 5
    },
    {
      "token" : "over",
      "start_offset" : 33,
      "end_offset" : 37,
      "type" : "word",
      "position" : 6
    },
    {
      "token" : "lazy",
      "start_offset" : 38,
      "end_offset" : 42,
      "type" : "word",
      "position" : 7
    },
    {
      "token" : "dogs",
      "start_offset" : 43,
      "end_offset" : 47,
      "type" : "word",
      "position" : 8
    },
    {
      "token" : "in",
      "start_offset" : 48,
      "end_offset" : 50,
      "type" : "word",
      "position" : 9
    },
    {
      "token" : "the",
      "start_offset" : 51,
      "end_offset" : 54,
      "type" : "word",
      "position" : 10
    },
    {
      "token" : "summer",
      "start_offset" : 55,
      "end_offset" : 61,
      "type" : "word",
      "position" : 11
    },
    {
      "token" : "evening",
      "start_offset" : 62,
      "end_offset" : 69,
      "type" : "word",
      "position" : 12
    }
  ]
}

11.Language Analyzer

选择不同国家的语音分词的结果是不同的!!

举例:

#english
GET _analyze
{
  "analyzer": "english",
  "text": "2 running Quick brown-foxes leap over lazy dogs in the summer evening."
}

结果:

{
  "tokens" : [
    {
      "token" : "2",
      "start_offset" : 0,
      "end_offset" : 1,
      "type" : "<NUM>",
      "position" : 0
    },
    {
      "token" : "run",
      "start_offset" : 2,
      "end_offset" : 9,
      "type" : "<ALPHANUM>",
      "position" : 1
    },
    {
      "token" : "quick",
      "start_offset" : 10,
      "end_offset" : 15,
      "type" : "<ALPHANUM>",
      "position" : 2
    },
    {
      "token" : "brown",
      "start_offset" : 16,
      "end_offset" : 21,
      "type" : "<ALPHANUM>",
      "position" : 3
    },
    {
      "token" : "fox",
      "start_offset" : 22,
      "end_offset" : 27,
      "type" : "<ALPHANUM>",
      "position" : 4
    },
    {
      "token" : "leap",
      "start_offset" : 28,
      "end_offset" : 32,
      "type" : "<ALPHANUM>",
      "position" : 5
    },
    {
      "token" : "over",
      "start_offset" : 33,
      "end_offset" : 37,
      "type" : "<ALPHANUM>",
      "position" : 6
    },
    {
      "token" : "lazi",
      "start_offset" : 38,
      "end_offset" : 42,
      "type" : "<ALPHANUM>",
      "position" : 7
    },
    {
      "token" : "dog",
      "start_offset" : 43,
      "end_offset" : 47,
      "type" : "<ALPHANUM>",
      "position" : 8
    },
    {
      "token" : "summer",
      "start_offset" : 55,
      "end_offset" : 61,
      "type" : "<ALPHANUM>",
      "position" : 11
    },
    {
      "token" : "even",
      "start_offset" : 62,
      "end_offset" : 69,
      "type" : "<ALPHANUM>",
      "position" : 12
    }
  ]
}

12. 中文分词 - ICU Analyzer

《1.》中文句子,切分成一个一个词(不是一个个字)

《2.》英文中,单词有自然的空格作为分隔

《3.》一句中文,在不同的上下文,有不同的理解

        eg: 这个苹果,不大好吃  =》这个苹果 , 不大,好吃

具体安装方式,参考:https://my.oschina.net/hanchao/blog/3070695

举例:

POST _analyze
{
  "analyzer": "standard",
  "text": "他说的确实在理”"
}

##################结果 ####################3
{
  "tokens" : [
    {
      "token" : "他",
      "start_offset" : 0,
      "end_offset" : 1,
      "type" : "<IDEOGRAPHIC>",
      "position" : 0
    },
    {
      "token" : "说",
      "start_offset" : 1,
      "end_offset" : 2,
      "type" : "<IDEOGRAPHIC>",
      "position" : 1
    },
    {
      "token" : "的",
      "start_offset" : 2,
      "end_offset" : 3,
      "type" : "<IDEOGRAPHIC>",
      "position" : 2
    },
    {
      "token" : "确",
      "start_offset" : 3,
      "end_offset" : 4,
      "type" : "<IDEOGRAPHIC>",
      "position" : 3
    },
    {
      "token" : "实",
      "start_offset" : 4,
      "end_offset" : 5,
      "type" : "<IDEOGRAPHIC>",
      "position" : 4
    },
    {
      "token" : "在",
      "start_offset" : 5,
      "end_offset" : 6,
      "type" : "<IDEOGRAPHIC>",
      "position" : 5
    },
    {
      "token" : "理",
      "start_offset" : 6,
      "end_offset" : 7,
      "type" : "<IDEOGRAPHIC>",
      "position" : 6
    }
  ]
}

icu-analyzer 的例子:

POST _analyze
{
  "analyzer": "icu_analyzer",
  "text": "他说的确实在理”"
}

############################### 结果 ###########################
{
  "tokens" : [
    {
      "token" : "他",
      "start_offset" : 0,
      "end_offset" : 1,
      "type" : "<IDEOGRAPHIC>",
      "position" : 0
    },
    {
      "token" : "说的",
      "start_offset" : 1,
      "end_offset" : 3,
      "type" : "<IDEOGRAPHIC>",
      "position" : 1
    },
    {
      "token" : "确实",
      "start_offset" : 3,
      "end_offset" : 5,
      "type" : "<IDEOGRAPHIC>",
      "position" : 2
    },
    {
      "token" : "在",
      "start_offset" : 5,
      "end_offset" : 6,
      "type" : "<IDEOGRAPHIC>",
      "position" : 3
    },
    {
      "token" : "理",
      "start_offset" : 6,
      "end_offset" : 7,
      "type" : "<IDEOGRAPHIC>",
      "position" : 4
    }
  ]
}
POST _analyze
{
  "analyzer": "icu_analyzer",
  "text": "这个苹果不大好吃”"
}

############## 结果 ###################
{
  "tokens" : [
    {
      "token" : "这个",
      "start_offset" : 0,
      "end_offset" : 2,
      "type" : "<IDEOGRAPHIC>",
      "position" : 0
    },
    {
      "token" : "苹果",
      "start_offset" : 2,
      "end_offset" : 4,
      "type" : "<IDEOGRAPHIC>",
      "position" : 1
    },
    {
      "token" : "不大",
      "start_offset" : 4,
      "end_offset" : 6,
      "type" : "<IDEOGRAPHIC>",
      "position" : 2
    },
    {
      "token" : "好吃",
      "start_offset" : 6,
      "end_offset" : 8,
      "type" : "<IDEOGRAPHIC>",
      "position" : 3
    }
  ]
}

《4.》更多的中文分词器

① IK 

     支持自定义词库,支持热更新分词词典

     https://github.com/medcl/elasticsearch-analysis-ik

② THULAC

     THU Lexucal Analyzer for Chinese ,清华大学自然语言处理和社会人文计算实验室的一套中文分词器

     https://github.com/microbun/elasticsearch-thulac-plugin

《5.》参考文档

https://www.elastic.co/guide/en/elasticsearch/reference/7.1/indices-analyze.html

https://www.elastic.co/guide/en/elasticsearch/reference/current/analyzer-anatomy.html

 

今天关于电脑入门学习-学习汉字输入法1电脑入门学打字教学全集视频的讲解已经结束,谢谢您的阅读,如果想了解更多关于CentOS安装中文汉字输入法ibus、Demo中学习React-入门学习、django 入门学习(外加 MTV 模式 学习)、Elasticsearch 简单学习 4: 入门学习 - 1的相关知识,请在本站搜索。

在本文中,我们将带你了解电脑入门学习-入门学习-汉字输入法2在这篇文章中,我们将为您详细介绍电脑入门学习-入门学习-汉字输入法2的方方面面,并解答电脑入门学打字教学全集视频常见的疑惑,同时我们还将给您一些技巧,以帮助您实现更有效的c# 多线程 —— 入门学习、c#入门学习笔记、C++ 入门学习笔记、C++介绍与入门学习

本文目录一览:

电脑入门学习-入门学习-汉字输入法2(电脑入门学打字教学全集视频)

电脑入门学习-入门学习-汉字输入法2(电脑入门学打字教学全集视频)

电脑技术网教你学电脑入门学习系列视频教程适合刚学电脑的朋友,讲的很简单易懂。对刚学电脑的朋友是比较有帮助的,能快速引导你学习电脑入门。看完这一系列教程,基本上对电脑操作知识有了大概的了解,让你知道可以从哪里入手操作电脑。已经有一定电脑知识的朋友可以跳过此教程。

c# 多线程 —— 入门学习

c# 多线程 —— 入门学习

1. 概念介绍

1.1 线程

  线程是操作系统能够进行运算调度的最小单位,包含在进程之中,是进程中的实际运作单位。一条线程指的时进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。.NET 中 System.Thread 下可以创建线程。

1.2 主线程

  每个 windows 进程都包含一个用做程序入口点的主线程。进程入口点(main 方法)中创建的第一个线程称为主线程,调用 main 方法时,主线程被创建。 

1.3 前台线程

  默认情况下,Thread.Start () 方法创建的线程都是前台线程,属性 isBackground=true/false 能够设置线程的线程是否为后台线程。前台线程能阻止应用程序的终结,只有所有的前台线程执行完毕,CLR(Common Language Runtime,公共语言运行库)才能关闭应用程序。前台线程属于工作者线程。

1.4 后台线程

  后台线程通过 isBackground 设置,它不会影响应用程序的终结,当所有前台线程执行完毕后,后台线程无论是否执行完毕,都会被终结。一般后台线程用来做无关紧要的任务(如邮箱天气更新等),后台线程也属于工作者线程。

2. 多线程实现

2.1 创建线程

  在 VS2019 中,建立一个控制台应用程序,测试多线程服务。首先开启 2 个线程 workThread、printThread,分别实现数字计数、打印字母。代码实现如下:

   class Program
    {
        static void Main(string[] args)
        {
            //新建两个线程,单独运行
            Thread workThread=new Thread(NumberCount);
            Thread printThread=new  Thread(printNumber);
            workThread.Start();
            printThread.Start();
            Console.WriteLine("Hello World!");
        }

        public static void NumberCount()
        {
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine("the number is {0}",i);
            }
        }

        public static void printNumber()
        {
            for (char i = ''A''; i < ''J''; i++)
            {

                Console.WriteLine("print character {0}", i);
            }
        }
    }

运行结果如下:

   根据上述运行结果可以看出,主线程 workThread 和其他线程 printThread 运行时相互独立,互不干扰。

2.2  线程基本属性了解

    static void Main(string[] args)
        {
            Thread th = Thread.CurrentThread;//访问当前正在运行的线程
            bool aliveRes=th.IsAlive;//当前线程的执行状态
            Console.WriteLine("IsAlive= {0}", aliveRes);
            th.IsBackground =false;//线程是否为后台线程
            Console.WriteLine("IsBackground= {0}", th.IsBackground);
            bool isPool= th.IsThreadPoolThread;//当前线程是否属于托管线程池
            Console.WriteLine("isPool= {0}", isPool);
            int sysbol = th.ManagedThreadId;//获取当前托管线程的唯一标识
            Console.WriteLine("ManagedThreadId= {0}", sysbol);
            ThreadPriority pry=th.Priority;//设置线程调度优先级
            Console.WriteLine("pry= {0}", pry);
            ThreadState state=th.ThreadState;//获取当前线程状态值
            Console.WriteLine("state= {0}", state);
            th.Name = "main thread";
            Console.WriteLine("this is {0}",th.Name);
            Console.ReadKey();
            Console.WriteLine("Hello World!");
        }

2.3 暂停线程

  暂停线程通过调用 sleep () 方法实现,使得线程暂停但不占用计算机资源,实现代码如下:

    static void NumberCountCouldDelay()
        {
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine("the number is {0}", i);
                Thread.Sleep(TimeSpan.FromSeconds(1));
            }
        }
        public static void printNumber()
        {
            for (char i = ''A''; i < ''J''; i++)
            {
                Console.WriteLine("print character {0}", i);
                Thread.Sleep(TimeSpan.FromSeconds(1));
            }
        }

运行结果如下:

2.4 线程池

  线程池是一种多线程处理形式,将任务添加到队列,然后再创建线程后自动启动这些任务。通过线程池创建的任务属于后台任务,每个线程使用默认的堆栈大小,以默认的优先级运行,并处于多线程单元中。如果某个线程在托管代码中空闲(如正在等待某个事件),则线程池将插入另一个辅助线程来使所有的处理器保持繁忙。

实现代码及运行结果如下:

 
    static void Main(string[] args)
        {
            Console.WriteLine("this is main thread: ThreadId={0}", Thread.CurrentThread.ManagedThreadId);
            ThreadPool.QueueUserWorkItem(printNumber);
            ThreadPool.QueueUserWorkItem(Go);
            Console.Read();
        }
       
        public static void printNumber(object data)
        {
            for (char i = ''A''; i < ''D''; i++)
            {
                Console.WriteLine("print character {0}", i);
                Console.WriteLine("the print process threadId is {0}", Thread.CurrentThread.ManagedThreadId);
            }
        }
        public static void Go(object data)
        {
            Console.Write("this is another thread:ThreadId={0}",Thread.CurrentThread.ManagedThreadId);
        }

2.5 中止线程

  线程中止采用 abort 方法,实现如下:

static void Main(string[] args)
        {
            ThreadStart childref = new ThreadStart(CallToChildThread);
            Console.WriteLine("In Main: Creating the child thread");
            Thread childThread = new Thread(childref);//创建线程,扩展的Thread类
            childThread.Start();//调用start()方法开始子线程的执行
            //停止主线程一段时间
            Thread.Sleep(2000);
            //现在中止子线程
            Console.WriteLine("In Main: Abort the child thread");
            childThread.Abort();
            Console.WriteLine("Hello World!");
        }
        public static void CallToChildThread()
        {
            try
            {
                //调用abort()方法销毁线程
                Console.WriteLine("Child thread start");
                for (int counter=0; counter<=10;counter++)
                {
                    Thread.Sleep(500);
                    Console.WriteLine(counter);
                }
                Console.WriteLine("child thread abort");
            }
            catch (ThreadAbortException e)
            {
                Console.WriteLine(e);
                throw;
            }
            finally
            {
                Console.WriteLine("Couldn''t catch the Thread Exception");
            }
        }

  运行程序,出现如下错误:

  经查找,发现.NET CORE 平台不支持线程中止,在调用 abort 方法时会抛出 ThreadAbortException 异常。

2.5 跨线程访问

  新建一个 winform 窗体应用程序,实现点击按钮为 textbox 赋值,代码如下:

private void Button1_Click(object sender, EventArgs e)
        {
            Thread thread=new Thread(test);
            thread.IsBackground = true;
            thread.Start();
            Console.ReadLine();
        }

        private void test()
        {
            for (int i = 0; i < 10; i++)
            {
                this.textBox1.Text = i.ToString();
            }
        }

  然而,运行时出现以下错误,内容显示 “线程间操作无效:从不是创建控件 textBox1 的线程访问它”。是因为控件 textBox1 是由主线程创建的,thread 作为另外一个线程,在.NET 上执行的是托管代码,c# 强制要求代码线程安全,不允许跨线程访问。

  上述问题解决办法如下:(参考 https://docs.microsoft.com/en-us/dotnet/framework/winforms/controls/how-to-make-thread-safe-calls-to-windows-forms-controls)

   利用委托实现回调机制,回调过程如下:

  (1)定义并声明委托;

  (2)初始化回调方法;

  (3)定义回调使用的方法

public partial class UserControl1: UserControl
    {
        private delegate void SetTextboxCallBack(int value);//定义委托

        private SetTextboxCallBack setCallBack;

        /// <summary>
        ///定义回调使用的方法
        /// </summary>
        /// <param name="value"></param>
        private void SetText(int value)
        {
            textBox1.Text = value.ToString();
        }
       public UserControl1()
        {
            InitializeComponent();
        }
        private void Button1_Click(object sender, EventArgs e)
        {
            //初始化回调函数
            setCallBack=new SetTextboxCallBack(SetText);
            //创建一个线程去执行这个回调函数要操作的方法
            Thread thread = new Thread(test);
            thread.IsBackground = true;
            thread.Start();
            Console.ReadLine();
        }
        public void test()
        {
            for (int i = 0; i < 10; i++)
            {
                //控件上执行回调方法,触发操作
                textBox1.Invoke(setCallBack,i);
            }
        }
  }        

运行结果如下:

 

2.5 多线程使用委托

  线程的创建通过 new Thread 来实现,c# 中该构造函数的实现有以下 4 种:

  • public Thread(ThreadStart start){}
  • public Thread(ParameterizedThreadStart start){}
  • public Thread(ThreadStart start, int maxStackSize){}
  • public Thread(ParameterizedThreadStart start, int maxStackSize){}

其中,参数 ThreadStart 定义为:

public delegate void ThreadStart();//无参数无返回值的委托

参数 ParameterizedThreadStart 定义为:

public delegate void ParameterizedThreadStart(object obj);//有参数无返回值的委托

因此,对无返回值的委托实现如下。

2.5.1 无参数无返回值的委托

  对于无参数无返回值的委托,是最简单原始的使用方法。Thread thread= new Thread (new ThreadStart (()=> 参数),其中参数为 ThreadStart 类型的委托。此类多线程代码实现如下:

class Program
    {
        public delegate void ThreadStart();//新建一个无参数、无返回值的委托
        static void Main(string[] args)
        {
            Thread thread=new Thread(new System.Threading.ThreadStart(NumberCount));
            thread.IsBackground = true;
            thread.Start();
            for (char i = ''A''; i < ''D''; i++)
            {
                Console.WriteLine("print character {0},the threadId id ={1}", i, Thread.CurrentThread.ManagedThreadId);
            }
            Console.WriteLine("Hello World!");
        }

        public static void NumberCount()
        {
            for (int i = 0; i < 3; i++)
            {
                Console.WriteLine("the number is {0},the threadId id ={1}", i, Thread.CurrentThread.ManagedThreadId);
            }
        }
    }

2.5.2 有参数无返回值的委托

  对于有参数无返回值的委托,实现代码如下:

class Program
    {
        public delegate void ThreadStart(int i);//新建一个无参数、无返回值的委托
        static void Main(string[] args)
        {
            Thread thread=new Thread(new ParameterizedThreadStart(NumberCount));
            thread.IsBackground = true;
            thread.Start(3);
            for (char i = ''A''; i < ''D''; i++)
            {
                Console.WriteLine("print character {0},the threadId id ={1}", i, Thread.CurrentThread.ManagedThreadId);
            }
            Console.WriteLine("Hello World!");
        }

        public static void NumberCount(object i)
        {
           Console.WriteLine("the number is {0},the threadId id ={1}", i, Thread.CurrentThread.ManagedThreadId);
        }

    }

运行结果为:

2.5.2 有参数有返回值的委托

   对于有参数有返回值的委托,采用异步调用实现,如下所示:

2.6 异步实现

2.6.1 Task.Result

   ..NET 中引入了 System.Threading.Tasks,简化了异步编程的方式,而不用直接和线程、线程池打交道。 System.Threading.Tasks 中的类型被称为任务并行库(TPL),TPL 使用 CLR 线程池(TPL 创建的线程都是后台线程)自动将应用程序的工作动态分配到可用的 CPU 的中。

  Result 方法可以返回 Task 执行后的结果。但是在.NET CORE 的 webapi 中使用 result 方法来获取 task 的输出值,会造成当前 API 线程阻塞等待到 task 执行完成后再继续。以下代码中,get 方法中的线程 id-57, 调用一个新线程执行 task 后,等待 TaskCaller () 执行结果(threadid=59), 待 TaskCaller () 方法执行完成后,原来的线程继续之后之后的语句,输出 threadid=57

  public class ValuesController:Controller
    {
        //async/await是用来进行异步调用的形式,
        [HttpGet("get")]
        public async Task<string> Get()
        {
            var info = string.Format("api执行线程{0}",Thread.CurrentThread.ManagedThreadId);//get方法中的线程
            //调用新线程执行task任务
            var infoTask = TaskCaller().Result;//调用result方法获取task的值
            var infoTaskFinished = string.Format("api执行线程(taks调用completed){0}", Thread.CurrentThread.ManagedThreadId);
            return string.Format("{0},{1},{2}", info, infoTask, infoTaskFinished);
        }
        public async Task<string> TaskCaller()
        {
            await Task.Delay(5000);
            return string.Format("task 执行线程{0}", Thread.CurrentThread.ManagedThreadId);
        }
    }

运行结果如下:

 2.6.2 Async&Await

  c# 中 async 关键字用来指定方法,Lambda 表达式或匿名方法自动以异步的方式来调用。async/await 是用来进行异步调用的形式,内部采用线程池进行管理。如果使用 await,在调用 await tasjCall () 是不会阻塞 get 方法的主线程,主线程会被释放,新的线程执行完 task 后继续执行 await 后的代码,从而减少了线程切换的开销,而之前的线程则空闲了。

public class ValuesAwaitController : Controller
    {
        [HttpGet("get")]
        public async Task<string> Get()
        {
            var info = string.Format("api执行线程{0}",Thread.CurrentThread.ManagedThreadId);//get方法中的线程
            //调用新线程执行task任务
            var infoTask = await TaskCaller();//使用await调用不会阻塞Get()中线程
            var infoTaskFinished = string.Format("api执行线程(taks调用completed){0}", Thread.CurrentThread.ManagedThreadId);
            return string.Format("{0},{1},{2}", info, infoTask, infoTaskFinished);
        }
        public async Task<string> TaskCaller()
        {
            await Task.Delay(5000);
            return string.Format("task 执行线程{0}", Thread.CurrentThread.ManagedThreadId);
        }
    }

运行结果如下:

 

   Task.result 与 await 关键字具有类似的功能可以获取到任务的返回值,但本质上 Task.result 会让外层函数执行线程阻塞知道任务完成,而使用 await 外层函数线程不会阻塞,而是通过任务执行线程来执行 await 后的代码。

  • 默认创建的 Thread 是前台线程,创建的 Task 为后台线程;
  • ThreadPool 创建的线程都是后台线程;
  • 任务并行库 (TPL) 使用的是线程池计数;
  • 调用 async 标记的方法,刚开始是同步执行,只有当执行到 await 标记的方法中的异步任务时,才会挂起。

c#入门学习笔记

c#入门学习笔记

  1. Hello World

     //打印语句
     Console.WriteLine("Hello World");
     //暂停
     Console.ReadKey();
    
  2. 数据类型
    1.值类型 byte,char,short,int,long,bool,decimal,float,double,sbyte,uint,ulong,ushort
    2.引用类型: 储存的不是值实际数据而是一个内存地址 object、dynamic 和 string。
    3.对象类型:Object 类型检查是在编译时发生的
    4.动态类型: 可以存储任何类型的值在动态数据类型变量中,类型检查在运行时
    5.字符串(String)类型
    6.指针类型(Pointer types)

  3. 类型转换

    1. 隐式转换
    2. 显式转换
    3. Toxxx方法
  4. 变量

  5. 常量

    1. 整数常量
      • 整数常量可以是十进制、八进制或十六进制的常量。前缀指定基数:0x 或 0X 表示十六进制,0 表示八进制,不带前缀则默认表示十进制。
      • 整数常量也可以带一个后缀,后缀是 U 和 L 的组合,U 表示无符号整数(unsigned),L 表示长整数(long)。后缀可以是大写,也可以是小写,U 和 L 的顺序任意。
    2. 浮点常量(小数必须包含整数)
    3. 字符常量
    4. 字符串常量
    5. 定义常量
  6. 运算符

    1. 算数运算符
    2. 关系运算符
    3. 逻辑运算符
    4. 位运算符
    5. 赋值运算符
    6. 其他运算符
      1. sizeof():数据类型的大小
      2. typeof():返回 class的类型。
      3. &: 返回变量的地址
      4. *:变量的指针
      5. ?: :三元表达式
      6. is:判断对象是否为某一类型
      7. as: 强制转换,即使失败也不会抛出异常
  7. 判断:

    1. if
    2. switch
  8. 循环:

    1. while循环
    2. for/foreach
    3. do…while
  9. 封装:

    1. public:允许一个类将其成员变量和成员函数暴露给其他的函数和对象。任何公有成员可以被外部的类访问
    2. private:允许一个类将其成员变量和成员函数对其他的函数和对象进行隐藏。只有同一个类中的函数可以访问它的私有成员。即使是类的实例也不能访问它的私有成员。
    3. protected:该类内部和继承类中可以访问。
    4. internal:同一个程序集的对象可以访问。
    5. protected internal:3 和 4 的并集,符合任意一条都可以访问。
  10. 可空类型

    • //默认值为0
      int a;
      //默认值为null
      int? b=123;
      //如果b为null就赋值2否则c=b
      int c=  b?? 2;
      Console.WriteLine("c的值为{0}", c);
      Console.ReadLine();
      
  11. 数组

    //初始化数组逐个赋值
    int[] arr = new int[10];
    arr[0] = 12312;
    //初始化数组并赋值
    int[] arr1 = { 321, 312, 12312, 12312312, 12312312 };
    //使用for循环赋值
    for (int i = 0; i < 10; i++)
    {
    arr[i] = i + 100;
    }
    //使用forEach取值
    foreach (int i in arr)
    {
    Console.WriteLine("元素的值为{0}", i);
    }
    
  12. 结构体

    struct Books{
    public string id;
    public string name;
    public string price;
    }
    static void Main()
    {
    Books book1;
    book1.id = "123";
    book1.name = "aaa";
    book1.price = "23131";
    Console.WriteLine("书信息:书id{0},书名{1},书价格{2}",book1.id,book1.name,book1.price);
    Console.ReadLine();
    }
    
    • 类与结构的不同点
      1. 类是引用类型,结构是值类型
      2. 结构不支持继承
      3. 结构不能声明默认的构造函数
      4. 结构体中无法实例属性或赋初始值
    • 类与结构的选择
      1. 当我们描述一个轻量级对象的时候,结构可提高效率,成本更低。数据保存在栈中,访问速度快
      2. 当堆栈的空间很有限,且有大量的逻辑对象或者表现抽象和多等级的对象层次时,创建类要比创建结构好一些;
  13. 枚举

    //枚举列表中的每个符号代表一个整数值,一个比它前面的符号大的整数值,可自定义每个符号
    enum Days { Sun, Mon, Tue, Wed, Thu, Fri, Sat };
    static void Enum()
    {
    int a = (int)Days.Wed;
    Console.WriteLine(a);
    Console.ReadLine();
    }
    
  14. 析构函数

    class Test
    {
        string id;
        public Test()
        {
            Console.WriteLine("构造函数");
        }
        ~Test()
        {
            Console.WriteLine("析构函数");
        }
        static void Main()
        {
            Test test = new Test { id = "123" };
            Console.WriteLine("id为{0}", test.id);
            Console.ReadLine();
        }
    
    }
    
  15. 多态性

    1. 通过在类定义前面放置关键字 sealed,可以将类声明为密封类。当一个类被声明为 sealed 时,它不能被继承。抽象类不能被声明为 sealed。
    2. 当有一个定义在类中的函数需要在继承类中实现时,可以使用虚方法。虚方法是使用关键字 virtual 声明的。虚方法可以在不同的继承类中有不同的实现。
  16. 运算符的重载

    class Test2
        {
            public int length;
            //运算符重载  
            public static Test2 operator +(Test2 a, Test2 b)
            {
                Test2 test = new Test2 { length = a.length - b.length };
                return test;
            }
            static void Main(string[] args)
            {
                Test2 test = new Test2 { length = 12 };
                Test2 test1 = new Test2 { length = 213 };
                Test2 t = test + test1;
                Console.WriteLine("t的值{0}", t.length);
                Console.ReadLine();
            }
        }
    
  17. 预处理器指令

    1. define 预处理器

    2. 条件指令
  18. 异常处理

    1. try catch finally
    2. 常见异常:
      1. IO异常
      2. 空对象
      3. 类型转换
      4. 除以0
  19. 文件的输入与输出

     //字节流读取文件
     static void Main(string[] args)
     {
     StreamReader streamReader =new StreamReader(@"D:\Document\test.txt");
     string line;
     //读取文件内容
     while ((line = streamReader.ReadLine()) != null)
     {
     //打印出来
     Console.WriteLine(line);
     }
     Console.ReadLine();
     }
    
  20. windows文件系统操作

     static void Main(string[] args) {
            GetFile(@"D:\ProgramFiles");
            Console.ReadLine();
        }
        //获得某文件夹下的文件名与大小
        static void GetFile(String path) {
            DirectoryInfo directoryInfo = new DirectoryInfo(path);
            DirectoryInfo[] directoryInfo1 = directoryInfo.GetDirectories();
            FileInfo[] files = directoryInfo.GetFiles();
            if(directoryInfo1!=null) {
                foreach(DirectoryInfo directoryInfo2 in directoryInfo1) {
                    if(directoryInfo2.Name!="app") {
                        GetFile(path+@"\"+directoryInfo2.Name);
                    }
                }
            }
            if(files!=null) {
                foreach(FileInfo file in files) {
                    Console.WriteLine("文件名:{0},文件大小{1}",file.Name,file.Length);
                }
            }
        }
    
  21. 特性

    1. 预定义特性
      1.AttributeUsage
      2.Conditional
      3.Obsolete: [Obsolete("过时了")]编译器会给出警告信息[Obsolete("过时了",true)]编译器会给出错误信息

    2. 自定义特性

  22. 委托

    delegate void ConsoleWrite1();
    namespace ConsoleApp1 {
        class Program {
    
            static void Main(string[] args) {
                ConsoleWrite1 consoleWrite1 = new ConsoleWrite1(ConsoleWrite);
                consoleWrite1();
                Console.ReadLine();
            }
            static void ConsoleWrite() {
                Console.WriteLine("测试");
            }
    
    • 委托的用途

               static FileStream fs;
        static StreamWriter sw;
        // 委托声明
        public delegate void printString(string s);
      
        // 该方法打印到控制台
        public static void WriteToScreen(string str) {
            Console.WriteLine("The String is: {0}",str);
        }
        // 该方法打印到文件
        public static void WriteToFile(string s) {
            fs=new FileStream(@"D:\Document\test.txt",
            FileMode.Append,FileAccess.Write);
            sw=new StreamWriter(fs);
            sw.WriteLine(s);
            sw.Flush();
            sw.Close();
            fs.Close();
        }
        // 该方法把委托作为参数,并使用它调用方法
        public static void sendString(printString ps) {
            ps("Hello World");
        }
        static void Main(string[] args) {
            printString ps1 = new printString(WriteToScreen);
            printString ps2 = new printString(WriteToFile);
            sendString(ps1);
            sendString(ps2);
            Console.ReadKey();
        }
      
    1. 指针变量
       static unsafe void Test12() {
       int i = 0;
       int* p = &i;
       Console.WriteLine("i的值为{0},内存地址为{1}",i,(int)p);
       Console.WriteLine();
       }
      
    2. 传递指针作为方法的参数
           static unsafe void Main() {
           int var1 = 10;
           int var2 = 20;
           Console.WriteLine("var1:{0},var2:{1}",var1,var2);
           int* a = &var1;
           int* b = &var2;
           Swap(a,b);
           Console.WriteLine("var1:{0},var2:{1}",var1,var2);
           Console.ReadLine();
       }
       static unsafe void Swap(int* a,int* b) {
           int temp =*a;
           *a=*b;
           *b=temp;
       }
      
    3. 使用指针访问数组元素
                static unsafe void array() {
                       int[] list = { 10,100,200 };
                       fixed (int* ptr = list)
                         /* 显示指针中数组地址 */
                         for(int i = 0;i<3;i++) {
                             Console.WriteLine("Address of list[{0}]={1}",i,(int)(ptr+i));
                         Console.WriteLine("Value of list[{0}]={1}",i,*(ptr+i));
               }
                 Console.ReadKey();
      
  23. out参数:一个方法返回多个不同类型的参数

      static void Main() {
           string s="asd";
           int i=Test7(out s);
           Console.WriteLine(s);
           Console.WriteLine(i);
           Console.ReadLine();
    
       }
    
       public static int Test7(out string a) {
           a="asddddddddddd";
           return 1;
       }
    
  24. params参数
     static void Main() {
            Params(213,31231,12312,13231,123,1312,312,312,321,3,12,312,12);
        }
        static void Params(params int[] array) {
            int max = array[0];
            for(int i = 0;i<array.Length;i++) {
                if(array[i]>max) {
                    max=array[i];
                }
            }
            Console.WriteLine("最大值为{0}",max);
            Console.ReadLine();
        }
    
  25. ref参数
    static void Main() {
            int i = 30;
            Ref(ref i);
            Console.WriteLine(i);
            Console.ReadKey();
        }
        static void Ref(ref int a) {
            a+=500;
        }
    
  26. 连接数据库
        static void MysqlConnection() {
            //配置连接信息
            String connstr = "server=localhost;port=3306;user=root;password=123456;database=ztree";
            MySqlConnection mySqlConnection = new MySqlConnection(connstr);
            //打开连接
            mySqlConnection.Open();
            //sql语句
            string sql = "select * from city";
            MySqlCommand mySqlCommand = new MySqlCommand(sql,mySqlConnection);
            //执行sql语句
            MySqlDataReader mySqlDataReader = mySqlCommand.ExecuteReader();
            while(mySqlDataReader.Read()) {
                if(mySqlDataReader.HasRows) {
                    Console.WriteLine("id:{0};name:{1};pid:{2}",mySqlDataReader.GetString(0),mySqlDataReader.GetString(1),mySqlDataReader.GetString(2));
                }
            }
            mySqlConnection.Close();
        }
    

C++ 入门学习笔记

C++ 入门学习笔记

1、C++ 11 以前的版本,嵌套 vector 的尖括号,右尖括号之间需要留空格

std::vecotr<std::vector<int> >

C++介绍与入门学习

C++介绍与入门学习

C++是C语言的继承,它既可以进行C语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的程序设计,还可以进行以继承和多态为特点的面向对象的程序设计。C++擅长面向对象程序设计的同时,还可以进行基于过程的程序设计,因而C++就适应的问题规模而论,大小由之。

C++不仅拥有计算机高效运行的实用性特征,同时还致力于提高大规模程序的编程质量与程序设计语言的问题描述能力。

免费教程链接:C++ 入门教程(开发文档)

语言特点:

支持数据封装和数据隐藏

在C++中,类是支持数据封装的工具,对象则是数据封装的实现。C++通过建立用户定义类支持数据封装和数据隐藏。

在面向对象的程序设计中,将数据和对该数据进行合法操作的函数封装在一起作为一个类的定义。对象被说明为具有一个给定类的变量。每个给定类的对象包含这个类所规定的若干私有成员、公有成员及保护成员。完好定义的类一旦建立,就可看成完全封装的实体,可以作为一个整体单元使用。类的实际内部工作隐藏起来,使用完好定义的类的用户不需要知道类是如何工作的,只要知道如何使用它即可。

支持继承和重用

在C++现有类的基础上可以声明新类型,这就是继承和重用的思想。通过继承和重用可以更有效地组织程序结构,明确类间关系,并且充分利用已有的类来完成更复杂、深入的开发。新定义的类为子类,成为派生类。它可以从父类那里继承所有非私有的属性和方法,作为自己的成员。

支持多态性

采用多态性为每个类指定表现行为。多态性形成由父类和它们的子类组成的一个树型结构。在这个树中的每个子类可以接收一个或多个具有相同名字的消息。当一个消息被这个树中一个类的一个对象接收时,这个对象动态地决定给予子类对象的消息的某种用法。多态性的这一特性允许使用高级抽象。

继承性和多态性的组合,可以轻易地生成一系列虽然类似但独一无二的对象。由于继承性,这些对象共享许多相似的特征。由于多态性,一个对象可有独特的表现方式,而另一个对象有另一种表现方式。

工作原理编辑

C++语言的程序因为要体现高性能,所以都是编译型的。但其开发环境,为了方便测试,将调试环境做成解释型的。即开发过程中,以解释型的逐条语句执行方式来进行调试,以编译型的脱离开发环境而启动运行的方式来生成程序最终的执行代码。[9]

生成程序是指将源码(C++语句)转换成一个可以运行的应用程序的过程。如果程序的编写是正确的,那么通常只需按一个功能键,即可搞定这个过程。该过程实际上分成两个步骤。

第一步是对程序进行编译,这需要用到编译器(compiler)。编译器将C++语句转换成机器码(也称为目标码);如果这个步骤成功,下一步就是对程序进行链接,这需要用到链接器(linker)。链接器将编译获得机器码与C++库中的代码进行合并。C++库包含了执行某些常见任务的函数(“函数”是子程序的另一种称呼)。例如,一个C++库中包含标准的平方根函数sqrt,所以不必亲自计算平方根。C++库中还包含一些子程序,它们把数据发送到显示器,并知道如何读写硬盘上的数据文件。

语言评价:

C++是在C语言的基础上开发的一种面向对象编程语言,应用非常广泛。常用于系统开发,引擎开发等应用领域,支持类、封装、继承、多态等特性。C++语言灵活,运算符的数据结构丰富、具有结构化控制语句、程序执行效率高,而且同时具有高级语言与汇编语言的优点。

C++语言是对C语言的扩充,从Simula中吸取了类,从ALGOL语言中吸取了运算符的一名多用、引用和在分程序中任何位置均可说明变量,综合了Ada语言的类属和Clu语言的模块特点,形成了抽象类,从Ada Clu和ML等语言吸取了异常处理,从BCPL语言中吸取了用//表示注释C++语言保持了C语言的紧凑灵活、高效以及易于移植性强等优点,它对数据抽象的支持主要在于类概念和机制,对面向对象风范的支持主要通过虚拟机制函数因C++语言既有数据抽象和面向对象能力,运行性能高,加上C语言的普及,而从C语言到C++语言的过渡较为平滑,以及C++语言与C语言的兼容程度可使数量巨大的C语言程序能方便地在C++语言环境中复用,使C++语言在短短几年内能流行。

免费C++ 入门教程:阿里云大学—开发者课堂

今天的关于电脑入门学习-入门学习-汉字输入法2电脑入门学打字教学全集视频的分享已经结束,谢谢您的关注,如果想了解更多关于c# 多线程 —— 入门学习、c#入门学习笔记、C++ 入门学习笔记、C++介绍与入门学习的相关知识,请在本站进行查询。

以上就是给各位分享电脑入门学习-多媒体学习-internet学习01,其中也会对多媒体教学电脑进行解释,同时本文还将给你拓展(已导出)【kubernetes系列学习】client-go学习与实践、.net学习笔记之 AJAX学习、.NET开发人员关于ML.NET的入门学习、Android多媒体学习等相关知识,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!

本文目录一览:

电脑入门学习-多媒体学习-internet学习01(多媒体教学电脑)

电脑入门学习-多媒体学习-internet学习01(多媒体教学电脑)

电脑技术网教你学电脑入门学习系列视频教程适合刚学电脑的朋友,讲的很简单易懂。对刚学电脑的朋友是比较有帮助的,能快速引导你学习电脑入门知识。看完这一系列教程,基本上对电脑操作知识有了大概的了解,让你知道可以从哪里入手操作电脑。已经有一定电脑知识的朋友可以跳过此教程。

(已导出)【kubernetes系列学习】client-go学习与实践

(已导出)【kubernetes系列学习】client-go学习与实践

【kubernetes系列学习】client-go学习与实践

release author: ningan123

release time: 2022-08-09

client-go客户端对象

client-go支持RESTClient、ClientSet、Dynamicclient、discoveryClient四种客户端与Kubernetes Api Server进行交互。

  • RESTClient:最基础的客户端,主要是对HTTP请求进行了封装,支持Json和Protobuf格式的数据。

  • discoveryClient:发现客户端,负责发现APIServer支持的资源组、资源版本和资源信息的(GVR)。

  • ClientSet:负责操作Kubernetes内置的资源对象,例如:Pod、Services等。

  • Dynamicclient:动态客户端,可以对任意的Kubernetes资源对象进行通用操作,包括CRD。

client-go-demo 工程初始化

[root@master ~]# mkdir client-go-demo
[root@master ~]#
[root@master ~]#
[root@master ~]# cd client-go-demo/
[root@master client-go-demo]#
[root@master client-go-demo]# ll
总用量 0
[root@master client-go-demo]#
[root@master client-go-demo]#
[root@master client-go-demo]# go mod init ningan.com/client-go-demo
go: creating new go.mod: module ningan.com/client-go-demo
[root@master client-go-demo]#
[root@master client-go-demo]# ll
总用量 4
-rw-r--r-- 1 root root 42 89 04:06 go.mod
[root@master client-go-demo]#
[root@master client-go-demo]# cat go.mod
module ningan.com/client-go-demo

go 1.17



RESTClient

RESTClient是最基础的客户端,其他的ClientSet、Dynamicclient即DscoveryClient都是基于RESTClient实现的。

RESTClient对HTTP Client进行了封装,实现了Restful风格的API。

它具有很高的灵活性,数据不依赖于方法和资源,因此RESTClient能够处理多种类型的调用,返回不同的数据格式。

demo示例:通过RESTClient示例列出某一命名空间下的Pod资源对象

package main

import (
	"context"
	"fmt"

	corev1 "k8s.io/api/core/v1"
	Metav1 "k8s.io/apimachinery/pkg/apis/Meta/v1"
	"k8s.io/client-go/kubernetes/scheme"
	"k8s.io/client-go/rest"
	"k8s.io/client-go/tools/clientcmd"
)

/*
	@Author: ningan
	@Desc: 获取kube-system命名空间下的Pod列表
*/

func main() {
	/*
		1. k8s的配置文件
		2. 保证开发机能通过这个配置文件连接到k8s集群
	*/

	// 1. 加载配置文件,生成config对象
	config, err := clientcmd.BuildConfigFromFlags("", "/root/.kube/config")
	if err != nil {
		panic(err)
		// panic(err.Error())
	}

	// 2. 配置API路径  请求的HTTP路径
	config.APIPath = "api" // pods,  /api/v1/pods
	// config.APIPath = "apis" // deployments,  /apis/apps/v1/namespaces/{namespace}/deployments/{deployment}

	// 3. 配置请求的资源组/资源版本 GV
	config.GroupVersion = &corev1.SchemeGroupVersion // 无名资源组, group: " ", version: "v1"

	// 4. 配置数据的编解码工具  序列化和反序列化
	config.NegotiatedSerializer = scheme.Codecs

	// 5. 通过kubeconfg配置信息实例化RESTClient对象
	restClient, err := rest.RESTClientFor(config)
	if err != nil {
		panic(err)
	}

	// 6. 定义接收返回值的变量
	result := &corev1.PodList{}

	// 跟APIServer交互
	err = restClient.
		Get().                                                                  // RESTClient对象构建HTTP请求参数  请求方法:Get、Post、Put、Delete、Patch
		Namespace("kube-system").                                               // 命名空间
		Resource("pods").                                                       // 资源名
		VersionedParams(&Metav1.ListOptions{Limit: 50}, scheme.ParameterCodec). // 将一些查询选项(如limit、TimeoutSeconds)添加到请求参数中 limit参数表示最多检索出多少信息
		Do(context.Todo()).                                                     // 执行该请求
		Into(result)                                                            // 将kube-apiserver返回的结果(Result对象)解析到corev1.PodList对象中
	if err != nil {
		panic(err)
	}

	/*
		1)Get定义请求方式,返回了一个Request结构体对象。这个Request结构体对象,就是构建访问APIServer用的。
		2)依次执行了Namespace、Resource、VersionedParams,构建与APIServer交互的参数。
		3)Do方法通过requets发起请求,然后通过transformResponse解析请求返回,并绑定到对应资源对象的结构体对象上。这里的话,表示的是corev1.PodList对象。
		4)request先是检查了有没有可用的client,在这里开始调用net/Http包的功能。
	*/

	/*
		1) RESTClient发送请求的过程对Go语言标准库net/http进行了封装,由Do -> Request函数实现。
		2) 请求发送之前需要根据请求参数生成请求的RESTful URL,由r.URL().String()函数完成。 http://xxxx:x/api/v1/namespaces/kube-system/pods?limit=1
		3) 通过Go语言标准库net/http向RESTful URL(即kube-apiserver)发送请求,请求得到的结果存放在http.Response的Body对象中,fn函数(即transformResponse)将结果转化为资源对象。
	*/

	// 格式化输出结果
	for _, item := range result.Items {
		fmt.Printf("namespace: %v, name: %v, status: %v\n", item.Namespace, item.Name, item.Status.Phase)
	}
}

运行:

[root@master demo1]# go run main.go
namespace: kube-system, name: calico-kube-controllers-67878b879f-2x5xg, status: Running
namespace: kube-system, name: calico-node-4xwrz, status: Running
namespace: kube-system, name: metrics-server-68955dc6f-xvv9t, status: Running

ClientSet

RESTClient是一张最基础的客户端,使用时需要指定Resource和Version等信息,编写代码需要提前知道Resource所在的Group和对应的Version信息。

相比RESTClient,ClientSet使用起来更加便捷,一般情况下,开发者对Kubernetes进行二次开发时通常使用ClientSet。

ClientSet在RESTClient的基础上封装了对Resource和Version的管理方法。每一个Resource可以理解为一个客户端,而ClientSet则是多个客户端的几核,每一个Resource和Version都以函数的方法暴露给开发者,例如ClientSet提供的RbacV1、CoreV1、NetworkingV1等接口参数。

demo示例:通过ClientSet示例列出某一命名空间下的Pod资源对象

package main

import (
	"context"
	"fmt"

	Metav1 "k8s.io/apimachinery/pkg/apis/Meta/v1"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/tools/clientcmd"
)

/*
	@Author: ningan
	@Desc: 获取kube-system命名空间下的Pod列表
*/

func main() {
	// 1. 加载配置文件,生成config对象
	config, err := clientcmd.BuildConfigFromFlags("", "/root/.kube/config")
	if err != nil {
		panic(err.Error())
	}

	// 2. 通过kubeconfig配置信息实例化ClientSet 该对象用于管理所有Resource的客户端
	clientset, err := kubernetes.NewForConfig(config)
	if err != nil {
		panic(err.Error())
	}

	// 3. 查询
	result, err := clientset.
		CoreV1().            // 返回CoreV1Client实例
		Pods("kube-system"). // 指定查询的资源预计指定资源的namespace,namespace如果为空,表示查询所有namespace
		// Namespaces().     // 查询namespace
		List(context.Todo(), Metav1.ListOptions{Limit: 50})
	if err != nil {
		panic(err.Error())
	}
	/*
		1) CoreV1返回CoreV1Client实例对象
		2) Pods 调用了newPods函数,该函数返回的试PodInterface对象,PodInterface对象实现了Pods资源相关的全部方法,同时再newPods里面还将RESTClient实例对象赋值给了对应的Client属性
		3) List内部使用RestClient与k8s APIServer进行了交互
	*/

	/*
		1) clientset.CoreV1().Pods表示请求core核心资源组的v1资源版本下的Pod资源对象,其内部设置了APIPath请求的HTTP路径,GroupVersion请求的资源组、资源版本,NegotiatedSerializer数据的编解码器。
		2) Pods函数是一个资源对象接口,用于Pod资源对象的管理。例如,对Pod资源执行Create、Update、Delete、Get、List、Watch、Patch等操作,这些操作实际上是对RESTClient进行了封装,可以设置选项(如Limit、TimeoutSeconds等)。
	*/

	// 4. 格式化输出结果
	for _, item := range result.Items {
		fmt.Printf("namespace: %v, name: %v, status: %v\n", item.Namespace, item.Name, item.Status.Phase)
	}

}

Dynamicclient

Dynamicclient是一种动态客户端,它可以对任意Kubernetes资源进行RESTFul操作,包括CRD自定义资源。

Dynamicclient与ClientSet操作类似,同样封装了RESTClient,同样提供了Create、Update、Delete、Get、List、Watch、Patch等方法。

Dynamicclient与ClientSet最大的不同之处在于:

  • ClientSet仅能访问Kubernetes自带的资源(即客户端几核内的资源),不能直接访问CRD自定义资源。ClientSet需要预先实现每种Resource和Version的操作,其内部的数据都是结构化数据(即已知数据结构)

  • Dynamicclient内部实现了Unstructured,用于处理非结构化数据结构(即无法提前预知数据结构),这也是Dynamicclient能够处理CRD自定义资源的关键。

Dynamicclient的处理过程将Resource(例如PodList)转化成Unstructured结构类型,Kubernetes的所有Resource都可以转化为该结构类型。处理完成后,再将Unstructured转换成PodList。整个过程类似于Go语言的interface{}断言转换过程。另外,Unstructured结构类型是通过map[string]interface{}转换的。

两个重要的知识点:

  • Object.runtime:Kubernetes中的所有资源对象都实现了这个接口,其中包含DeepcopyObject和GetobjectKind的方法,分别用于对象深拷贝和获取对象的具体资源类型。
  • Unstructured:包含map[string]interface{}类型字段,在处理无法预知结构的数据时,将数据值存入interface{}中,待运行时利用反射判断。该结构体提供了大量的工具方法,便于处理非结构化的数据。

demo示例:通过Dynamicclient示例列出某一命名空间下的Pod资源对象

package main

import (
	"context"
	"fmt"

	corev1 "k8s.io/api/core/v1"
	Metav1 "k8s.io/apimachinery/pkg/apis/Meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/client-go/dynamic"
	"k8s.io/client-go/tools/clientcmd"
)

/*
	@Author: ningan
	@Desc: 获取kube-system命名空间下的Pod列表
*/

func main() {
	// 1. 加载配置文件,生成config对象
	config, err := clientcmd.BuildConfigFromFlags("", "/root/.kube/config")
	if err != nil {
		panic(err.Error())
	}

	// 2. 通过kubeconfig配置信息实例化客户端对象,这里是实例化动态客户端对象。该对象用于管理Kubernetes的所有Resource的客户端,例如对Resource执行Create、Update、Delete、Get、List、Watch、Patch等操作。
	dynamicclient, err := dynamic.NewForConfig(config)
	if err != nil {
		panic(err.Error())
	}

	// 3. 配置需要调用的GVR
	gvr := schema.GroupVersionResource{
		Group:    "",
		Version:  "v1",
		Resource: "pods",
	}

	// 4. 发送请求,并得到返回结果
	unstructedobj, err := dynamicclient.
		Resource(gvr).
		Namespace("kube-system").
		List(context.Todo(), Metav1.ListOptions{})
	if err != nil {
		panic(err.Error())
	}

	// 5. unstructedobj转化为结构化数据
	podList := &corev1.PodList{}
	err = runtime.DefaultUnstructuredConverter.FromUnstructured(
		unstructedobj.UnstructuredContent(),
		podList,
	)
	if err != nil {
		panic(err.Error())
	}
	/*
		1) Resource:基于gvr生成了一个针对于资源的客户端,也可以称之为动态资源客户端,dunamicResourceClient
		2) Namespace:指定一个可操作的命名空间,同时它是dynamicResourceClient的方法
		3) List:首先通过RESTClient调用k8s APIServer的接口返回了Pod的数据,返回的数据格式是二进制的Json格式,然后通过一些列的解析方法,转换成unstructured.UnstructuredList
	*/

	/*
		1) dynamicclient.Resource()函数用于设置请求的资源组、资源版本、资源名称。
		2) Namespace函数用于设置请求的命名空间。
		3) List函数用户获取Pod列表,得到的Pod列表为unstructured.UnstructuredList指针类型
		4) 然后通过runtime.DefaultUnstructuredConverter.FromUnstructured函数将unstructured.UnstructuredList转换为PodList类型。
	*/

	// 6. 格式化输出结果
	for _, item := range podList.Items {
		fmt.Printf("namespace: %v, name: %v, status: %v\n", item.Namespace, item.Name, item.Status.Phase)
	}
}

discoveryClient

discoveryClient是发现客户端,它主要用于发现Kubernetes API Server所支持的资源组、资源版本、资源信息。

Kubernetes API Server支持很多资源组、资源版本、资源信息,开发者可以通过discoveryClient进行查看。

kuectlde api-versions和api-resources命令输出也是通过discoveryClient实现的。另外,discoveryClient也是子啊RESTClient的基础上进行了封装。

discoveryClient除了可以发现Kubernetes API Server所支持的资源组、资源版本、资源信息,还可以将这些信息存储到本地,用于本地缓存(cache),以减轻对Kubernetes API Server访问的压力。在运行Kubernetes组件的机器上,缓存信息默认存储与/.kube/cache和/.kube/http-cache下。

demo示例:通过Dynamicclient列出Kubernetes API Server所支持的资源组、资源版本、资源信息

package main

import (
	"fmt"

	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/client-go/discovery"
	"k8s.io/client-go/tools/clientcmd"
)

/*
	@Author: ningan
	@Desc: 通过Dynamicclient列出Kubernetes API Server所支持的资源组、资源版本、资源信息
*/

func main() {
	// 1. 加载配置文件,生成config对象
	config, err := clientcmd.BuildConfigFromFlags("", "/root/.kube/config")
	if err != nil {
		panic(err.Error())
	}

	// 2. 通过kubeconfig配置信息实例化discoveryClient对象,这个对象是用于发现Kubernetes API Server所支持的资源组、资源版本、资源信息的客户端。
	discoveryClient, err := discovery.NewdiscoveryClientForConfig(config)
	if err != nil {
		panic(err.Error())
	}

	// 3. 发送请求,获取GVR数据
	_, apiResourcesList, err := discoveryClient.ServerGroupsAndResources()
	if err != nil {
		panic(err.Error())
	}
	/*
		1) ServerGroups负责获取gv数据
		2) 然后调用fetchGroupVersionResources,且给这个方法传递gv参数,通过调用ServerResourcesForGroupVersion方法获取gv对应的Resource数据,同时返回一个map[gv]resourceList的数据格式
		3) 处理map->slice,然后返回GCR slice
	*/

	/*
		Kubernetes API Server暴露出/api和/apis接口。discoveryClient通过RESTClient分别请求/api和/apis接口,从而获取Kubernetes API Server所支持的资源组、资源版本、资源信息。核心实现位于:ServerGroupsAndResources->ServerGroups中

	*/

	for _, list := range apiResourcesList {
		gv, err := schema.ParseGroupVersion(list.GroupVersion)
		if err != nil {
			panic(err.Error())
		}

		for _, resource := range list.APIResources {
			fmt.Printf("name: %v, group: %v, version: %v\n", resource.Name, gv.Group, gv.Version)
		}
	}

}

[root@master demo1]# go run main.go
name: bindings, group: , version: v1
name: componentstatuses, group: , version: v1
name: configmaps, group: , version: v1
name: endpoints, group: , version: v1
name: events, group: , version: v1
name: limitranges, group: , version: v1
name: namespaces, group: , version: v1
name: namespaces/finalize, group: , version: v1
name: namespaces/status, group: , version: v1
name: nodes, group: , version: v1
name: nodes/proxy, group: , version: v1
name: nodes/status, group: , version: v1
name: persistentvolumeclaims, group: , version: v1
name: persistentvolumeclaims/status, group: , version: v1
name: persistentvolumes, group: , version: v1
name: persistentvolumes/status, group: , version: v1
name: pods, group: , version: v1
name: pods/attach, group: , version: v1
name: pods/binding, group: , version: v1
name: pods/eviction, group: , version: v1
name: pods/exec, group: , version: v1
name: pods/log, group: , version: v1
name: pods/portforward, group: , version: v1
name: pods/proxy, group: , version: v1
name: pods/status, group: , version: v1
name: podtemplates, group: , version: v1
name: replicationcontrollers, group: , version: v1
name: replicationcontrollers/scale, group: , version: v1
name: replicationcontrollers/status, group: , version: v1
name: resourcequotas, group: , version: v1
name: resourcequotas/status, group: , version: v1
name: secrets, group: , version: v1
name: serviceaccounts, group: , version: v1
name: services, group: , version: v1
name: services/proxy, group: , version: v1
name: services/status, group: , version: v1
name: apiservices, group: apiregistration.k8s.io, version: v1
name: apiservices/status, group: apiregistration.k8s.io, version: v1
name: apiservices, group: apiregistration.k8s.io, version: v1beta1
name: apiservices/status, group: apiregistration.k8s.io, version: v1beta1
name: ingresses, group: extensions, version: v1beta1
name: ingresses/status, group: extensions, version: v1beta1
name: controllerrevisions, group: apps, version: v1
name: daemonsets, group: apps, version: v1
name: daemonsets/status, group: apps, version: v1
name: deployments, group: apps, version: v1
name: deployments/scale, group: apps, version: v1
name: deployments/status, group: apps, version: v1
name: replicasets, group: apps, version: v1
name: replicasets/scale, group: apps, version: v1
name: replicasets/status, group: apps, version: v1
name: statefulsets, group: apps, version: v1
name: statefulsets/scale, group: apps, version: v1
name: statefulsets/status, group: apps, version: v1
name: events, group: events.k8s.io, version: v1
name: events, group: events.k8s.io, version: v1beta1
name: tokenreviews, group: authentication.k8s.io, version: v1
name: tokenreviews, group: authentication.k8s.io, version: v1beta1
name: localsubjectaccessreviews, group: authorization.k8s.io, version: v1
name: selfsubjectaccessreviews, group: authorization.k8s.io, version: v1
name: selfsubjectrulesreviews, group: authorization.k8s.io, version: v1
name: subjectaccessreviews, group: authorization.k8s.io, version: v1
name: localsubjectaccessreviews, group: authorization.k8s.io, version: v1beta1
name: selfsubjectaccessreviews, group: authorization.k8s.io, version: v1beta1
name: selfsubjectrulesreviews, group: authorization.k8s.io, version: v1beta1
name: subjectaccessreviews, group: authorization.k8s.io, version: v1beta1
name: horizontalpodautoscalers, group: autoscaling, version: v1
name: horizontalpodautoscalers/status, group: autoscaling, version: v1
name: horizontalpodautoscalers, group: autoscaling, version: v2beta1
name: horizontalpodautoscalers/status, group: autoscaling, version: v2beta1
name: horizontalpodautoscalers, group: autoscaling, version: v2beta2
name: horizontalpodautoscalers/status, group: autoscaling, version: v2beta2
name: jobs, group: batch, version: v1
name: jobs/status, group: batch, version: v1
name: cronjobs, group: batch, version: v1beta1
name: cronjobs/status, group: batch, version: v1beta1
name: certificatesigningrequests, group: certificates.k8s.io, version: v1
name: certificatesigningrequests/approval, group: certificates.k8s.io, version: v1
name: certificatesigningrequests/status, group: certificates.k8s.io, version: v1
name: certificatesigningrequests, group: certificates.k8s.io, version: v1beta1
name: certificatesigningrequests/approval, group: certificates.k8s.io, version: v1beta1
name: certificatesigningrequests/status, group: certificates.k8s.io, version: v1beta1
name: ingressclasses, group: networking.k8s.io, version: v1
name: ingresses, group: networking.k8s.io, version: v1
name: ingresses/status, group: networking.k8s.io, version: v1
name: networkpolicies, group: networking.k8s.io, version: v1
name: ingressclasses, group: networking.k8s.io, version: v1beta1
name: ingresses, group: networking.k8s.io, version: v1beta1
name: ingresses/status, group: networking.k8s.io, version: v1beta1
name: poddisruptionbudgets, group: policy, version: v1beta1
name: poddisruptionbudgets/status, group: policy, version: v1beta1
name: podsecuritypolicies, group: policy, version: v1beta1
name: clusterrolebindings, group: rbac.authorization.k8s.io, version: v1
name: clusterroles, group: rbac.authorization.k8s.io, version: v1
name: rolebindings, group: rbac.authorization.k8s.io, version: v1
name: roles, group: rbac.authorization.k8s.io, version: v1
name: clusterrolebindings, group: rbac.authorization.k8s.io, version: v1beta1
name: clusterroles, group: rbac.authorization.k8s.io, version: v1beta1
name: rolebindings, group: rbac.authorization.k8s.io, version: v1beta1
name: roles, group: rbac.authorization.k8s.io, version: v1beta1
name: csidrivers, group: storage.k8s.io, version: v1
name: csinodes, group: storage.k8s.io, version: v1
name: storageclasses, group: storage.k8s.io, version: v1
name: volumeattachments, group: storage.k8s.io, version: v1
name: volumeattachments/status, group: storage.k8s.io, version: v1
name: csidrivers, group: storage.k8s.io, version: v1beta1
name: csinodes, group: storage.k8s.io, version: v1beta1
name: storageclasses, group: storage.k8s.io, version: v1beta1
name: volumeattachments, group: storage.k8s.io, version: v1beta1
name: mutatingwebhookconfigurations, group: admissionregistration.k8s.io, version: v1
name: validatingwebhookconfigurations, group: admissionregistration.k8s.io, version: v1
name: mutatingwebhookconfigurations, group: admissionregistration.k8s.io, version: v1beta1
name: validatingwebhookconfigurations, group: admissionregistration.k8s.io, version: v1beta1
name: customresourcedeFinitions, group: apiextensions.k8s.io, version: v1
name: customresourcedeFinitions/status, group: apiextensions.k8s.io, version: v1
name: customresourcedeFinitions, group: apiextensions.k8s.io, version: v1beta1
name: customresourcedeFinitions/status, group: apiextensions.k8s.io, version: v1beta1
name: priorityclasses, group: scheduling.k8s.io, version: v1
name: priorityclasses, group: scheduling.k8s.io, version: v1beta1
name: leases, group: coordination.k8s.io, version: v1
name: leases, group: coordination.k8s.io, version: v1beta1
name: runtimeclasses, group: node.k8s.io, version: v1beta1
name: endpointslices, group: discovery.k8s.io, version: v1beta1
name: cukclusters, group: dubhe.welkin, version: v1alpha1
name: cukclusters/status, group: dubhe.welkin, version: v1alpha1
name: cuknodes, group: dubhe.welkin, version: v1alpha1
name: cuknodes/status, group: dubhe.welkin, version: v1alpha1
name: cuksets, group: dubhe.welkin, version: v1alpha1
name: cuksets/status, group: dubhe.welkin, version: v1alpha1
name: nodes, group: metrics.k8s.io, version: v1beta1
name: pods, group: metrics.k8s.io, version: v1beta1

将GVR缓存到本地

可以发现,GVR数据其实是很少变动的,因此我们可以将GVR的数据缓存到本地,来减少Client与Apiserver交互。

在discovery/cached中,有另外两个客户端是来实现将GVR数据缓存到本地文件中和内存中的,分别是CacheddiscoveryClient和memCacheClient。

平时管理集群的kubectl命令也是使用这种方式来使用GVR与APIServer交互的。

discoveryClient除了可以发现Kubernetes API Server所支持的资源组、资源版本、资源信息,还可以将这些信息存储到本地,用于本地缓存(cache),以减轻对Kubernetes API Server访问的压力。在运行Kubernetes组件的机器上,缓存信息默认存储与/.kube/cache和/.kube/http-cache下。

package main

import (
	"fmt"
	"time"

	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/client-go/discovery/cached/disk"
	"k8s.io/client-go/tools/clientcmd"
)

/*
	@Author: ningan
	@Desc: 将GVR数据缓存到本地
*/

func main() {
	// 1. 加载配置文件,生成config对象
	config, err := clientcmd.BuildConfigFromFlags("", "/root/.kube/config")
	if err != nil {
		panic(err.Error())
	}

	// 2. 实例化客户端,本客户端负责将GVR数据缓存到本地文件中
	cacheddiscoveryClient, err := disk.NewCacheddiscoveryClientForConfig(config, "./cache/discovery", "./cache/http", time.Minute*60)
	if err != nil {
		panic(err.Error())
	}

	_, apiResourcesList, err := cacheddiscoveryClient.ServerGroupsAndResources()
	if err != nil {
		panic(err.Error())
	}

	/*
		1) 先从缓存文件中找GVR数据,有则直接返回,没有则调用APIServer
		2) 嗲用APIServer获取GVR数据
		3) 将获取到的GVR数据缓存到本地,然后返回给客户端

	*/

	for _, list := range apiResourcesList {
		gv, err := schema.ParseGroupVersion(list.GroupVersion)
		if err != nil {
			panic(err.Error())
		}

		for _, resource := range list.APIResources {
			fmt.Printf("name: %v, group: %v, version: %v\n", resource.Name, gv.Group, gv.Version)
		}
	}
}

执行go run main.go之后,确实生成了cache目录

[root@master demo2]# tree -L 2
.
├── cache
│   ├── discovery
│   └── http
└── main.go

3 directories, 1 file

参考

Kubernetes源码剖析 5.2节 Client客户端对象

b站视频:Client-go实战教程

.net学习笔记之 AJAX学习

.net学习笔记之 AJAX学习

总结

以上是小编为你收集整理的.net学习笔记之 AJAX学习全部内容。

如果觉得小编网站内容还不错,欢迎将小编网站推荐给好友。

.NET开发人员关于ML.NET的入门学习

.NET开发人员关于ML.NET的入门学习

ML.NET一直在微软的研究部门的工作。这些创新已经用于他们自己的产品,如Windows Defender,Microsoft Office(Powerpoint设计理念,Excel图表推荐),Azure机器学习,PowerBI。 ML.NET旨在提供终端工作流程,以便在机器学习(预处理,特征工程,建模,评估和操作)的各个步骤中将ML用于.NET应用程序。

ML.NET 1.0提供以下关键组件:数据表示机器学习任务(分类,回归,异常检测等)数据特征工程

机器学习模型应该让分析师的生活更轻松,现在甚至可以构建这些模型,因为新框架的设计考虑了AutoML。除了通常的机器学习任务外,ML.NET还支持AutoML。

对于机器学习初学者,Microsoft开发人员建议从Visual Studio中的ML.NET模型构建器和任何平台上的ML.NET CLI开始。对于可以随时构建模型的场景,AutoML API也非常方便。

使用ML.NET模型构建器,只需右键单击即可向应用程序添加机器学习。

在命令行使用ML.NET

还引入了另一个工具ML.NET CLI(命令行工具),它允许使用AutoML和ML.NET生成ML.NET模型。ML.NET CLI快速遍历特定ML任务的数据集(目前支持回归和分类)并生成最佳模型。

CLI除了生成最佳模型外,还允许用户为最佳性能模型生成模型训练和 消费模型代码。

ML.NET CLI是跨平台的,是.NET CLI 的全局工具。Visual Studio扩展ML.NET Model Builder 还使用ML.NET CLI提供模型构建器功能。

安装ML.NET CLI:

dotnet tool install -g mlnet 

这是使用回归预测出租车票价的代码

加载数据集

IDataView trainingDataView = mlContext.Data.LoadFromTextFile(TrainDataPath, hasHeader: true); 
IDataView testDataView = mlContext.Data.LoadFromTextFile(TestDataPath, hasHeader: true); 

运行AutoML二进制分类

ExperimentResult experimentResult = mlContext.Auto().CreateRegressionExperiment(ExperimentTime).Execute(trainingDataView, LabelColumnName, progressHandler: new RegressionExperimentProgressHandler());

模型评估

ITransformer model = experimentResult.BestRun.Model; 

并使用测试数据集评估其质量(taxi-fare-test.csv)。

Regression.Evaluate() 计算已知票价与模型预测值之间的差异,以生成各种指标。

var predictions = trainedModel.Transform(testDataView); 
var metrics = mlContext.Regression.Evaluate(predictions,scoreColumnName:“Score”);

创建预测引擎

var predEngine = mlContext.Model.CreatePredictionEngine<TaxiTrip, TaxiTripFarePrediction>(model);

计算分数

var predictedResult = predEngine.Predict(taxiTripSample); 

上面是使用Visual Studio内部的模型构建器以及CLI命令测试AutoML,还有一个API可以在.Net应用程序中使用它,使用非常简单,添加[ Microsoft.ML.AutoML ] nuget包到项目中就可以使用API 进行工作

ML.Net示例仓库中有一整套示例。可以重用了Common文件夹中的一些类来通过API使用AutoML 。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

您可能感兴趣的文章:
  • win7-vs2012下安装.net frame work 的过程图文详解
  • .NET Core Dapper操作mysql数据库的实现方法
  • 打造自己的.NET Core项目模板
  • 浅谈从ASP.NET Core2.2到3.0你可能会遇到这些问题
  • ASP.NET Core MVC/WebApi基础系列2
  • ASP.NET Core MVC/WebApi基础系列1

Android多媒体学习

Android多媒体学习

一、Image的获取可以通过调Android自带的Camera应用来完成。该应用含有一个Intent-Filter。通过使用
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);startActivityForResult(intent)就可以启动Camera应用了。
二、Image存储,Android系统中含有一个多媒体库,其中包括所有Image、Video、Audio的数据。通过MediaStore对象可以访问相关数据。
闲话少说,直接看例子,这是一本英文书上的,觉得写的很好,自己翻译了一下,并加入了很多注释。以备查询。

 package demo.camera;  
import java.io.File;  
import android.app.Activity;  
import android.content.ContentValues;  
import android.content.Intent;  
import android.graphics.Bitmap;  
import android.graphics.BitmapFactory;  
import android.net.Uri;  
import android.os.Bundle;  
import android.os.Environment;  
import android.provider.MediaStore;  
import android.util.Log;  
import android.view.Display;  
import android.view.View;  
import android.widget.Button;  
import android.widget.ImageView;  
/** 
 * 这里多媒体第一个示例,主要介绍Image的获取和存储 
 * Image的获取可以通过Android自带的Camera应用来获得, 
 * 图片的存储需要用到MediaStore对象。Android中的多媒体库。 
 *  
 * @author Administrator 
 * 
 */  
public class MainActivity extends Activity {  
      
    private static final int RESULT_CODE = 1;  
    private Button btnCamera;  
    private ImageView imageView;  
      
    private Uri imageFilePath;  
      
    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.main);  
          
          
        imageView = (ImageView)this.findViewById(R.id.imageView);  
        btnCamera = (Button)this.findViewById(R.id.camera);  
        btnCamera.setOnClickListener(new View.OnClickListener() {  
              
            @Override  
            public void onClick(View v) {  
                  
                  
                /** 
                 * 由于Camara返回的是缩略图,我们可以传递给他一个参数EXTRA_OUTPUT, 
                 * 来将用Camera获取到的图片存储在一个指定的URI位置处。 
                 * 下面就指定image存储在SDCard上,并且文件名为123.jpg 
                 * imageFilePath = Environment.getExternalStorageDirectory().getAbsolutePath()+"123.jpg"; 
                 * File file = new File(imageFilePath); //创建一个文件 
                 * Uri imageUri = Uri.fromFile(file); 
                 * 然而Android已经提供了一个多媒体库,那里统一存放了设备上所有的多媒体数据。所以, 
                 * 我们可以将获取到的图片存放在那个多媒体库中。 
                 * Android提供了MediaStore类,该类是一个ContentProvider,管理着设备上自带的和外部的多媒体文件, 
                 * 同时包含着每一个多媒体文件的数据信息。 
                 * 为了将数据存储在多媒体库,使用ContentResolver对象来操纵MediaStore对象 
                 * 在MediaStore.Images.Media中有两个URI常量,一个是    EXTERNAL_CONTENT_URI,另一个是INTERNAL_CONTENT_URI 
                 * 第一个URI对应着外部设备(SDCard),第二个URI对应着系统设备内部存储位置。 
                 * 对于多媒体文件,一般比较大,我们选择外部存储方式 
                 * 通过使用ContentResolver对象的insert方法我们可以向MediaStore中插入一条数据 
                 * 这样在检索那张图片的时候,不再使用文件的路径,而是根据insert数据时返回的URI,获取一个InputStream 
                 * 并传给BitmapFactory 
                 */  
                //在这里启动Camera。 
  
                //Camera中定义了一个Intent-Filter,其中Action是android.media.action.IMAGE_CAPTURE 
  
                //我们使用的时候,最好不要直接使用这个,而是用MediaStore中的常量ACTION_IMAGE_CAPTURE. 
  
                //这个常量就是对应的上面的action   
                Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);  
              
                //这里我们插入一条数据,ContentValues是我们希望这条记录被创建时包含的数据信息 
  
                //这些数据的名称已经作为常量在MediaStore.Images.Media中,有的存储在MediaStore.MediaColumn中了 
  
                //ContentValues values = new ContentValues(); 
  
                ContentValues values = new ContentValues(3);  
                values.put(MediaStore.Images.Media.DISPLAY_NAME, "testing");  
                values.put(MediaStore.Images.Media.DESCRIPTION, "this is description");  
                values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");  
                imageFilePath = MainActivity.this.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);  
                intent.putExtra(MediaStore.EXTRA_OUTPUT, imageFilePath); //这样就将文件的存储方式和uri指定到了Camera应用中   
                  
                //由于我们需要调用完Camera后,可以返回Camera获取到的图片, 
  
                //所以,我们使用startActivityForResult来启动Camera                     
  
                startActivityForResult(intent, RESULT_CODE);  
                  
            }  
        });  
    }  
    /** 
     * 为了获取Camera返回的图片信息,重写该方法。 
     */  
    @Override  
    public void onActivityResult(int requestCode, int resultCode, Intent data){  
        super.onActivityResult(requestCode, resultCode, data);  
        if(resultCode == RESULT_CODE){  
            //说明是由Camera返回的数据 
  
            //由Camera应用返回的图片数据是一个Camera对象,存储在一个名为data的extra域 
  
            //然后将获取到的图片存储显示在ImageView中 
  
              
            try {  
                Bundle extra = data.getExtras();  
                /** 
                 * 然而为了节约内存的消耗,这里返回的图片是一个121*162的缩略图。 
                 * 那么如何返回我们需要的大图呢?看上面 
                 * 然而存储了图片。有了图片的存储位置,能不能直接将图片显示出来呢》 
                 * 这个问题就设计到对于图片的处理和显示,是非常消耗内存的,对于PC来说可能不算什么,但是对于手机来说 
                 * 很可能使你的应用因为内存耗尽而死亡。不过还好,Android为我们考虑到了这一点 
                 * Android中可以使用BitmapFactory类和他的一个内部类BitmapFactory.Options来实现图片的处理和显示 
                 * BitmapFactory是一个工具类,里面包含了很多种获取Bitmap的方法。BitmapFactory.Options类中有一个inSampleSize,比如设定他的值为8,则加载到内存中的图片的大小将 
                 * 是原图片的1/8大小。这样就远远降低了内存的消耗。 
                 * BitmapFactory.Options op = new BitmapFactory.Options(); 
                 * op.inSampleSize = 8; 
                 * Bitmap pic = BitmapFactory.decodeFile(imageFilePath, op); 
                 * 这是一种快捷的方式来加载一张大图,因为他不用考虑整个显示屏幕的大小和图片的原始大小 
                 * 然而有时候,我需要根据我们的屏幕来做相应的缩放,如何操作呢? 
                 *  
                 */  
                //首先取得屏幕对象 
  
                Display display = this.getWindowManager().getDefaultDisplay();  
                //获取屏幕的宽和高 
  
                int dw = display.getWidth();  
                int dh = display.getHeight();  
                /** 
                 * 为了计算缩放的比例,我们需要获取整个图片的尺寸,而不是图片 
                 * BitmapFactory.Options类中有一个布尔型变量inJustDecodeBounds,将其设置为true 
                 * 这样,我们获取到的就是图片的尺寸,而不用加载图片了。 
                 * 当我们设置这个值的时候,我们接着就可以从BitmapFactory.Options的outWidth和outHeight中获取到值 
                 */  
                BitmapFactory.Options op = new BitmapFactory.Options();  
                //op.inSampleSize = 8; 
  
                op.inJustDecodeBounds = true;  
                //Bitmap pic = BitmapFactory.decodeFile(imageFilePath, op);//调用这个方法以后,op中的outWidth和outHeight就有值了 
  
                //由于使用了MediaStore存储,这里根据URI获取输入流的形式 
  
                Bitmap pic = BitmapFactory.decodeStream(this  
                        .getContentResolver().openInputStream(imageFilePath),  
                        null, op);  
                int wRatio = (int) Math.ceil(op.outWidth / (float) dw); //计算宽度比例 
  
                int hRatio = (int) Math.ceil(op.outHeight / (float) dh); //计算高度比例 
  
                Log.v("Width Ratio:", wRatio + "");  
                Log.v("Height Ratio:", hRatio + "");  
                /** 
                 * 接下来,我们就需要判断是否需要缩放以及到底对宽还是高进行缩放。 
                 * 如果高和宽不是全都超出了屏幕,那么无需缩放。 
                 * 如果高和宽都超出了屏幕大小,则如何选择缩放呢》 
                 * 这需要判断wRatio和hRatio的大小 
                 * 大的一个将被缩放,因为缩放大的时,小的应该自动进行同比率缩放。 
                 * 缩放使用的还是inSampleSize变量 
                 */  
                if (wRatio > 1 && hRatio > 1) {  
                    if (wRatio > hRatio) {  
                        op.inSampleSize = wRatio;  
                    } else {  
                        op.inSampleSize = hRatio;  
                    }  
                }  
                op.inJustDecodeBounds = false; //注意这里,一定要设置为false,因为上面我们将其设置为true来获取图片尺寸了 
  
                pic = BitmapFactory.decodeStream(this.getContentResolver()  
                        .openInputStream(imageFilePath), null, op);  
                imageView.setImageBitmap(pic);  
            } catch (Exception e) {  
                e.printStackTrace();  
            }   
        }  
    }  
}

检索并显示媒体库中的图片

如果你在模拟器已经启动的情况下,push了几张图片到SDCard中,建议将模拟器关了,再重新启动一下,否则,刚刚添加的图片,是没有办法获取到的。这是因为Android是在系统启动的时候来扫描模拟器上SDCard中多媒体文件的。

 package demo.camera;  
import android.app.Activity;  
import android.database.Cursor;  
import android.graphics.Bitmap;  
import android.graphics.BitmapFactory;  
import android.os.Bundle;  
import android.provider.MediaStore.Images.Media;  
import android.util.Log;  
import android.view.View;  
import android.widget.ImageButton;  
import android.widget.TextView;  
/** 
 * 该类完成图片的检索,显示功能 
 * @author Administrator 
 * 
 */  
public class PhotoManager extends Activity {  
      
    public static final float DISPLAY_WIDTH = 200;  
    public static final float DISPLAY_HEIGHT = 200;  
      
    //这里采用ImageButton的原因是有Button的作用 
  
    private ImageButton photoView;  
    private TextView nameView;  
      
    private Cursor cursor;  
      
    private String photoPath; //存放某张图片对应的位置信息   
    private Bitmap currPhoto;  
      
    //这三个变量主要用来保存Media.DATA,Media.TITLE,Media.DISPLAY_NAME的索引号,来获取每列的数据 
  
    private int photoIndex;  
    //private int titleIndex; 
  
    private int nameIndex;  
      
    public void onCreate(Bundle savedInstanceState){  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.photo_view);  
          
        photoView = (ImageButton)this.findViewById(R.id.image_view);  
        photoView.setOnClickListener(clickListener);  
        nameView = (TextView)this.findViewById(R.id.view_name);  
          
        //指定获取的列 
  
        String columns[] = new String[]{  
                Media.DATA,Media._ID,Media.TITLE,Media.DISPLAY_NAME  
        };  
        //cursor = this.managedQuery(Media.EXTERNAL_CONTENT_URI, columns, null, null, null); 
  
        cursor = this.getContentResolver().query(Media.EXTERNAL_CONTENT_URI, columns, null, null, null);  
        photoIndex = cursor.getColumnIndexOrThrow(Media.DATA);  
        //titleIndex = cursor.getColumnIndexOrThrow(Media.TITLE); 
  
        nameIndex = cursor.getColumnIndexOrThrow(Media.DISPLAY_NAME);  
          
        Log.v("HERE First:", "First Debug");  
        //显示第一张图片,但是首先要判断一下,Cursor是否有值   
        if(cursor.moveToFirst()){  
            showImage();  
        }  
    }  
      
    private View.OnClickListener clickListener = new View.OnClickListener() {  
          
        @Override  
        public void onClick(View v) {  
              
            if(cursor.moveToNext()){  
                showImage();  
            }  
        }  
    };  
      
    /** 
     * 显示图像信息 
     */  
    private void showImage(){  
        photoPath = cursor.getString(photoIndex); //这里获取到的就是图片存储的位置信息   
        //这里怎样获取图片呢?看decodeBitmap 
  
        Log.v("Photo Path:", photoPath);  
        currPhoto = decodeBitmap(photoPath);  
        photoView.setImageBitmap(currPhoto);  
        nameView.setText(cursor.getString(nameIndex));        
    }  
      
    /** 
     * 从path中获取图片信息 
     * @param path 
     * @return 
     */  
    private Bitmap decodeBitmap(String path){  
        BitmapFactory.Options op = new BitmapFactory.Options();  
        op.inJustDecodeBounds = true;  
        Bitmap bmp = BitmapFactory.decodeFile(path, op); //获取尺寸信息   
        //获取比例大小 
  
        int wRatio = (int)Math.ceil(op.outWidth/DISPLAY_WIDTH);  
        int hRatio = (int)Math.ceil(op.outHeight/DISPLAY_HEIGHT);  
        //如果超出指定大小,则缩小相应的比例 
  
        if(wRatio > 1 && hRatio > 1){  
            if(wRatio > hRatio){  
                op.inSampleSize = wRatio;  
            }else{  
                op.inSampleSize = hRatio;  
            }  
        }  
        op.inJustDecodeBounds = false;  
        bmp = BitmapFactory.decodeFile(path, op);  
        return bmp;  
    }  
      
}

Android自带的Camera应用虽然可以满足大多数情景,但是其灵活性上还有不足。但是Android允许我们定制自己的Camera。

在Android的hardware包中有一个Camera类。这个类就是获取Camera服务的,可以定制Camera等。

可以通过open()方法获取其实例。在使用这个类是需要在AndroidManifest.xml文件中加入相应的权限和特性 

如:  <uses-permission android:name = "android.permission.CAMERA" />
  <uses-feature android:name = "android.hardware.camera" />
  <uses-feature android:name = "android.hardware.camera.autofocus" /> 等。

package demo.camera;  
import java.io.OutputStream;  
import java.util.Iterator;  
import java.util.List;  
import android.app.Activity;  
import android.content.ContentValues;  
import android.content.res.Configuration;  
import android.hardware.Camera;  
import android.net.Uri;  
import android.os.Bundle;  
import android.provider.MediaStore;  
import android.view.SurfaceHolder;  
import android.view.SurfaceView;  
import android.view.View;  
import android.widget.LinearLayout;  
/** 
 * Android自带的Camera应用程序可以完成很多功能。但是当其不能满足我们需要的时候 
 * 我们可以定制自己的Camera。Android提供了Camera类来辅助我们实现自己的Camera。 
 * 这个例子就来定义一个自己的Camera 
 * 首先,在Manifest中需要引入权限<uses-permission android:name="android:permission.CAMERA"/> 
 * 我们需要用来存放取景器的容器,这个容器就是SurfaceView。 
 * 使用SurfaceView的同时,我们还需要使用到SurfaceHolder,SurfaceHolder相当于一个监听器,可以监听 
 * Surface上的变化,通过其内部类CallBack来实现。 
 * 为了可以获取图片,我们需要使用Camera的takePicture方法同时我们需要实现Camera.PictureCallBack类,实现onPictureTaken方法 
 * @author Administrator 
 * 
 */  
public class MyCamera extends Activity implements SurfaceHolder.Callback,Camera.PictureCallback{  
      
    public static final int MAX_WIDTH = 200;  
    public static final int MAX_HEIGHT = 200;  
      
    private SurfaceView surfaceView;  
      
    private Camera camera; //这个是hardare的Camera对象   
      
    public void onCreate(Bundle savedInstanceState){  
        super.onCreate(savedInstanceState);  
        this.setContentView(R.layout.camera);  
        surfaceView = (SurfaceView)this.findViewById(R.id.myCameraView);  
        surfaceView.setFocusable(true);   
        surfaceView.setFocusableInTouchMode(true);  
        surfaceView.setClickable(true);  
        surfaceView.setOnClickListener(new View.OnClickListener() {  
              
            @Override  
            public void onClick(View v) {  
                  
                camera.takePicture(null, null, null, MyCamera.this);  
                  
            }  
        });  
        //SurfaceView中的getHolder方法可以获取到一个SurfaceHolder实例 
  
        SurfaceHolder holder = surfaceView.getHolder();  
        //为了实现照片预览功能,需要将SurfaceHolder的类型设置为PUSH 
  
        //这样,画图缓存就由Camera类来管理,画图缓存是独立于Surface的 
  
        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);  
        holder.addCallback(this);  
    }  
    @Override  
    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {  
    }  
    @Override  
    public void surfaceCreated(SurfaceHolder holder) {  
        // 当Surface被创建的时候,该方法被调用,可以在这里实例化Camera对象 
  
        //同时可以对Camera进行定制 
  
        camera = Camera.open(); //获取Camera实例   
      
          
        /** 
         * Camera对象中含有一个内部类Camera.Parameters.该类可以对Camera的特性进行定制 
         * 在Parameters中设置完成后,需要调用Camera.setParameters()方法,相应的设置才会生效 
         * 由于不同的设备,Camera的特性是不同的,所以在设置时,需要首先判断设备对应的特性,再加以设置 
         * 比如在调用setEffects之前最好先调用getSupportedColorEffects。如果设备不支持颜色特性,那么该方法将 
         * 返回一个null 
         */  
        try {  
              
            Camera.Parameters param = camera.getParameters();  
            if(this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE){  
                //如果是竖屏 
  
                param.set("orientation", "portrait");  
                //在2.2以上可以使用 
  
                //camera.setDisplayOrientation(90); 
  
            }else{  
                param.set("orientation", "landscape");  
                //在2.2以上可以使用 
  
                //camera.setDisplayOrientation(0);               
  
            }  
            //首先获取系统设备支持的所有颜色特效,有复合我们的,则设置;否则不设置 
  
            List<String> colorEffects = param.getSupportedColorEffects();  
            Iterator<String> colorItor = colorEffects.iterator();  
            while(colorItor.hasNext()){  
                String currColor = colorItor.next();  
                if(currColor.equals(Camera.Parameters.EFFECT_SOLARIZE)){  
                    param.setColorEffect(Camera.Parameters.EFFECT_SOLARIZE);  
                    break;  
                }  
            }  
            //设置完成需要再次调用setParameter方法才能生效 
  
            camera.setParameters(param);  
              
            camera.setPreviewDisplay(holder);  
              
            /** 
             * 在显示了预览后,我们有时候希望限制预览的Size 
             * 我们并不是自己指定一个SIze而是指定一个Size,然后 
             * 获取系统支持的SIZE,然后选择一个比指定SIZE小且最接近所指定SIZE的一个 
             * Camera.Size对象就是该SIZE。 
             *  
             */  
            int bestWidth = 0;  
            int bestHeight = 0;  
              
            List<Camera.Size> sizeList = param.getSupportedPreviewSizes();  
            //如果sizeList只有一个我们也没有必要做什么了,因为就他一个别无选择 
  
            if(sizeList.size() > 1){  
                Iterator<Camera.Size> itor = sizeList.iterator();  
                while(itor.hasNext()){  
                    Camera.Size cur = itor.next();  
                    if(cur.width > bestWidth && cur.height>bestHeight && cur.width <MAX_WIDTH && cur.height < MAX_HEIGHT){  
                        bestWidth = cur.width;  
                        bestHeight = cur.height;  
                    }  
                }  
                if(bestWidth != 0 && bestHeight != 0){  
                    param.setPreviewSize(bestWidth, bestHeight);  
                    //这里改变了SIze后,我们还要告诉SurfaceView,否则,Surface将不会改变大小,进入Camera的图像将质量很差 
  
                    surfaceView.setLayoutParams(new LinearLayout.LayoutParams(bestWidth, bestHeight));  
                }  
            }  
            camera.setParameters(param);  
        } catch (Exception e) {  
            // 如果出现异常,则释放Camera对象 
  
            camera.release();  
        }  
          
        //启动预览功能 
  
        camera.startPreview();  
          
    }  
    @Override  
    public void surfaceDestroyed(SurfaceHolder holder) {  
        // 当Surface被销毁的时候,该方法被调用 
  
        //在这里需要释放Camera资源 
  
        camera.stopPreview();  
        camera.release();  
          
    }  
    @Override  
    public void onPictureTaken(byte[] data, Camera camera) {  
        // data是一个原始的JPEG图像数据, 
  
        //在这里我们可以存储图片,很显然可以采用MediaStore   
        //注意保存图片后,再次调用startPreview()回到预览 
  
        Uri imageUri = this.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new ContentValues());  
        try {  
            OutputStream os = this.getContentResolver().openOutputStream(imageUri);  
            os.write(data);  
            os.flush();  
            os.close();  
        } catch (Exception e) {  
            // TODO: handle exception 
  
            e.printStackTrace();  
        }  
          
        camera.startPreview();  
    }  
      
      
      
}

图像的编辑和合成

package demo.camera;  
import java.io.FileNotFoundException;  
import android.app.Activity;  
import android.content.Intent;  
import android.graphics.Bitmap;  
import android.graphics.BitmapFactory;  
import android.graphics.Canvas;  
import android.graphics.ColorMatrix;  
import android.graphics.ColorMatrixColorFilter;  
import android.graphics.Matrix;  
import android.graphics.Paint;  
import android.graphics.PorterDuff;  
import android.graphics.PorterDuffXfermode;  
import android.net.Uri;  
import android.os.Bundle;  
import android.provider.MediaStore;  
import android.util.Log;  
import android.view.Menu;  
import android.view.MenuItem;  
import android.view.View;  
import android.widget.Button;  
import android.widget.ImageView;  
/** 
 * 在Android中我们可以对图像进行编辑处理等操作 
 * 包括放大缩小,旋转,偏移,裁剪,以及更改亮度,饱和度等 
 *  
 * 1、首先,从SDCard中选择图片,采用Android自带的Callery应用获得 
 * Gallery是Android自带的图片和视频管理应用 
 * 使用Intent来启动Gallery应用,需要指定两个参数,一个是Action,另一个是多媒体存放的URI 
 * Action是一个通用的Action叫ACTION_PICK,来告诉Gallery,我们想检索数据。 
 * 第二个是Data,是一个URI,这里当然是MediaStore.Images.Media.EXTERNAL_CONTENT_URI 
 * 当在Gallery中选择了一个图片的时候,返回的Intent中的Data域就是所选图片对应的URI 
 *  
 * @author Administrator 
 * 
 */  
public class PhotoProcess extends Activity{  
    public static final int FIRST_PIC = 0;  
    public static final int SECOND_PIC = 1;  
    public static final int MAX_WIDTH = 240;  
    public static final int MAX_HEIGHT = 180;  
    private Button btnSelect,btnSelect2;  
    private ImageView srcImageView, dstImageView;  
      
    private Bitmap srcBitmap, dstBitmap;  
    private Uri imageUri;  
      
      
    public void onCreate(Bundle savedInstanceState){  
        super.onCreate(savedInstanceState);  
        this.setContentView(R.layout.process);  
          
        this.btnSelect = (Button)this.findViewById(R.id.btn_select);  
        btnSelect.setOnClickListener(clickListener);  
        this.btnSelect2 = (Button)this.findViewById(R.id.btn_select2);  
        btnSelect2.setOnClickListener(clickListener2);  
        srcImageView = (ImageView)this.findViewById(R.id.img_src);  
        dstImageView = (ImageView)this.findViewById(R.id.img_dst);  
    }  
      
    private View.OnClickListener clickListener = new View.OnClickListener() {  
          
        @Override  
        public void onClick(View arg0) {  
            // 启动Gallery应用 
  
            Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);  
            startActivityForResult(intent, FIRST_PIC);  
        }  
    };  
    private View.OnClickListener clickListener2 = new View.OnClickListener() {  
          
        @Override  
        public void onClick(View arg0) {  
            // 启动Gallery应用 
  
            Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);  
            startActivityForResult(intent, SECOND_PIC);  
              
        }  
    };    
      
    public boolean onCreateOptionsMenu(Menu menu){  
        //super.onCreateOptionsMenu(menu); 
  
        //MenuInflater menuInflater = new MenuInflater(this); 
  
        //menuInflater.inflate(R.layout.image, menu) 
  
        menu.add(Menu.NONE,1,Menu.NONE,"复制");  
        menu.add(Menu.NONE,2,Menu.NONE,"变换");  
        menu.add(Menu.NONE,3,Menu.NONE,"亮度");  
        menu.add(Menu.NONE,4,Menu.NONE,"合成");  
        return super.onCreateOptionsMenu(menu);  
    }  
      
    public boolean onOptionsItemSelected(MenuItem item){  
        int id = item.getItemId();  
        switch(id){  
        case 1:  
            //复制一个图像 
  
            if(srcBitmap != null){  
                dstBitmap = getDstImage(null);//这里没有变换 
  
                dstImageView.setImageBitmap(dstBitmap);  
            }  
            break;  
        case 2:  
            //对复制后的图像进行变换 
  
            if(srcBitmap != null){  
                dstBitmap = transferImage();  
                dstImageView.setImageBitmap(dstBitmap);  
            }  
            break;  
        case 3:  
            //改变图像的色彩 
  
            if(srcBitmap != null){  
                dstBitmap = ajustImage();  
                dstImageView.setImageBitmap(dstBitmap);  
            }  
            break;  
        case 4:  
            if(srcBitmap != null && dstBitmap != null){  
                dstBitmap = compositeImages();  
                dstImageView.setImageBitmap(dstBitmap);  
            }  
            break;  
        }  
        return true;  
    }  
      
    /** 
     * 为了创建一个图像的副本,我们可以在创建一个新的空的Bitmap,然后在这个Bitmap上绘制一个Bitmap 
     * 这个空的Bitmap应该和已存在的Bitmap具有相同的尺寸和颜色深度 
     *  
     * 然后我们需要一个Canvas对象,一个Canvas简单说,就是一个画布,存放Bitmap,在构造时,就可以传入Bitmap对象 
     * 同时,Canvas中定义了很多便捷的画图方法,方便我们绘制各种图形 
     * 接下来,如果我们需要处理颜色和对比度,我们需要一个Paint对象,通过Paint我们可以设置画笔的各种特性。 
     *  
     * 最后,我们调用Canvas的drawBitmap就可以将原Bitmap绘制在dstBitmap上了 
     *  
     */  
    private Bitmap getDstImage(Matrix matrix){  
          
        Bitmap bmp = null;  
        //下面这个Bitmap中创建的函数就可以创建一个空的Bitmap 
  
        //返回的是一个可以改变的Bitmap对象,这样我们后面就可以对其进行变换和颜色调整等操作了 
  
        bmp = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), srcBitmap.getConfig());  
        //创建Canvas对象, 
  
        Canvas canvas = new Canvas(bmp);   
        //创建Paint对象,这里先不用 
  
        Paint paint = new Paint();  
        //在Canvas上绘制一个已经存在的Bitmap。这样,dstBitmap就和srcBitmap一摸一样了 
  
          
        if(matrix != null){  
            //如果matrix存在,则采用变换 
  
            canvas.drawBitmap(dstBitmap, matrix, paint);  
        }else{  
            canvas.drawBitmap(srcBitmap, 0, 0, paint);  
        }  
          
          
        return bmp;  
  
    }  
      
      
    /** 
     * 重载getDstImage函数,传入定制的Paint对象 
     * @param matrix 
     * @param paint 
     * @return 
     */  
    private Bitmap getDstImage(Matrix matrix, Paint paint){  
          
        Bitmap bmp = null;  
        //下面这个Bitmap中创建的函数就可以创建一个空的Bitmap 
  
        //返回的是一个可以改变的Bitmap对象,这样我们后面就可以对其进行变换和颜色调整等操作了 
  
        bmp = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), srcBitmap.getConfig());  
        //创建Canvas对象, 
  
        Canvas canvas = new Canvas(bmp);   
          
        //在Canvas上绘制一个已经存在的Bitmap。这样,dstBitmap就和srcBitmap一摸一样了 
  
          
        if(matrix != null){  
            //如果matrix存在,则采用变换 
  
            canvas.drawBitmap(dstBitmap, matrix, paint);  
        }else{  
            canvas.drawBitmap(srcBitmap, 0, 0, paint);  
        }  
          
          
        return bmp;  
  
    }     
      
    /** 
     * 为了放大缩小、旋转图像,我们要使用Matrix类。Matrix类是一个三维矩阵。 
     * 在Android屏幕中,图像的每个像素对应都是一个坐标,一个坐标由x/y/z组成 
     * ------------------------ 
     * cosX -sinX translateX 
     * sinX cosX  translateY 
     * 0    0     scale 
     * ------------------------ 
     * 第一行的值,影响着x坐标。比如 1 0 0 =>x = 1*x + 0*y + 0*z 
     * 第二行的值,影响着y坐标。比如0 1 0 => y = 0*x + 1*y + 0*z 
     * 第三行的值,影响着z坐标。比如 0 0 1 => z = 0*x + 0*y + 1*z 
     *  
     * 我们自己计算一个矩阵然后通过Matrax.setValues设置。 
     * 这样,在调用canvas的drawBitmap方法时,传入matrix 
     *  
     * Matrix类并不提倡我们使用这种方式来操作变换,Matrix针对不同的变换都相应的有pre,set,post三种方法 
     * 可以使用。 
     * pre是矩阵前乘 
     * set是直接设置 
     * post是矩阵后乘 
     */  
    private Bitmap transferImage(){  
        Matrix matrix = new Matrix();  
        matrix.setValues(new float[]{  
            .5f,0,0,//这里只会影响到x轴,所以,图片的长度将是原来的一半   
            0,1,0,  
            0,0,1  
        });  
        return this.getDstImage(matrix);  
    }  
      
    /** 
     * 该方法中我们将对图像的颜色,亮度,对比度等进行设置 
     * 需要用到ColorMatrix类。ColorMatrix类是一个四行五列的矩阵 
     * 每一行影响着[R,G,B,A]中的一个 
     * ------------------------- 
     * a1 b1 c1 d1 e1 
     * a2 b2 c2 d2 e2 
     * a3 b3 c3 d3 e3 
     * a4 b4 c4 d4 e4 
     * ------------------------- 
     * Rnew => a1*R+b1*G+c1*B+d1*A+e1 
     * Gnew => a2*R+b2*G+c2*B+d2*A+e2 
     * Bnew => a3*R+b3*G+c3*B+d3*A+e3 
     * Gnew => a4*R+b4*G+c4*B+d4*A+e4 
     * 其中R,G,B的值是128,A的值是0 
     *  
     * 最后将颜色的修改,通过Paint.setColorFilter应用到Paint对象中。 
     * 主要对于ColorMatrix,需要将其包装成ColorMatrixColorFilter对象,再传给Paint对象 
     *  
     * 同样的,ColorMatrix提供给我们相应的方法,setSaturation()就可以设置一个饱和度 
     */  
    private Bitmap ajustImage(){  
        ColorMatrix cMatrix = new ColorMatrix();  
//      int brightIndex = -25; 
  
//      int doubleColor = 2; 
  
//      cMatrix.set(new float[]{ 
  
//              doubleColor,0,0,0,brightIndex, //这里将1改为2则我们让Red的值为原来的两倍 
  
//              0,doubleColor,0,0,brightIndex,//改变最后一列的值,我们可以不改变RGB同道颜色的基础上,改变亮度 
  
//              0,0,doubleColor,0,brightIndex, 
  
//              0,0,0,doubleColor,0 
  
//      }); 
  
        //cMatrix.setSaturation(2.0f);//设置饱和度 
  
        cMatrix.setScale(2.0f, 2.0f, 2.0f, 2.0f);//设置颜色同道色彩缩放 
  
        Paint paint = new Paint();  
        paint.setColorFilter(new ColorMatrixColorFilter(cMatrix));  
        return this.getDstImage(null, paint);  
    }  
      
    /** 
     * 图像的合成,可以通过在同一个Canvas中绘制两张图片。 
     * 只是在绘制第二章图片的时候,需要给Paint指定一个变幻模式TransferMode。 
     * 在Android中有一个XFermode所有的变幻模式都是这个类的子类 
     * 我们需要用到它的一个子类PorterDuffXfermode,关于这个类,其中用到PorterDuff类 
     * 这个类很简单,就包含一个Enum是Mode,其中定义了一组规则,这组规则就是如何将 
     * 一张图像和另一种图像进行合成 
     * 关于图像合成有四种模式,LIGHTEN,DRAKEN,MULTIPLY,SCREEN 
     */  
    private Bitmap compositeImages(){  
          
        Bitmap bmp = null;  
        //下面这个Bitmap中创建的函数就可以创建一个空的Bitmap 
  
        bmp = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), srcBitmap.getConfig());  
        Paint paint = new Paint();  
        Canvas canvas = new Canvas(bmp);  
        //首先绘制第一张图片,很简单,就是和方法中getDstImage一样 
  
        canvas.drawBitmap(srcBitmap, 0, 0, paint);        
          
        //在绘制第二张图片的时候,我们需要指定一个Xfermode   
        //这里采用Multiply模式,这个模式是将两张图片的对应的点的像素相乘 
  
        //,再除以255,然后以新的像素来重新绘制显示合成后的图像   
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY));  
        canvas.drawBitmap(dstBitmap, 0, 0, paint);  
          
        return bmp;  
    }  
    public void onActivityResult(int requestCode, int resultCode, Intent data){  
        super.onActivityResult(requestCode, resultCode, data);  
          
        Log.v("Result OK Value:", resultCode+"");  
        Log.v("RequestCode Value", requestCode+"");  
          
        if(resultCode == RESULT_OK){  
            imageUri = data.getData();    
            if(requestCode == FIRST_PIC){  
                //在Gallery中选中一个图片时,返回来的Intent中的Data就是选择图片的Uri 
  
                srcBitmap = getSrcImage(imageUri);  
                srcImageView.setImageBitmap(srcBitmap);               
            }else if(requestCode == SECOND_PIC){  
                //这里处理用户选择的第二张图片 
  
                  
                dstBitmap = getSrcImage(imageUri);  
                dstImageView.setImageBitmap(dstBitmap);  
            }  
        }  
    }  
      
    /** 
     * 需要加载的图片可能是大图,我们需要对其进行合适的缩小处理 
     * @param imageUri 
     */  
    private Bitmap getSrcImage(Uri imageUri){  
        //Display display = this.getWindowManager().getDefaultDisplay(); 
  
        try {  
            BitmapFactory.Options ops = new BitmapFactory.Options();  
            ops.inJustDecodeBounds = true;  
            Bitmap bmp = BitmapFactory.decodeStream(this.getContentResolver().openInputStream(imageUri),null,ops);  
            int wRatio = (int)Math.ceil(ops.outWidth/(float)MAX_WIDTH);  
            int hRatio = (int)Math.ceil(ops.outHeight/(float)MAX_HEIGHT);  
              
            if(wRatio > 1 && hRatio > 1){  
                if(wRatio > hRatio){  
                    ops.inSampleSize = wRatio;  
                }else{  
                    ops.inSampleSize = hRatio;  
                }  
            }  
              
            ops.inJustDecodeBounds = false;  
            bmp = BitmapFactory.decodeStream(this.getContentResolver().openInputStream(imageUri),null,ops);  
              
            return bmp;  
              
        } catch (FileNotFoundException e) {  
            // TODO Auto-generated catch block 
  
            e.printStackTrace();  
            Log.e(this.getClass().getName(), e.getMessage());  
        }  
          
        return null;  
    }  
}

调用Android自带的播放器播放audio

Android有其自带的播放器,我们可以使用隐式Intent来调用它:通过传入一个Action为ACTION_VIEW同时,指定Data为所要播放的Audio的Uri对象,并指定格式信息,则我们就可以调用播放器来播放该Audio了。

Intent intent = new Intent(Intent.ACTION_VIEW);

intent.setDataAndType(Uri, MimeType);

startActivity(intent);

本文我们需要访问MediaStore,来获取所有Audio信息,我们首先将获取所有的Album,然后当用户点击某个Album时,显示该Album下所有的Audio,然后当用户点击某个Audio时,调用系统自带的播放器播放该Audio。

package demo.camera;  
import java.io.File;  
import org.apache.http.client.utils.URIUtils;  
import android.app.Activity;  
import android.app.ListActivity;  
import android.content.Intent;  
import android.database.Cursor;  
import android.net.Uri;  
import android.os.Bundle;  
import android.os.Environment;  
import android.provider.MediaStore;  
import android.provider.MediaStore.Audio;  
import android.provider.MediaStore.Audio.Albums;  
import android.view.View;  
import android.widget.Button;  
import android.widget.CursorAdapter;  
import android.widget.ListView;  
import android.widget.SimpleCursorAdapter;  
/** 
 * 本示例演示如何利用Android自带的Music来播放程序 
 * 和Camera一样,可以通过Intent来启动它。 
 * 我们需要指定一个ACTION_VIEW的Action 
 * 同时一个Uri来指定我们要播放文件的路径 
 * 最后指定一个MIME类型,指定所要播放的文件类型 
 * 每种文件类型对应的都有一个MIME,他一般是类似于audio/mp3格式 
 * 前部分是一个较大的类型,后面是更具体的类型 
 *  
 * 同样的,对于Audio类型的多媒体,系统存储在MediaStore.Audio中 
 * 包括Media,Album,Genre等信息体 
 *  
 * 本文将以列表的形式列出所有的Album信息,供用户选择 
 * 当用户选择某个Album时,系统将打开这个ALbum下的所有Audio 
 * @author Administrator 
 * 
 */  
public class AudioDemo extends ListActivity {  
      
    private Button btnMusic;  
      
    private boolean isAlbum = true; //true时,说明当前列表的内容是Album,false时,说明是Media 
  
      
    private Cursor cursor; //游标对象,   
      
    public void onCreate(Bundle savedInstanceState){  
        super.onCreate(savedInstanceState);  
        this.setContentView(R.layout.audio);  
        btnMusic = (Button)this.findViewById(R.id.btn_music);  
        btnMusic.setOnClickListener(new View.OnClickListener() {  
              
            @Override  
            public void onClick(View v) {  
                  
//              Intent intent = new Intent(Intent.ACTION_VIEW); 
  
//              //这里我们先从SDCard文件中获取指定文件的URi 
  
//              File sdcard = Environment.getExternalStorageDirectory(); //这个是获取SDCard路径 
  
//              File audioFile = new File(sdcard.getPath()+"/music/tt.mp3"); 
  
//              //然后需要获取该文件的Uri 
  
//              Uri audioUri = Uri.fromFile(audioFile); 
  
//              //然后指定Uri和MIME 
  
//              intent.setDataAndType(audioUri, "audio/mp3"); 
  
//              startActivity(intent); 
  
                  
                //获取Album列表 
  
                getAlbums();  
                isAlbum = true;  
            }  
        });  
          
    }  
      
    public void onListItemClick(ListView l, View v, int position, long id){  
          
        //判断当前是哪个列表 
  
        if(isAlbum){  
            //如果是Album,当用户点击某一个时,获取该Album下的所有media 
  
            //l.getChildAt(position); 
  
            if(cursor.moveToPosition(position)){  
                getMedias(cursor.getInt(cursor.getColumnIndexOrThrow(Albums._ID)));  
                isAlbum = false;  
            }  
        }else{  
            //如果是Media,则当用户点击某一个时,则播放该Media 
  
            //调用系统自带的MediaPlayer来播放   
            if(cursor.moveToPosition(position)){  
                String mediaUri = cursor.getString(cursor.getColumnIndexOrThrow(Audio.Media.DATA));  
                String type = cursor.getString(cursor.getColumnIndexOrThrow(Audio.Media.MIME_TYPE));  
                Uri data = Uri.fromFile(new File(mediaUri));  
                Intent intent = new Intent(Intent.ACTION_VIEW);  
                intent.setDataAndType(data, type);  
                startActivity(intent);  
            }  
        }  
          
        //super.onListItemClick(l, v, position, id); 
  
    }  
      
      
    //获取所有Albums 
  
    public void getAlbums(){  
        String[] columns = new String[]{  
                Albums._ID,  
                Albums.ALBUM  
        };  
        String[] from = new String[]{  
                Albums.ALBUM  
        };  
        int[] to = new int[]{  
                android.R.id.text1  
        };  
        cursor = this.managedQuery(Albums.EXTERNAL_CONTENT_URI, columns, null, null, Albums.DEFAULT_SORT_ORDER);  
        CursorAdapter adapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, cursor, from, to);  
        this.setListAdapter(adapter);  
        //this.isAlbum = true; 
  
          
    }  
      
    //获取某个Albums下对应的medias 
  
    public void getMedias(int albumId){  
        String[] columns = new String[]{  
                Audio.Media._ID,  
                Audio.Media.DATA,  
                Audio.Media.DISPLAY_NAME,  
                Audio.Media.MIME_TYPE  
        };  
        String selection = Audio.Media.ALBUM_ID + "=?";  
        String[] selectionArgs = new String[]{  
                albumId+""  
        };  
          
        String[] from = new String[]{  
                Audio.Media.DISPLAY_NAME  
        };  
        int[] to = new int[]{  
                android.R.id.text1  
        };  
          
        cursor = this.managedQuery(Audio.Media.EXTERNAL_CONTENT_URI, columns, selection, selectionArgs, Audio.Media.TITLE);  
        CursorAdapter adapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1,cursor,from,to);  
        this.setListAdapter(adapter);  
    }  
}
利用Service实现背景音乐的播放

Activity类

package demo.camera;  
import android.app.Activity;  
import android.content.ComponentName;  
import android.content.Context;  
import android.content.Intent;  
import android.content.ServiceConnection;  
import android.os.Bundle;  
import android.os.IBinder;  
import android.view.View;  
/** 
 * 演示Activity如何利用Service来完成后台Audio的播放功能 
 * 同时如何将Service和Activity进行绑定 
 * @author Administrator 
 * 
 */  
public class BackgroundAudioDemo extends Activity {  
      
    private AudioService audioService;  
      
    //使用ServiceConnection来监听Service状态的变化 
  
    private ServiceConnection conn = new ServiceConnection() {  
          
        @Override  
        public void onServiceDisconnected(ComponentName name) {  
            // TODO Auto-generated method stub 
  
            audioService = null;  
        }  
          
        @Override  
        public void onServiceConnected(ComponentName name, IBinder binder) {  
            //这里我们实例化audioService,通过binder来实现 
  
            audioService = ((AudioService.AudioBinder)binder).getService();  
              
        }  
    };  
      
    public void onCreate(Bundle savedInstanceState){  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.back_audio);  
    }  
      
      
    public void onClick(View v){  
        int id = v.getId();  
        Intent intent = new Intent();  
        intent.setClass(this, AudioService.class);        
        if(id == R.id.btn_start){  
            //启动Service,然后绑定该Service,这样我们可以在同时销毁该Activity,看看歌曲是否还在播放 
  
            startService(intent);  
            bindService(intent, conn, Context.BIND_AUTO_CREATE);  
            finish();  
        }else if(id == R.id.btn_end){  
            //结束Service 
  
            unbindService(conn);  
            stopService(intent);  
            finish();  
        }else if(id == R.id.btn_fun){  
            audioService.haveFun();  
        }  
    }  
}

Service类

 package demo.camera;  
import android.app.Service;  
import android.content.Intent;  
import android.media.MediaPlayer;  
import android.os.Binder;  
import android.os.IBinder;  
import android.widget.MediaController.MediaPlayerControl;  
/** 
 * 为了可以使得在后台播放音乐,我们需要Service 
 * Service就是用来在后台完成一些不需要和用户交互的动作 
 * @author Administrator 
 * 
 */  
public class AudioService extends Service implements MediaPlayer.OnCompletionListener{  
      
    MediaPlayer player;  
      
    private final IBinder binder = new AudioBinder();  
    @Override  
    public IBinder onBind(Intent arg0) {  
        // TODO Auto-generated method stub 
  
        return binder;  
    }  
    /** 
     * 当Audio播放完的时候触发该动作 
     */  
    @Override  
    public void onCompletion(MediaPlayer player) {  
        // TODO Auto-generated method stub 
  
        stopSelf();//结束了,则结束Service 
  
    }  
      
    //在这里我们需要实例化MediaPlayer对象 
  
    public void onCreate(){  
        super.onCreate();  
        //我们从raw文件夹中获取一个应用自带的mp3文件 
  
        player = MediaPlayer.create(this, R.raw.tt);  
        player.setOnCompletionListener(this);  
    }  
      
    /** 
     * 该方法在SDK2.0才开始有的,替代原来的onStart方法 
     */  
    public int onStartCommand(Intent intent, int flags, int startId){  
        if(!player.isPlaying()){  
            player.start();  
        }  
        return START_STICKY;  
    }  
      
    public void onDestroy(){  
        //super.onDestroy(); 
  
        if(player.isPlaying()){  
            player.stop();  
        }  
        player.release();  
    }  
      
    //为了和Activity交互,我们需要定义一个Binder对象 
  
    class AudioBinder extends Binder{  
          
        //返回Service对象 
  
        AudioService getService(){  
            return AudioService.this;  
        }  
    }  
      
    //后退播放进度 
  
    public void haveFun(){  
        if(player.isPlaying() && player.getCurrentPosition()>2500){  
            player.seekTo(player.getCurrentPosition()-2500);  
        }  
    }  
}

在清单文件AndroidManifest.xml中配置Service

<service
            android:name=".AudioService" />

 

我们今天的关于电脑入门学习-多媒体学习-internet学习01多媒体教学电脑的分享已经告一段落,感谢您的关注,如果您想了解更多关于(已导出)【kubernetes系列学习】client-go学习与实践、.net学习笔记之 AJAX学习、.NET开发人员关于ML.NET的入门学习、Android多媒体学习的相关信息,请在本站查询。

最近很多小伙伴都在问电脑入门学习办公学习WORD使用-精彩的表格办公软件word表格入门教学视频这两个问题,那么本篇文章就来给大家详细解答一下,同时本文还将给你拓展Android Framework 入门学习、Android入门学习_Hello Word程序设计、Aspose.Words for .NET使用表格教程之创建表格——Microsoft Word和Aspose.Words表格介绍、excel表格如何转换为word中的表格等相关知识,下面开始了哦!

本文目录一览:

电脑入门学习办公学习WORD使用-精彩的表格(办公软件word表格入门教学视频)

电脑入门学习办公学习WORD使用-精彩的表格(办公软件word表格入门教学视频)

电脑技术网教你学电脑入门学习系列视频教程适合刚学电脑的朋友,讲的很简单易懂。对刚学电脑的朋友是比较有帮助的,能快速引导你学习电脑入门。看完这一系列教程,基本上对电脑操作知识有了大概的了解,让你知道可以从哪里入手操作电脑。已经有一定电脑知识的朋友可以跳过此教程。

Android Framework 入门学习

Android Framework 入门学习

前言

众所皆知,Android系统是当前占据用户量最大的手机系统,国内流行的客户端开发无非是android 与 ios,即使作为一个普通用户,小伙伴们可曾想过这个给我们生活带来巨大变化的系统是如何为我们服务的呢?

Android系统可大致分为五层,如下图,第一层就是我们平时看到的各种应用了,这个小伙伴们肯定熟悉,这里就不多说了,要给大家介绍的是第二层——Framework,它直接对接应用程序,提供了本地系统服务和java系统服务。

那么这些服务是如何使用的呢,下面简要分析一下这个过程

Android Framework

先来看一个应用的启动过程

如上图,一个应用启动主要依赖于ActivityManager服务,它是系统提供的众多服务里的其中一个,服务作为framework提供的主要内容,扮演着承上启下的重要责任:一方面为应用提供约定好的功能调用接口,另一方面无需应用关心服务如何实现,framework会负责与底下驱动层进行交互,达到目的。

正因为有了framework层,应用开发才能事半功倍,专注于业务逻辑实现,接下来就来介绍一下服务如何运行.

1、服务检索

服务检索是指调用服务的客户端向Context Manager(service manager中第一个注册的节点)请求指定服务的handle的过程。调用服务的客户端把包含服务请求信息的IPC数据发送给Context Manager,然后Context Manager通过IPC应答数据将指定服务的handle发送给它。Binder Driver将把调用服务的客户端请求的服务的binder_node结构体注册到客户端的bind_proc结构体中。 

针对上面这段话有三点需要解释一下:

1)service_manager如何查找指定服务的handle,如下代码:

struct svcinfo  

上面就是service_manager.c中的检索服务代码,可以看出service_manager维护一张服务表svclist,可以根据服务名查找对应的结构体svcinfo,这个结构体里面就包含了需要的handle变量,handle值会被保存在BpBinder里面的mHandle变量里面。

2)binder_node是什么?下面是一段服务注册过程中的代码:

fp = (struct flat_binder_object *)(t->buffer->data + *offp);

来看一下bind_ref结构体:

struct binder_ref {

所以binder_node就是服务注册时传入的服务对象,其中第一个参数proc是代表Service Server的binder_proc,因为所有的服务实体都是注册到Service Server,而后面的binder_get_ref_for_node则是将该实体对应的引用注册到Context Manager,即Context Manager拥有所有服务实体对应的引用,Service Server拥有所有服务实体对象,下面是binder_node结构体:

struct binder_node {

其中proc是Service Server进程的binder proc地址,ptr是远程binder对象地址,即BpBinder,cookie是注册的本地服务的binder地址,每次Service Server接收到消息会先把cookie转换成对应的Service对象,然后根据传入的方法编号选择对应的方法执行生成结果数据,这样Service Server只要负责执行就行了,不用管服务对象的查找。

3)什么是binder_proc?首先看一下binder_open函数:

static int binder_open(struct inode *nodp, struct file *filp){

从上面函数可以看出每个进程调用binder_open都会生成自己的binder_proc,从binder_proc结构体可以看出进程间通信主要是靠每个进程在内核空间开辟的一块buffer,通信时一方会把自己的数据传到自己开辟的Buffer里面,然后binder driver负责将这些数据拷贝到目标进程的buffer里,然后唤醒目标进程处理数据就行了。

总结起来服务检索过程有如下几步:

  1. Context Manager(ServiceManager)进入待机状态,等待接收IPC数据。
  2. 调用服务的客户端生成并初始化binder_proc结构体,而后开辟一块buffer用于接收IPC应答数据
  3. 调用服务的客户端通过ioctl()调用binder driver的binder_ioctl()函数。与注册服务时一样,binder driver会查找Context Manager的binder_proc结构体。但与注册服务不同的是,它并不生成binder_node结构体,只是将IPC数据拷贝到Context Manager的接收buffer中。并且记下调用服务客户端的binder_proc结构体,以便查找IPC应答数据的接收端。
  4. Binder driver让调用服务的客户端处于待机状态,并唤醒处于待机状态的Context Manager,而后接收IPC数据。从待机状态苏醒的Context Manager在服务目录中查找请求的服务,把服务编号插入到IPC应答数据中,并把IPC应答数据传递给binder driver.
  5. Binder dirver将(4)中接收到服务编号去Context Manager中查找相应的binder_node结构体(先查找对应结构体的引用,引用里的一个属性就是binder_node),而后将查找到binder_node结构体注册到调用服务的客户端的binder_proc中。binder_node结构体用于在调用服务时查找Service Server的binder_proc结构体.
  6. Binder driver将(5)中注册的binder_node结构体的编号插入到IPC应答数据中,传递给客户端,然后唤醒客户端。在使用服务时,客户端将编号作为handle使用。

2、服务使用

经过服务检索,客户端获得了Service Server所拥有服务的binder_node,在生成IPC数据时,它就可以把要使用服务的binder节点编号设置到IPC数据的handle中,取代原来值为0的handle,服务使用有如下过程:

  • Service Server处于待机状态,等待接收IPC数据。
  • 客户端将从服务检索中获取的binder节点编号保存到IPC数据的handle(等于binder_ref中的desc)中,生成IPC数据后传递给binder driver,binder driver根据IPC数据中的handle查找相应的binder_ref结构体(ContextManager的binder proc结构体里面保存了所有的binder_ref对象,可以根据desc属性查找对应的binder_ref对象),然后获取binder_ref里面的binder_node对象,而binder_node结构体里面的proc属性就是注册该服务的Service Server的binder_proc地址。最后通过binder_proc结构体中binder_buffer结构体,将IPC数据拷贝到Service Server进程的buffer中。
  • Binder driver让客户端进入待机状态,唤醒处于待机状态的Service Server。Service Server从待机状态苏醒后接受IPC数据,并通过IPC数据中的RPC代码、RPC数据调用相应的服务函数。
  • 在服务函数执行完毕后,Service Server会生成IPC应答数据,并将其传递给binder driver,binder driver将IPC数据传递给客户端。至此,客户端调用服务的整个IPC过程就完成了。

总结

Android 提供的系统服务我们在开发过程中很多可以通过反射方式调用,不过系统也有提供接口给我们,比如context.getSystemService,不过getSystemService方法获取的是注册在SystemServiceRegistry里面的服务,里面的服务有的是来自系统服务;有的不是,比如Context.WINDOW_SERVICE就不是系统的,而是与当前进程绑定的 WindowManagerImpl(ctx);

参考:https://mp.weixin.qq.com/s/blMeASduNrJqXxH07tmInA

Android百大框架源码解析学习视频

Android入门学习_Hello Word程序设计

Android入门学习_Hello Word程序设计

Hello,World是我们每学一门语言,第一个要写得程序,今天我就从这开始。

       打开ECLIPSE,选择 File > New > Project.>others>Andriod project在出现的对话框里输入 Project Name,Application Name,Package Name,Create Activity,选择ANDROID1.5,点击FINISH.

       项目就建完了,很简单吧。出乎我的意料。

       现在看看具体代码文件,在左边的package explorer,select project helloworld.

       在src下打开HelloAndriod.java文件。


java代码:
  1. package eoe.demo;

  2. import android.app.Activity;
  3. import android.os.Bundle;

  4. public class HelloAndroid extends Activity {
  5. /** Called when the activity is first created. */
  6. //程序入口点
  7. @Override
  8. public void onCreate(Bundle savedInstanceState) {
  9. super.onCreate(savedInstanceState);
  10. setContentView(R.layout.main);
  11. //设置显示的UI,
  12. R.layout.main就是一个XML文件。
  13. }
  14. }
  15. /res/layout/main.XML内容如下
  16. <?xml version="1.0" encoding="utf-8"?>
  17. <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_;fill_parent"
  18. android:layout_height="fill_parent"
  19. android:text="@string/hello"/>
  20. //在strings.xml定义
  21. <?xml version="1.0" encoding="utf-8"?>
  22. //固定的
  23. xmlns:android=http://schemas.android.com/apk/res/android
  24. XML的NAMESPACE,每一格都必须有。
复制代码

       android:layout_width
       android:layout_height


       当前VIEW的宽和高。fill_parent的含义在这个程序中是暂居占据整个SCREEN。text 显示的内容,这里采用定义的常量表示。

    res/values/ strings.xml


java代码:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <resources>
  3. <string name="hello">Hello, Android! I am a string resource!</string>
  4. <string name="app_name">Hello, Android</string>
  5. </resources>

  6. //顺便看一下R.JAVA

  7. package eoe.demo;
  8. public final class R {
  9. public static final class attr { }
  10. public static final class drawable {
  11. public static final int icon=0x7f020000;
  12. }
  13. public static final class layout {
  14. public static final int main=0x7f030000;
  15. }
  16. public static final class string {
  17. public static final int app_name=0x7f040001;
  18. public static final int hello=0x7f040000;
  19. }

  20. }
复制代码

Aspose.Words for .NET使用表格教程之创建表格——Microsoft Word和Aspose.Words表格介绍

Aspose.Words for .NET使用表格教程之创建表格——Microsoft Word和Aspose.Words表格介绍

Aspose.Words For .Net是一种高级Word文档处理API,用于执行各种文档管理和操作任务。API支持生成,修改,转换,呈现和打印文档,而无需在跨平台应用程序中直接使用Microsoft Word。此外,API支持所有流行的Word处理文件格式,并允许将Word文档导出或转换为固定布局文件格式和最常用的图像/多媒体格式。

【下载Aspose.Words for .NET最新试用版】

接下来我们将进入“使用格式”的介绍,其中包括应用格式、介绍和创建表、添加和拆分表以及使用列和行。


表是word文档中常见的元素。它们允许在具有行和列的网格结构中清晰地组织和显示大量信息。它们还经常用作页面布局工具,并且是显示选项卡数据(带有选项卡停止)的更好选择,因为它们允许更好地控制内容的设计和布局。

表由Cell,Row和Column等元素组成。这些概念通常适用于所有表,无论它们来自Microsoft Word文档还是HTML文档,完全支持Aspose.Words中的表。您可以自由编辑,更改,添加和删除表格。还支持高保真表格的渲染。

Microsoft Word中的表

▲在Microsoft Word中插入表

在Microsoft Word 2003及更早版本中插入表:

  1. 单击顶部工具栏中的“表格”菜单。
  2. 单击插入,然后单击表格。
  3. 填写适当的值,然后按确定以插入表格。

在Microsoft Word 2007及更高版本中插入表:

  1. 单击“插入”选项卡。
  2. 选择表格下拉菜单。
  3. 选择“插入表”。
  4. 填写适当的值,然后按确定以插入表格。

▲使用Microsoft Word中的自动调整功能

要使用自动调整功能自动调整Microsoft Word中的表格大小:

  1. 右键单击所需表格内的任何位置。
  2. 从弹出菜单中选择AutoFit。
  3. 选择所需的自动调整选项
    • AutoFit to Contents适合围绕内容的表格。
    • AutoFit to Window调整表格的大小,使其填充左右边距之间的可用页面宽度。
    • 固定列宽度将每个列宽设置为绝对值。这意味着即使单元格内的内容发生变化,表格中每列的宽度也会保持不变。

Aspose.Words中的表格

加载到Aspose.Words中的任何文档中的表都作为表节点导入。表可以作为主体文本的子元素,内容故事(如注释或脚注)或单元格内的嵌套表格来查找。此外,表可以嵌套在其他表中,直到任何深度。一个表节点不包含任何实际的内容-取而代之的则是其他这些节点从而弥补了内容物的容器:

  • 表包含许多Row节点。表公开了节点的所有普通成员,允许您自由移动,修改和删除文档中的表。
  • A Row表示表的单行,包含许多Cell节点。此外,一行提供了定义行显示方式的成员,例如高度和对齐方式。
  • Cell包含在表中看到的真实内容,由Paragraph和其他块级节点组成。此外,单元格可以包含其他嵌套表。

通过使用DocumentExplorer检查文档中表节点的结构,可以最好地表示这种关系。同时还可以在上图中看到该文档包含一个表,该表由一行组成,而该行又由两个单元组成。两个单元格中的每一个都包含一个段落,该段落是格式化文本的容器。在Aspose.Words中,所有与表相关的类和属性都包含在Aspose.Words.Tables命名空间中。

 

                                         欢迎下载|体验更多Aspose文档管理产品  或 加入Aspose技术交流群(761297826

 

excel表格如何转换为word中的表格

excel表格如何转换为word中的表格

excel表格如何转换为word中的表格

首先我们打开excel表格,全选表格,右键单击,选择“复制”选项

9ec9b434b7a4d297da40204f3d43591.png

接着我们新建一个空白文档,右键单击,选择“粘贴”选项,粘贴后表格格式会比较混乱,我们继续下一步。全选混乱的表格,右键单击,在弹出的菜单中依次选择“自动调整”、“根据窗口调整”选项

3efcd295f9003554dd86a4720f74261.png

e2ff15f9394e233d89605d0426fad1f.png

最后我们适当调整一下单元格的宽度,这样表格就转换完成了。

推荐教程:excel教程

以上就是excel表格如何转换为word中的表格的详细内容,更多请关注php中文网其它相关文章!

关于电脑入门学习办公学习WORD使用-精彩的表格办公软件word表格入门教学视频的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于Android Framework 入门学习、Android入门学习_Hello Word程序设计、Aspose.Words for .NET使用表格教程之创建表格——Microsoft Word和Aspose.Words表格介绍、excel表格如何转换为word中的表格等相关知识的信息别忘了在本站进行查找喔。

这篇文章主要围绕电脑入门学习办公学习Excel简介电脑办公入门教程5步快速学会excel表格制作展开,旨在为您提供一份详细的参考资料。我们将全面介绍电脑入门学习办公学习Excel简介的优缺点,解答电脑办公入门教程5步快速学会excel表格制作的相关问题,同时也会为您带来easyexcel实现导出excel简单例子、EasyExcel简介及使用方法、Elasticsearch 简单学习 4: 入门学习 - 1、Elasticsearch 简单学习 5: 入门学习 - 2的实用方法。

本文目录一览:

电脑入门学习办公学习Excel简介(电脑办公入门教程5步快速学会excel表格制作)

电脑入门学习办公学习Excel简介(电脑办公入门教程5步快速学会excel表格制作)

电脑技术网教你学电脑入门学习系列视频教程适合刚学电脑的朋友,讲的很简单易懂。对刚学电脑的朋友是比较有帮助的,能快速引导你学习电脑入门。看完这一系列教程,基本上对电脑操作知识有了大概的了解,让你知道可以从哪里入手操作电脑。已经有一定电脑知识的朋友可以跳过此教程。

easyexcel实现导出excel简单例子

easyexcel实现导出excel简单例子

<!-- https://mvnrepository.com/artifact/com.alibaba/easyexcel -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>2.2.6</version>
</dependency>

 

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import lombok.Data;
import org.apache.poi.ss.usermodel.IndexedColors;

import java.util.ArrayList;
import java.util.List;

public class ExcelDownload {

    public static void main(String[] args) {
        ExcelDownload excelDownload = new ExcelDownload();
        excelDownload.download();
    }

    public void download() {
        String path = "/Users/xxx/Desktop/data/test.xlsx";

        List<DownEntry> list = new ArrayList<>();
        list.add(new DownEntry("张三", 10));
        list.add(new DownEntry("李四", 20));

        // 创建写入器
        ExcelWriter excelWriter = EasyExcel.write(path).registerWriteHandler(style()).head(DownEntry.class).build();
        WriteSheet writeSheet = EasyExcel.writerSheet("Sheet1").build();

        for (int i = 0; i < 2; i++) {
            // 写入数据  业务上可以配合分页多次写入
            excelWriter.write(list, writeSheet);
        }
        excelWriter.finish();
    }

    public HorizontalCellStyleStrategy style() {
        // 头的策略
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        // 背景设置为红色
        headWriteCellStyle.setFillForegroundColor(IndexedColors.YELLOW.getIndex());
        WriteFont headWriteFont = new WriteFont();
        headWriteFont.setFontHeightInPoints((short) 20);
        headWriteCellStyle.setWriteFont(headWriteFont);
        // 内容的策略
        WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
        // 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定
//        contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
        // 背景绿色
//        contentWriteCellStyle.setFillForegroundColor(IndexedColors.AUTOMATIC.getIndex());
        WriteFont contentWriteFont = new WriteFont();
        // 字体大小
        contentWriteFont.setFontHeightInPoints((short) 10);
        contentWriteCellStyle.setWriteFont(contentWriteFont);
        // 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现
        HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
        return horizontalCellStyleStrategy;
    }


    @Data
    public static class DownEntry {

        @ExcelProperty(value = "姓名")
        private String name;

        @ExcelProperty(value = "年龄")
        private Integer age;

        public DownEntry(String name, Integer age) {
            this.name = name;
            this.age = age;
        }
    }
}

EasyExcel简介及使用方法

EasyExcel简介及使用方法

EasyExcel简介

  • easyExcel是阿里巴巴开源poi插件之一,当前最新版本1.1.2-beta5,poi版本3.17,因此,集成时老版本poi需要提升poi版本,或者做版本隔离。
  • 吐槽一下这个版本没有RELEASE版本
  • 主要解决了poi框架使用复杂,sax解析模式不容易操作,数据量大起来容易OOM,解决了POI并发造成的报错
  • 主要解决方式:通过解压文件的方式加载,一行一行的加载,并且抛弃样式字体等不重要的数据,降低内存的占用
  • 具体实现原理,建议看github上的readme

 

EasyExcel 的 github 地址: https://github.com/alibaba/easyexcel

EasyExcel优势

  • EasyExcel 最大的特点就是使用内存少,当然现在它的功能还比较简单,能够面对的复杂场景比较少,不过基本的读写完全可以满足。
  • 注解式自定义操作。
  • 输入输出简单,提供输入输出过程的接口
  • 支持一定程度的单元格合并等灵活化操作

EasyExcel劣势

  • 框架不成熟,1.1.0版本后提供灵活接口的只剩beta版本
  • 依然存在一些bug
  • 没有一套完整的api
  • 一. 依赖

    首先是添加该项目的依赖,目前的版本是 1.0.2

    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>easyexcel</artifactId>
        <version>1.0.2</version>
    </dependency>
    

    二. 需要的类

    1. ExcelUtil

    工具类,可以直接调用该工具类的方法完成 Excel 的读或者写

     

    /**
     * Created with IntelliJ IDEA
     *
     * @Author yuanhaoyue swithaoy@gmail.com
     * @Description 工具类
     * @Date 2018-06-06
     * @Time 14:07
     */
    public class ExcelUtil {
        /**
         * 读取 Excel(多个 sheet)
         *
         * @param excel    文件
         * @param rowModel 实体类映射,继承 BaseRowModel 类
         * @return Excel 数据 list
         */
        public static List<Object> readExcel(MultipartFile excel, BaseRowModel rowModel) {
            ExcelListener excelListener = new ExcelListener();
            ExcelReader reader = getReader(excel, excelListener);
            if (reader == null) {
                return null;
            }
            for (Sheet sheet : reader.getSheets()) {
                if (rowModel != null) {
                    sheet.setClazz(rowModel.getClass());
                }
                reader.read(sheet);
            }
            return excelListener.getDatas();
        }
    
        /**
         * 读取某个 sheet 的 Excel
         *
         * @param excel    文件
         * @param rowModel 实体类映射,继承 BaseRowModel 类
         * @param sheetNo  sheet 的序号 从1开始
         * @return Excel 数据 list
         */
        public static List<Object> readExcel(MultipartFile excel, BaseRowModel rowModel, int sheetNo) {
            return readExcel(excel, rowModel, sheetNo, 1);
        }
    
        /**
         * 读取某个 sheet 的 Excel
         *
         * @param excel       文件
         * @param rowModel    实体类映射,继承 BaseRowModel 类
         * @param sheetNo     sheet 的序号 从1开始
         * @param headLineNum 表头行数,默认为1
         * @return Excel 数据 list
         */
        public static List<Object> readExcel(MultipartFile excel, BaseRowModel rowModel, int sheetNo,
                                             int headLineNum) {
            ExcelListener excelListener = new ExcelListener();
            ExcelReader reader = getReader(excel, excelListener);
            if (reader == null) {
                return null;
            }
            reader.read(new Sheet(sheetNo, headLineNum, rowModel.getClass()));
            return excelListener.getDatas();
        }
    
        /**
         * 导出 Excel :一个 sheet,带表头
         *
         * @param response  HttpServletResponse
         * @param list      数据 list,每个元素为一个 BaseRowModel
         * @param fileName  导出的文件名
         * @param sheetName 导入文件的 sheet 名
         * @param object    映射实体类,Excel 模型
         */
        public static void writeExcel(HttpServletResponse response, List<? extends BaseRowModel> list,
                                      String fileName, String sheetName, BaseRowModel object) {
            ExcelWriter writer = new ExcelWriter(getOutputStream(fileName, response), ExcelTypeEnum.XLSX);
            Sheet sheet = new Sheet(1, 0, object.getClass());
            sheet.setSheetName(sheetName);
            writer.write(list, sheet);
            writer.finish();
        }
    
        /**
         * 导出 Excel :多个 sheet,带表头
         *
         * @param response  HttpServletResponse
         * @param list      数据 list,每个元素为一个 BaseRowModel
         * @param fileName  导出的文件名
         * @param sheetName 导入文件的 sheet 名
         * @param object    映射实体类,Excel 模型
         */
        public static ExcelWriterFactroy writeExcelWithSheets(HttpServletResponse response, List<? extends BaseRowModel> list,
                                                              String fileName, String sheetName, BaseRowModel object) {
            ExcelWriterFactroy writer = new ExcelWriterFactroy(getOutputStream(fileName, response), ExcelTypeEnum.XLSX);
            Sheet sheet = new Sheet(1, 0, object.getClass());
            sheet.setSheetName(sheetName);
            writer.write(list, sheet);
            return writer;
        }
    
        /**
         * 导出文件时为Writer生成OutputStream
         */
        private static OutputStream getOutputStream(String fileName, HttpServletResponse response) {
            //创建本地文件
            String filePath = fileName + ".xlsx";
            File dbfFile = new File(filePath);
            try {
                if (!dbfFile.exists() || dbfFile.isDirectory()) {
                    dbfFile.createNewFile();
                }
                fileName = new String(filePath.getBytes(), "ISO-8859-1");
                response.addHeader("Content-Disposition", "filename=" + fileName);
                return response.getOutputStream();
            } catch (IOException e) {
                throw new ExcelException("创建文件失败!");
            }
        }
    
        /**
         * 返回 ExcelReader
         *
         * @param excel         需要解析的 Excel 文件
         * @param excelListener new ExcelListener()
         */
        private static ExcelReader getReader(MultipartFile excel,
                                             ExcelListener excelListener) {
            String filename = excel.getOriginalFilename();
            if (filename == null || (!filename.toLowerCase().endsWith(".xls") && !filename.toLowerCase().endsWith(".xlsx"))) {
                throw new ExcelException("文件格式错误!");
            }
            InputStream inputStream;
            try {
                inputStream = new BufferedInputStream(excel.getInputStream());
                return new ExcelReader(inputStream, null, excelListener, false);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
    }
    

     

    2. ExcelListener

    监听类,可以根据需要与自己的情况,自定义处理获取到的数据,我这里只是简单地把数据添加到一个 List 里面。

    public class ExcelListener extends AnalysisEventListener {
    
        //自定义用于暂时存储data。
        //可以通过实例获取该值
        private List<Object> datas = new ArrayList<>();
    
        /**
         * 通过 AnalysisContext 对象还可以获取当前 sheet,当前行等数据
         */
        @Override
        public void invoke(Object object, AnalysisContext context) {
            //数据存储到list,供批量处理,或后续自己业务逻辑处理。
            datas.add(object);
            //根据自己业务做处理
            doSomething(object);
        }
    
        private void doSomething(Object object) {
        }
    
        @Override
        public void doAfterAllAnalysed(AnalysisContext context) {
            /*
                datas.clear();
                解析结束销毁不用的资源
             */
        }
    
        public List<Object> getDatas() {
            return datas;
        }
    
        public void setDatas(List<Object> datas) {
            this.datas = datas;
        }
    }
    

    3. ExcelWriterFactroy

    用于导出多个 sheet 的 Excel,通过多次调用 write 方法写入多个 sheet

    /**
     * Created with IntelliJ IDEA
     *
     * @Author yuanhaoyue swithaoy@gmail.com
     * @Description
     * @Date 2018-06-07
     * @Time 16:47
     */
    public class ExcelWriterFactroy extends ExcelWriter {
        private OutputStream outputStream;
        private int sheetNo = 1;
    
        public ExcelWriterFactroy(OutputStream outputStream, ExcelTypeEnum typeEnum) {
            super(outputStream, typeEnum);
            this.outputStream = outputStream;
        }
    
        public ExcelWriterFactroy write(List<? extends BaseRowModel> list, String sheetName,
                                        BaseRowModel object) {
            this.sheetNo++;
            try {
                Sheet sheet = new Sheet(sheetNo, 0, object.getClass());
                sheet.setSheetName(sheetName);
                this.write(list, sheet);
            } catch (Exception ex) {
                ex.printStackTrace();
                try {
                    outputStream.flush();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return this;
        }
    
        @Override
        public void finish() {
            super.finish();
            try {
                outputStream.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    

     

    4. ExcelException

    捕获相关 Exception

     

    /**
     * Created with IntelliJ IDEA
     *
     * @Author yuanhaoyue swithaoy@gmail.com
     * @Description Excel 解析 Exception
     * @Date 2018-06-06
     * @Time 15:56
     */
    public class ExcelException extends RuntimeException {
        public ExcelException(String message) {
            super(message);
        }
    }
    

     

    三. 读取 Excel

    读取 Excel 时只需要调用 ExcelUtil.readExcel() 方法

    @RequestMapping(value = "readExcel", method = RequestMethod.POST)
    public Object readExcel(MultipartFile excel) {
        return ExcelUtil.readExcel(excel, new ImportInfo());
    }
    

    其中 excel 是 MultipartFile 类型的文件对象,而 new ImportInfo() 是该 Excel 所映射的实体对象,需要继承 BaseRowModel 类,如:

    public class ImportInfo extends BaseRowModel {
        @ExcelProperty(index = 0)
        private String name;
    
        @ExcelProperty(index = 1)
        private String age;
    
        @ExcelProperty(index = 2)
        private String email;
    
        /*
            作为 excel 的模型映射,需要 setter 方法
         */
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getAge() {
            return age;
        }
    
        public void setAge(String age) {
            this.age = age;
        }
    
        public String getEmail() {
            return email;
        }
    
        public void setEmail(String email) {
            this.email = email;
        }
    }
    

    作为映射实体类,通过 @ExcelProperty 注解与 index 变量可以标注成员变量所映射的列,同时不可缺少 setter 方法

    四. 导出 Excel

    1. 导出的 Excel 只拥有一个 sheet

    只需要调用 ExcelUtil.writeExcelWithSheets() 方法:

    @RequestMapping(value = "writeExcel", method = RequestMethod.GET)
    public void writeExcel(HttpServletResponse response) throws IOException {
        List<ExportInfo> list = getList();
        String fileName = "一个 Excel 文件";
        String sheetName = "第一个 sheet";
    
        ExcelUtil.writeExcel(response, list, fileName, sheetName, new ExportInfo());
        }
    

    fileName,sheetName 分别是导出文件的文件名和 sheet 名,new ExportInfo() 为导出数据的映射实体对象,list 为导出数据。

    对于映射实体类,可以根据需要通过 @ExcelProperty 注解自定义表头,当然同样需要继承 BaseRowModel 类,如:

    public class ExportInfo extends BaseRowModel {
        @ExcelProperty(value = "姓名" ,index = 0)
        private String name;
    
        @ExcelProperty(value = "年龄",index = 1)
        private String age;
    
        @ExcelProperty(value = "邮箱",index = 2)
        private String email;
    
        @ExcelProperty(value = "地址",index = 3)
        private String address;
    }
    

    value 为列名,index 为列的序号

    如果需要复杂一点,可以实现如下图的效果: 

    对应的实体类写法如下:

    public class MultiLineHeadExcelModel extends BaseRowModel {
    
        @ExcelProperty(value = {"表头1","表头1","表头31"},index = 0)
        private String p1;
    
        @ExcelProperty(value = {"表头1","表头1","表头32"},index = 1)
        private String p2;
    
        @ExcelProperty(value = {"表头3","表头3","表头3"},index = 2)
        private int p3;
    
        @ExcelProperty(value = {"表头4","表头4","表头4"},index = 3)
        private long p4;
    
        @ExcelProperty(value = {"表头5","表头51","表头52"},index = 4)
        private String p5;
    
        @ExcelProperty(value = {"表头6","表头61","表头611"},index = 5)
        private String p6;
    
        @ExcelProperty(value = {"表头6","表头61","表头612"},index = 6)
        private String p7;
    
        @ExcelProperty(value = {"表头6","表头62","表头621"},index = 7)
        private String p8;
    
        @ExcelProperty(value = {"表头6","表头62","表头622"},index = 8)
        private String p9;
    }
    

    2. 导出的 Excel 拥有多个 sheet

    调用 ExcelUtil.writeExcelWithSheets() 处理第一个 sheet,之后调用 write() 方法依次处理之后的 sheet,最后使用 finish() 方法结束

    public void writeExcelWithSheets(HttpServletResponse response) throws IOException {
        List<ExportInfo> list = getList();
        String fileName = "一个 Excel 文件";
        String sheetName1 = "第一个 sheet";
        String sheetName2 = "第二个 sheet";
        String sheetName3 = "第三个 sheet";
    
        ExcelUtil.writeExcelWithSheets(response, list, fileName, sheetName1, new ExportInfo())
                    .write(list, sheetName2, new ExportInfo())
                    .write(list, sheetName3, new ExportInfo())
                    .finish();
    }
    

    write 方法的参数为当前 sheet 的 list 数据,当前 sheet 名以及对应的映射类

Elasticsearch 简单学习 4: 入门学习 - 1

Elasticsearch 简单学习 4: 入门学习 - 1

一、基本概念

1. 文档

《1.》Elasticsearch 是面向文档的,文档是所有可搜索数据的最小单位。

       eg: ① 日志文件中的日志项

             ② 一部电影的具体信息 | 一张唱片的详细信息

             ③ MP3 播放器里的一首歌 | 一篇 PDF 文档中的具体内容

《2.》文档会被序列化成 JSON 格式,保存在 Elasticsearch 中

          ① JSON 对象由字段组成

          ② 每个字段都有对应的字段类型 (字符串 | 数值 | 布尔 | 日期 | 二进制 | 范围类型)

《3.》每个文档都有一个 Uinque ID

         ① 你可以自己指定 ID

         ② 或者通过 Elasticsearch 自动生成

2.JSON 文档

《1.》一篇文档包含了一系列的字段。类似数据库表中一条记录

《2.》JSON 文档,格式灵活,不需要预先定义格式

         ① 字段的类型可以指定或者通过 Elasticsearch 自动推算

         ② 支持数组 | 支持嵌套

3. 文档的元数据

4. 索引

5. 索引的不同语意

6. 抽象与类比

为什么不再支持单个 Index 下,多个 Types:

https://www.elastic.co/cn/blog/moving-from-types-to-typeless-apis-in-elasticsearch-7-0

 

7.REST API 

很容易被各种语言调用

8. 一些基本的 API

之前装 Kibana 时,我们导入的有一些测试数据,电子商务订单、监控航线的示例数据、监控 Web 日志的示例数据,

以及装入 Logstash 时,导入的 movie 的测试数据,我们可以通过 kibana 的索引管理看到。

//查看“电子商务订单”索引相关信息
GET kibana_sample_data_ecommerce

//查看“电子商务订单”的文档总数
GET kibana_sample_data_ecommerce/_count

//查看“电子商务订单”前10条文档,了解文档格式
POST kibana_sample_data_ecommerce/_search

//查以kibana开头的索引(通配符查询)
GET /_cat/indices/kibana*?v&s=index

//查看状态为绿的索引
GET /_cat/indices?v&health=green

//按照文档的个数排序
GET /_cat/indices?v&s=docs.count:desc

//查看每个索引占用的内存
GET /_cat/indices?v&h=i,tm&s=tm:desc

CAT Indices:

https://www.elastic.co/guide/en/elasticsearch/reference/7.1/cat-indices.html

二、集群 | 节点 | 分片 | 副本

 

1. 分布式系统的可用性与扩展性

《1.》高可用

        服务可用性:允许有节点停止服务

        数据可用性:部分节点丢失,不会丢失数据

《2.》可扩展性

        请求量提升 | 数据的不断增长(将数据分布到所有节点上)

 

2. 分布式特性

《1.》Elasticsearch 分布式架构的好处

         存储的水平扩容

         提高系统的可用性,部分节点停止服务,整个集群的服务不受影响

《2.》Elasticsearch 的分布式架构

         不同的集群通过不同的名字来区分,默认名字 “elasticsearch

         通过配置文件修改,或者在命令行中 -E cluster.name=beehive 进行设定

        一个集群可以有一个或者多个节点

 

3. 节点

《1.》节点是一个 Elasticsearch 的实例

         本质上就是一个 JAVA 进程

          一台机器上可以运行多个 Elasticsearch 进程,但是,生产环境一般建议一台机器上只运行一个 Elasticsearch 实例

《2.》每一个节点都有名字,通过配置文件配置,或者启动时候 -E node.name=node1 指定

《3.》每一个节点在启动之后,会分配一个 UID,保存在 data 目录下

 

4.Master-eligible nodes 和 Master Node

《1.》每个节点启动后,默认就是一个 Master eligible 节点 

         可以设置 node.master:false 禁止

《2.》Master-eligible 节点可以参加选主流程,成为 Master 节点

《3.》当第一个节点启动时候,它会将自己选举成 Master 节点。

《4.》每个节点上都保存了集群的状态,只有 Master 节点才能修改集群的状态信息

《5.》集群状态(Cluster State) , 维护了一个集群中,必要的信息

          ① 所有的节点信息

          ② 所有的索引和其相关的 Mapping 与 Setting 信息

          ③ 分片的路由信息

          注意事项:只有 Master 节点才能修改集群的状态信息,如果任意节点都能修改信息会导致数据的不一致性

 

 5.Data Node & Coordinating Node

 《1.》Data Node

          可以保存数据的节点,叫做 Data Node 。负责保存分片数据。在数据扩展上起到了至关重要的作用

《2.》Coordinating Node

          ① 负责接受 Client 的请求,将请求分发到合适的节点,最终把结果汇集到一起

          ② 每个节点默认都起到了 Coordinating Node 的职责

6. 其他的节点类型

《1.》Hot & Warm Node

        不同硬件配置的 Data Node , 用来实现 Hot & Warm 架构 ,降低集群部署的成本。

        比如:日志处理时,会设置冷热节点,热节点会有更好的磁盘以及吞吐量。 

《2.》Machine Learning Node

         负责跑机器学习的 Job , 用来做异常检测

《3.》Tribe Node (未来可能会被淘汰)

         【5.3 开始使用 Cross Cluster Search 】,Tribe Node  连接到不同的 Elasticsearch 集群,

          并且支持将这些集群当成一个单独的集群处理。

7. 配置节点类型

《1.》开发环境中一个节点可以承担多种角色

《2.》生产环境中,可以设置单一的角色的节点(dedicated node)

         性能更好,职责明确,不同的节点可以配置不同的机器!

8. 分片 (Primary Shard & Replica Shard)

《1.》主分片 ,用以解决数据水平扩展的问题。通过主分片,可以将数据分布到集群内的所有节点之上。

        ① 一个分片是一个运行的 Lucene 的实例

        ② 主分片数量在索引创建时指定 ,后续不允许修改,除非 Reindex

《2.》副本分片,用以解决数据高可用的问题。分片是主分片的拷贝

        ① 副本分片数目,可以动态的调整

        ② 增加副本数,还可以在一定程度上提高服务的可用性(读取的吞吐量)

《3.》一个三节点的集群中,blogs 索引的分片分布情况

9. 分片的设定

         对于生产环境中分片的设定,需要提前做好容量规划

         ① 分片数目设置过小

              * 导致后续无法增加节点实现水平扩展

              * 单个分片的数据量太大, 导致数据重新分配耗时

        ② 分片数目设置过大

              * 7.0 开始,默认主分片设置成 1 ,解决了 over-sharding 的问题

              * 影响搜索结果的相关性打分,影响统计结果的准确性

              * 单个节点上过多的分片,会导致资源浪费,同时也会影响性能

10. 查看集群的健康状况

http://localhost:9200/_cluster/health

《1.》Green - 主分片与副本都正常分配

《2.》Yellow - 主分片全部正常分配,有副本分片未能正常分配

《3.》Red - 有主分片未能分配

         eg. 当服务器的磁盘容量超过 85% 时,去创建了一个新的索引。

《4.》

//查看集群的健康状况
GET _cluster/health

//查看node的信息
GET _cat/nodes

//查看shards信息
GET _cat/shards

CAT Nodes API : https://www.elastic.co/guide/en/elasticsearch/reference/7.1/cat-nodes.html

Cluster APIS : https://www.elastic.co/guide/en/elasticsearch/reference/7.1/cluster.html

CAT Shards API : https://www.elastic.co/guide/en/elasticsearch/reference/7.1/cat-shards.html

三、文档的基本操作

1.CRUD

2.Create 一个文档

《1.》支持自动生成文档 Id 和指定文档 Id 两种方式

《2.》通过调用 “POST  users/_doc” , 系统会自动生成 document Id

《3.》使用 HTTP PUT  users/_doc/1 创建时,URI 中显示指定_doc, 此时如果该 Id 的文档已经存在,操作失败

《4.》举例:

 

3.GET 一个文档

《1.》找到文档,返回 HTTP 200

          文档元信息:

          ① _index/_type/

          ② 版本信息,同一个 Id 的文档,即使被删除,Version 号也不会不断增加

          ③ _source 中默认包含了文档的所有原始信息

《2.》找不到文档,返回 HTTP 404

 

4.Index 文档

《1.》Index 和 Create 不一样的地方:如果文档不存在,就索引新的文档。

         否则现有的文档会被删除,新的文档被索引。版本信息 +1

 

5.Update 文档

《1.》Update 方法不会删除原来的文档,而是实现真正的数据更新

《2.》注意使用的是 POST 方法,要更新的内容是放在 doc 中。

6.Bulk API

《1.》支持在一次 API 调用中,对不同的索引进行操作

《2.》支持四种类型的操作

          Index Create Update Delete

《3.》操作中单条操作失败,并不会影响其他的操作

《4.》返回结果包含了每一条操作执行的结果

eg.:https://www.elastic.co/guide/en/elasticsearch/reference/7.1/docs-bulk.html

 

《5.》批量读取 - mget

批量读取,可以减少网络连接所产生的开销,提高性能。

《6.》批量查询 - msearch

//msearch 操作
POST kibana_sample_data_ecommerce/_msearch
{}
{"query" : {"match_all" : {}},"size" : 1}
{"index" : "kibana_sample_data_flights"}
{"query" : {"match_all" : {}},"size" : 2}

7. 常见错误返回

Document API : https://www.elastic.co/guide/en/elasticsearch/reference/7.1/docs.html

四、倒排索引介绍

倒排索引理解:

https://my.oschina.net/hanchao/blog/3053367

https://zh.wikipedia.org/wiki/%E5%80%92%E6%8E%92%E7%B4%A2%E5%BC%95

https://www.elastic.co/guide/cn/elasticsearch/guide/current/inverted-index.html

1. 正排索引和倒排索引

2. 倒排索引的核心组成

《1.》单词词典 (Term Dictionary)

          记录所有文档的单词,记录单词到倒排列表的关联关系。

          单词词典一般比较大,可以通过 B + 树或哈希拉链法实现,以满足高性能的插入与查询。

《2.》倒排列表(Posting List)

          - 记录了单词对应的文档结合,由倒排索引项组成

         倒排索引项(Posting)

         ① 文档 Id

         ② 词频 TF - 该单词在文档中出现的次数,用于相关性评分

         ③ 位置(Position) - 单词在文档中分词的位置。用于语句搜索(phrase query)

         ④ 偏移(Offset) - 记录单词的开始结束位置,实现高亮显示

《3.》例子 - Elasticsearch

3. 倒排索引说明

 

 

五、通过 Analyzer 进行分词

1.Analysis 与 Analyzer

《1.》Analysis - 文本分析是把全文本转换成一系列单词(term | token)的过程,也叫分词

《2.》Analysis 是通过 Analyzer 来实现的

         可使用 Elasticsearch 内置的分析器 | 或者按需定制化分析器

《3.》除了在数据写入时转换词条,匹配 Query 语句时候也需要用相同的分析器对查询语句进行分析

eg:

2.Analyzer 的组成

3.Elasticsearch 的内置分词器

4. 使用_analyzer API

《1.》直接指定 Analyzer 进行测试

//直接使用指定的Analyzer进行测试
GET /_analyze
{
  "analyzer": "standard",
  "text" : "Masterting Elasticsearch, elasticsearch in Action"
}

结果:

{
  "tokens" : [
    {
      "token" : "masterting",
      "start_offset" : 0,
      "end_offset" : 10,
      "type" : "<ALPHANUM>",
      "position" : 0
    },
    {
      "token" : "elasticsearch",
      "start_offset" : 11,
      "end_offset" : 24,
      "type" : "<ALPHANUM>",
      "position" : 1
    },
    {
      "token" : "elasticsearch",
      "start_offset" : 26,
      "end_offset" : 39,
      "type" : "<ALPHANUM>",
      "position" : 2
    },
    {
      "token" : "in",
      "start_offset" : 40,
      "end_offset" : 42,
      "type" : "<ALPHANUM>",
      "position" : 3
    },
    {
      "token" : "action",
      "start_offset" : 43,
      "end_offset" : 49,
      "type" : "<ALPHANUM>",
      "position" : 4
    }
  ]
}

《2.》指定索引的字段进行测试

//指定索引的字段进行测试
POST users/_analyze
{
  "field": "message",
  "text" : "Mastering Elasticsearch"
}

结果:

{
  "tokens" : [
    {
      "token" : "mastering",
      "start_offset" : 0,
      "end_offset" : 9,
      "type" : "<ALPHANUM>",
      "position" : 0
    },
    {
      "token" : "elasticsearch",
      "start_offset" : 10,
      "end_offset" : 23,
      "type" : "<ALPHANUM>",
      "position" : 1
    }
  ]
}

《3.》自定义分词器进行测试

//使用自定义分词器进行测试
POST /_analyze
{
  "tokenizer": "standard",
  "filter": ["lowercase"],
  "text" : "Mastering Elastcisearch HANCHAO"
}

结果:

{
  "tokens" : [
    {
      "token" : "mastering",
      "start_offset" : 0,
      "end_offset" : 9,
      "type" : "<ALPHANUM>",
      "position" : 0
    },
    {
      "token" : "elastcisearch",
      "start_offset" : 10,
      "end_offset" : 23,
      "type" : "<ALPHANUM>",
      "position" : 1
    },
    {
      "token" : "hanchao",
      "start_offset" : 24,
      "end_offset" : 31,
      "type" : "<ALPHANUM>",
      "position" : 2
    }
  ]
}

5.Standard Analyzer

举例:

#standard
GET _analyze
{
  "analyzer": "standard",
  "text": "2 running Quick brown-foxes leap over lazy dogs in the summer evening."
}

结果:

{
  "tokens" : [
    {
      "token" : "2",
      "start_offset" : 0,
      "end_offset" : 1,
      "type" : "<NUM>",
      "position" : 0
    },
    {
      "token" : "running",
      "start_offset" : 2,
      "end_offset" : 9,
      "type" : "<ALPHANUM>",
      "position" : 1
    },
    {
      "token" : "quick",
      "start_offset" : 10,
      "end_offset" : 15,
      "type" : "<ALPHANUM>",
      "position" : 2
    },
    {
      "token" : "brown",
      "start_offset" : 16,
      "end_offset" : 21,
      "type" : "<ALPHANUM>",
      "position" : 3
    },
    {
      "token" : "foxes",
      "start_offset" : 22,
      "end_offset" : 27,
      "type" : "<ALPHANUM>",
      "position" : 4
    },
    {
      "token" : "leap",
      "start_offset" : 28,
      "end_offset" : 32,
      "type" : "<ALPHANUM>",
      "position" : 5
    },
    {
      "token" : "over",
      "start_offset" : 33,
      "end_offset" : 37,
      "type" : "<ALPHANUM>",
      "position" : 6
    },
    {
      "token" : "lazy",
      "start_offset" : 38,
      "end_offset" : 42,
      "type" : "<ALPHANUM>",
      "position" : 7
    },
    {
      "token" : "dogs",
      "start_offset" : 43,
      "end_offset" : 47,
      "type" : "<ALPHANUM>",
      "position" : 8
    },
    {
      "token" : "in",
      "start_offset" : 48,
      "end_offset" : 50,
      "type" : "<ALPHANUM>",
      "position" : 9
    },
    {
      "token" : "the",
      "start_offset" : 51,
      "end_offset" : 54,
      "type" : "<ALPHANUM>",
      "position" : 10
    },
    {
      "token" : "summer",
      "start_offset" : 55,
      "end_offset" : 61,
      "type" : "<ALPHANUM>",
      "position" : 11
    },
    {
      "token" : "evening",
      "start_offset" : 62,
      "end_offset" : 69,
      "type" : "<ALPHANUM>",
      "position" : 12
    }
  ]
}

6.Simple Analyzer

按照非字母切分(符号被过滤),小写处理。

#simpe analyzer
GET _analyze
{
  "analyzer": "simple",
  "text": "2 running Quick brown-foxes leap over lazy dogs in the summer evening."
}

结果:

{
  "tokens" : [
    {
      "token" : "running",
      "start_offset" : 2,
      "end_offset" : 9,
      "type" : "word",
      "position" : 0
    },
    {
      "token" : "quick",
      "start_offset" : 10,
      "end_offset" : 15,
      "type" : "word",
      "position" : 1
    },
    {
      "token" : "brown",
      "start_offset" : 16,
      "end_offset" : 21,
      "type" : "word",
      "position" : 2
    },
    {
      "token" : "foxes",
      "start_offset" : 22,
      "end_offset" : 27,
      "type" : "word",
      "position" : 3
    },
    {
      "token" : "leap",
      "start_offset" : 28,
      "end_offset" : 32,
      "type" : "word",
      "position" : 4
    },
    {
      "token" : "over",
      "start_offset" : 33,
      "end_offset" : 37,
      "type" : "word",
      "position" : 5
    },
    {
      "token" : "lazy",
      "start_offset" : 38,
      "end_offset" : 42,
      "type" : "word",
      "position" : 6
    },
    {
      "token" : "dogs",
      "start_offset" : 43,
      "end_offset" : 47,
      "type" : "word",
      "position" : 7
    },
    {
      "token" : "in",
      "start_offset" : 48,
      "end_offset" : 50,
      "type" : "word",
      "position" : 8
    },
    {
      "token" : "the",
      "start_offset" : 51,
      "end_offset" : 54,
      "type" : "word",
      "position" : 9
    },
    {
      "token" : "summer",
      "start_offset" : 55,
      "end_offset" : 61,
      "type" : "word",
      "position" : 10
    },
    {
      "token" : "evening",
      "start_offset" : 62,
      "end_offset" : 69,
      "type" : "word",
      "position" : 11
    }
  ]
}

7.Whitespace Analyzer

#whitespace
GET _analyze
{
  "analyzer": "whitespace",
  "text": "2 running Quick brown-foxes leap over lazy dogs in the summer evening."
}

结果:

{
  "tokens" : [
    {
      "token" : "2",
      "start_offset" : 0,
      "end_offset" : 1,
      "type" : "word",
      "position" : 0
    },
    {
      "token" : "running",
      "start_offset" : 2,
      "end_offset" : 9,
      "type" : "word",
      "position" : 1
    },
    {
      "token" : "Quick",
      "start_offset" : 10,
      "end_offset" : 15,
      "type" : "word",
      "position" : 2
    },
    {
      "token" : "brown-foxes",
      "start_offset" : 16,
      "end_offset" : 27,
      "type" : "word",
      "position" : 3
    },
    {
      "token" : "leap",
      "start_offset" : 28,
      "end_offset" : 32,
      "type" : "word",
      "position" : 4
    },
    {
      "token" : "over",
      "start_offset" : 33,
      "end_offset" : 37,
      "type" : "word",
      "position" : 5
    },
    {
      "token" : "lazy",
      "start_offset" : 38,
      "end_offset" : 42,
      "type" : "word",
      "position" : 6
    },
    {
      "token" : "dogs",
      "start_offset" : 43,
      "end_offset" : 47,
      "type" : "word",
      "position" : 7
    },
    {
      "token" : "in",
      "start_offset" : 48,
      "end_offset" : 50,
      "type" : "word",
      "position" : 8
    },
    {
      "token" : "the",
      "start_offset" : 51,
      "end_offset" : 54,
      "type" : "word",
      "position" : 9
    },
    {
      "token" : "summer",
      "start_offset" : 55,
      "end_offset" : 61,
      "type" : "word",
      "position" : 10
    },
    {
      "token" : "evening.",
      "start_offset" : 62,
      "end_offset" : 70,
      "type" : "word",
      "position" : 11
    }
  ]
}

8.Stop Analyzer

小写处理:停用词过滤(the , a  , is)

# stop analyzer
GET _analyze
{
  "analyzer": "stop",
  "text": "2 running Quick brown-foxes leap over lazy dogs in the summer evening."
}

结果:

{
  "tokens" : [
    {
      "token" : "running",
      "start_offset" : 2,
      "end_offset" : 9,
      "type" : "word",
      "position" : 0
    },
    {
      "token" : "quick",
      "start_offset" : 10,
      "end_offset" : 15,
      "type" : "word",
      "position" : 1
    },
    {
      "token" : "brown",
      "start_offset" : 16,
      "end_offset" : 21,
      "type" : "word",
      "position" : 2
    },
    {
      "token" : "foxes",
      "start_offset" : 22,
      "end_offset" : 27,
      "type" : "word",
      "position" : 3
    },
    {
      "token" : "leap",
      "start_offset" : 28,
      "end_offset" : 32,
      "type" : "word",
      "position" : 4
    },
    {
      "token" : "over",
      "start_offset" : 33,
      "end_offset" : 37,
      "type" : "word",
      "position" : 5
    },
    {
      "token" : "lazy",
      "start_offset" : 38,
      "end_offset" : 42,
      "type" : "word",
      "position" : 6
    },
    {
      "token" : "dogs",
      "start_offset" : 43,
      "end_offset" : 47,
      "type" : "word",
      "position" : 7
    },
    {
      "token" : "summer",
      "start_offset" : 55,
      "end_offset" : 61,
      "type" : "word",
      "position" : 10
    },
    {
      "token" : "evening",
      "start_offset" : 62,
      "end_offset" : 69,
      "type" : "word",
      "position" : 11
    }
  ]
}

9.Keyword Analyzer★

10.Pattern Analyzer

#pattern analyzer
GET _analyze
{
  "analyzer": "pattern",
  "text": "2 running Quick brown-foxes leap over lazy dogs in the summer evening."
}

结果:

{
  "tokens" : [
    {
      "token" : "2",
      "start_offset" : 0,
      "end_offset" : 1,
      "type" : "word",
      "position" : 0
    },
    {
      "token" : "running",
      "start_offset" : 2,
      "end_offset" : 9,
      "type" : "word",
      "position" : 1
    },
    {
      "token" : "quick",
      "start_offset" : 10,
      "end_offset" : 15,
      "type" : "word",
      "position" : 2
    },
    {
      "token" : "brown",
      "start_offset" : 16,
      "end_offset" : 21,
      "type" : "word",
      "position" : 3
    },
    {
      "token" : "foxes",
      "start_offset" : 22,
      "end_offset" : 27,
      "type" : "word",
      "position" : 4
    },
    {
      "token" : "leap",
      "start_offset" : 28,
      "end_offset" : 32,
      "type" : "word",
      "position" : 5
    },
    {
      "token" : "over",
      "start_offset" : 33,
      "end_offset" : 37,
      "type" : "word",
      "position" : 6
    },
    {
      "token" : "lazy",
      "start_offset" : 38,
      "end_offset" : 42,
      "type" : "word",
      "position" : 7
    },
    {
      "token" : "dogs",
      "start_offset" : 43,
      "end_offset" : 47,
      "type" : "word",
      "position" : 8
    },
    {
      "token" : "in",
      "start_offset" : 48,
      "end_offset" : 50,
      "type" : "word",
      "position" : 9
    },
    {
      "token" : "the",
      "start_offset" : 51,
      "end_offset" : 54,
      "type" : "word",
      "position" : 10
    },
    {
      "token" : "summer",
      "start_offset" : 55,
      "end_offset" : 61,
      "type" : "word",
      "position" : 11
    },
    {
      "token" : "evening",
      "start_offset" : 62,
      "end_offset" : 69,
      "type" : "word",
      "position" : 12
    }
  ]
}

11.Language Analyzer

选择不同国家的语音分词的结果是不同的!!

举例:

#english
GET _analyze
{
  "analyzer": "english",
  "text": "2 running Quick brown-foxes leap over lazy dogs in the summer evening."
}

结果:

{
  "tokens" : [
    {
      "token" : "2",
      "start_offset" : 0,
      "end_offset" : 1,
      "type" : "<NUM>",
      "position" : 0
    },
    {
      "token" : "run",
      "start_offset" : 2,
      "end_offset" : 9,
      "type" : "<ALPHANUM>",
      "position" : 1
    },
    {
      "token" : "quick",
      "start_offset" : 10,
      "end_offset" : 15,
      "type" : "<ALPHANUM>",
      "position" : 2
    },
    {
      "token" : "brown",
      "start_offset" : 16,
      "end_offset" : 21,
      "type" : "<ALPHANUM>",
      "position" : 3
    },
    {
      "token" : "fox",
      "start_offset" : 22,
      "end_offset" : 27,
      "type" : "<ALPHANUM>",
      "position" : 4
    },
    {
      "token" : "leap",
      "start_offset" : 28,
      "end_offset" : 32,
      "type" : "<ALPHANUM>",
      "position" : 5
    },
    {
      "token" : "over",
      "start_offset" : 33,
      "end_offset" : 37,
      "type" : "<ALPHANUM>",
      "position" : 6
    },
    {
      "token" : "lazi",
      "start_offset" : 38,
      "end_offset" : 42,
      "type" : "<ALPHANUM>",
      "position" : 7
    },
    {
      "token" : "dog",
      "start_offset" : 43,
      "end_offset" : 47,
      "type" : "<ALPHANUM>",
      "position" : 8
    },
    {
      "token" : "summer",
      "start_offset" : 55,
      "end_offset" : 61,
      "type" : "<ALPHANUM>",
      "position" : 11
    },
    {
      "token" : "even",
      "start_offset" : 62,
      "end_offset" : 69,
      "type" : "<ALPHANUM>",
      "position" : 12
    }
  ]
}

12. 中文分词 - ICU Analyzer

《1.》中文句子,切分成一个一个词(不是一个个字)

《2.》英文中,单词有自然的空格作为分隔

《3.》一句中文,在不同的上下文,有不同的理解

        eg: 这个苹果,不大好吃  =》这个苹果 , 不大,好吃

具体安装方式,参考:https://my.oschina.net/hanchao/blog/3070695

举例:

POST _analyze
{
  "analyzer": "standard",
  "text": "他说的确实在理”"
}

##################结果 ####################3
{
  "tokens" : [
    {
      "token" : "他",
      "start_offset" : 0,
      "end_offset" : 1,
      "type" : "<IDEOGRAPHIC>",
      "position" : 0
    },
    {
      "token" : "说",
      "start_offset" : 1,
      "end_offset" : 2,
      "type" : "<IDEOGRAPHIC>",
      "position" : 1
    },
    {
      "token" : "的",
      "start_offset" : 2,
      "end_offset" : 3,
      "type" : "<IDEOGRAPHIC>",
      "position" : 2
    },
    {
      "token" : "确",
      "start_offset" : 3,
      "end_offset" : 4,
      "type" : "<IDEOGRAPHIC>",
      "position" : 3
    },
    {
      "token" : "实",
      "start_offset" : 4,
      "end_offset" : 5,
      "type" : "<IDEOGRAPHIC>",
      "position" : 4
    },
    {
      "token" : "在",
      "start_offset" : 5,
      "end_offset" : 6,
      "type" : "<IDEOGRAPHIC>",
      "position" : 5
    },
    {
      "token" : "理",
      "start_offset" : 6,
      "end_offset" : 7,
      "type" : "<IDEOGRAPHIC>",
      "position" : 6
    }
  ]
}

icu-analyzer 的例子:

POST _analyze
{
  "analyzer": "icu_analyzer",
  "text": "他说的确实在理”"
}

############################### 结果 ###########################
{
  "tokens" : [
    {
      "token" : "他",
      "start_offset" : 0,
      "end_offset" : 1,
      "type" : "<IDEOGRAPHIC>",
      "position" : 0
    },
    {
      "token" : "说的",
      "start_offset" : 1,
      "end_offset" : 3,
      "type" : "<IDEOGRAPHIC>",
      "position" : 1
    },
    {
      "token" : "确实",
      "start_offset" : 3,
      "end_offset" : 5,
      "type" : "<IDEOGRAPHIC>",
      "position" : 2
    },
    {
      "token" : "在",
      "start_offset" : 5,
      "end_offset" : 6,
      "type" : "<IDEOGRAPHIC>",
      "position" : 3
    },
    {
      "token" : "理",
      "start_offset" : 6,
      "end_offset" : 7,
      "type" : "<IDEOGRAPHIC>",
      "position" : 4
    }
  ]
}
POST _analyze
{
  "analyzer": "icu_analyzer",
  "text": "这个苹果不大好吃”"
}

############## 结果 ###################
{
  "tokens" : [
    {
      "token" : "这个",
      "start_offset" : 0,
      "end_offset" : 2,
      "type" : "<IDEOGRAPHIC>",
      "position" : 0
    },
    {
      "token" : "苹果",
      "start_offset" : 2,
      "end_offset" : 4,
      "type" : "<IDEOGRAPHIC>",
      "position" : 1
    },
    {
      "token" : "不大",
      "start_offset" : 4,
      "end_offset" : 6,
      "type" : "<IDEOGRAPHIC>",
      "position" : 2
    },
    {
      "token" : "好吃",
      "start_offset" : 6,
      "end_offset" : 8,
      "type" : "<IDEOGRAPHIC>",
      "position" : 3
    }
  ]
}

《4.》更多的中文分词器

① IK 

     支持自定义词库,支持热更新分词词典

     https://github.com/medcl/elasticsearch-analysis-ik

② THULAC

     THU Lexucal Analyzer for Chinese ,清华大学自然语言处理和社会人文计算实验室的一套中文分词器

     https://github.com/microbun/elasticsearch-thulac-plugin

《5.》参考文档

https://www.elastic.co/guide/en/elasticsearch/reference/7.1/indices-analyze.html

https://www.elastic.co/guide/en/elasticsearch/reference/current/analyzer-anatomy.html

 

Elasticsearch 简单学习 5: 入门学习 - 2

Elasticsearch 简单学习 5: 入门学习 - 2

一、基础说明

1.Search API

《1.》URI Search 

          在 URL 中使用查询参数

《2.》Request Body Search

         使用 Elasticsearch 提供的,基于 JSON 格式的更加完备的 Query Domain Specific Language (DSL)

2. 指定查询的索引

3.URI 查询

4.Request Body

5.search Response

6. 搜索的相关性 Relevance

 

假设我们手上有 60 个正样本,40 个负样本,我们要找出所有的正样本,系统查找出 50 个,其中只有 40 个是真正的正样本,计算上述各指标。

  • TP(true positives): 将正类预测为正类数 40
  • FN(false negatives): 将正类预测为负类数 20
  • FP(false positives): 将负类预测为正类数 10
  • TN(true negatives): 将负类预测为负类数 30

准确率 (accuracy) = 预测对的 / 所有 = (TP+TN)/(TP+FN+FP+TN) = 70%
精确率 (precision) = TP/(TP+FP) = 80%
召回率 (recall) = TP/(TP+FN) = 2/3

7. 参考文档

https://www.elastic.co/guide/en/elasticsearch/reference/7.1/search-search.html

https://searchenginewatch.com/sew/news/2065080/search-engines-101

https://www.entrepreneur.com/article/176398

https://baike.baidu.com/item/%E6%90%9C%E7%B4%A2%E5%BC%95%E6%93%8E%E5%8F%91%E5%B1%95%E5%8F%B2/2422574

https://www.searchtechnologies.com/meaning-of-relevancy

二、URI Search 详解

1. 说明

2. 指定字段 & 泛查询

#基本查询
GET /movies/_search?q=2012&df=title&sort=year:desc&from=0&size=10&timeout=1s

################# 结果 #####################
{
  "took" : 28,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [
      {
        "_index" : "movies",
        "_type" : "_doc",
        "_id" : "105254",
        "_score" : null,
        "_source" : {
          "id" : "105254",
          "title" : "Crystal Fairy & the Magical Cactus and 2012",
          "year" : 2013,
          "@version" : "1",
          "genre" : [
            "Adventure",
            "Comedy"
          ]
        },
        "sort" : [
          2013
        ]
      },
      {
        "_index" : "movies",
        "_type" : "_doc",
        "_id" : "72378",
        "_score" : null,
        "_source" : {
          "id" : "72378",
          "title" : "2012",
          "year" : 2009,
          "@version" : "1",
          "genre" : [
            "Action",
            "Drama",
            "Sci-Fi",
            "Thriller"
          ]
        },
        "sort" : [
          2009
        ]
      }
    ]
  }
}

例子 2:profile 显示是 termQuery

#带profile ,指定df字段为title =>>查询title中含有2012的数据
GET /movies/_search?q=2012&df=title
{
	"profile":"true"
}

################### 返回的结果 #########################
{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 11.303033,
    "hits" : [
      {
        "_index" : "movies",
        "_type" : "_doc",
        "_id" : "72378",
        "_score" : 11.303033,
        "_source" : {
          "id" : "72378",
          "title" : "2012",
          "year" : 2009,
          "@version" : "1",
          "genre" : [
            "Action",
            "Drama",
            "Sci-Fi",
            "Thriller"
          ]
        }
      },
      {
        "_index" : "movies",
        "_type" : "_doc",
        "_id" : "105254",
        "_score" : 5.2497,
        "_source" : {
          "id" : "105254",
          "title" : "Crystal Fairy & the Magical Cactus and 2012",
          "year" : 2013,
          "@version" : "1",
          "genre" : [
            "Adventure",
            "Comedy"
          ]
        }
      }
    ]
  },
  "profile" : {
    "shards" : [
      {
        "id" : "[IFYvrFIHTDiAFmTdfyB9AQ][movies][0]",
        "searches" : [
          {
            "query" : [
              {
                "type" : "TermQuery",
                "description" : "title:2012",
                "time_in_nanos" : 95582,
                "breakdown" : {
                  "set_min_competitive_score_count" : 0,
                  "match_count" : 0,
                  "shallow_advance_count" : 0,
                  "set_min_competitive_score" : 0,
                  "next_doc" : 5548,
                  "match" : 0,
                  "next_doc_count" : 3,
                  "score_count" : 2,
                  "compute_max_score_count" : 0,
                  "compute_max_score" : 0,
                  "advance" : 0,
                  "advance_count" : 0,
                  "score" : 5120,
                  "build_scorer_count" : 3,
                  "create_weight" : 59732,
                  "shallow_advance" : 0,
                  "create_weight_count" : 1,
                  "build_scorer" : 25173
                }
              }
            ],
            "rewrite_time" : 2133,
            "collector" : [
              {
                "name" : "CancellableCollector",
                "reason" : "search_cancelled",
                "time_in_nanos" : 20055,
                "children" : [
                  {
                    "name" : "SimpleTopScoreDocCollector",
                    "reason" : "search_top_hits",
                    "time_in_nanos" : 13227
                  }
                ]
              }
            ]
          }
        ],
        "aggregations" : [ ]
      }
    ]
  }
}

例子 3:泛查询 - 性能低

#泛查询,正对_all,所有字段
GET /movies/_search?q=2012
{
	"profile":"true"
}

3.Term & Phrase

例子 1:

#使用引号,Phrase查询
GET /movies/_search?q=title:"Beautiful Mind"
{
	"profile":"true"
}

例子 2:

#查找美丽心灵, Mind为泛查询
GET /movies/_search?q=title:Beautiful Mind
{
	"profile":"true"
}

例子 3:

#分组,Bool查询
GET /movies/_search?q=title:(Beautiful Mind)
{
	"profile":"true"
}

4. 布尔操作

例子 1:

# 查找美丽心灵
GET /movies/_search?q=title:(Beautiful AND Mind)
{
	"profile":"true"
}

例子 2:

# 查找美丽心灵
GET /movies/_search?q=title:(Beautiful NOT Mind)
{
	"profile":"true"
}

例子 3:

# 查找美丽心灵 ,%2B代表+
GET /movies/_search?q=title:(Beautiful %2BMind)
{
	"profile":"true"
}

5. 范围查询和算术符号

例子 1:

#范围查询 , 区间写法
GET /movies/_search?q=year:>=1980
{
  "profile": "true"
}

 

例子 2:

#范围查询 ,区间写法
GET /movies/_search?q=title:beautiful AND year:[2002 TO 2018%7D
{
	"profile":"true"
}

6. 通配符查询 & 模糊查询

例子 1:

#通配符查询
GET /movies/_search?q=title:b*
{
	"profile":"true"
}

例子 2:

//模糊匹配&近似度匹配
GET /movies/_search?q=title:beautifl~1
{
	"profile":"true"
}

例子 3:

GET /movies/_search?q=title:"Lord Rings"~2
{
	"profile":"true"
}

推荐阅读:

  • https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-uri-request.html
  • https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-search.html

三、Request Body 和 DSL

1.Request Body Search

例子 1:

ignore_unavailable=true,可以忽略尝试访问不存在的索引 “404_idx” 导致的报错

POST /movies,404_idx/_search?ignore_unavailable=true
{
  "profile": "true",
  "query": {
      "match_all": {}
  }
}
#From从0开始,默认返回10个结果
POST /kibana_sample_data_ecommerce/_search
{
  "from": 10, 
  "size": 20,
  "query": {
    "match_all": {}
  }
}
#对日期排序
POST kibana_sample_data_ecommerce/_search
{
  "sort":[{"order_date":"desc"}],
  "query":{
    "match_all": {}
  }
}

说明:最好在 “数字型” 与 “日期型” 字段上排序

例子 2:

#source filtering
POST kibana_sample_data_ecommerce/_search
{
  "_source":["order_date"],
  "query":{
    "match_all": {}
  }
}

 

例子 3:

#脚本字段-订单中有不同的汇率,需要结合汇率对订单价格进行排序
#painless是ES的脚本
GET kibana_sample_data_ecommerce/_search
{
  "script_fields": {
    "new_field": {
      "script": {
        "lang": "painless",
        "source": "doc[''order_date''].value+''hello''"
      }
    }
  },
  "query": {
    "match_all": {}
  }
}

例子 4:

#或的关系
POST movies/_search
{
  "query": {
    "match": {
      "title": "last christmas"
    }
  }
}

#与的关系
POST movies/_search
{
  "query": {
    "match": {
      "title": {
        "query": "last christmas",
        "operator": "and"
      }
    }
  }
}

#match_phrase查询
POST movies/_search
{
  "query": {
    "match_phrase": {
      "title":{
        "query": "one love"

      }
    }
  }
}

#slop的用法参考官网
POST movies/_search
{
  "query": {
    "match_phrase": {
      "title":{
        "query": "one love",
        "slop": 1

      }
    }
  }
}

https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-uri-request.html

https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-search.html

2.Query String Query

类似 URI 的 Query

#插入用户赵一花
PUT /users/_doc/1
{
  "name":"Zhao YiHua",
  "about":"java, golang, node, swift, elasticsearch"
}

#插入用户李一花
PUT /users/_doc/2
{
  "name":"Li YiHua",
  "about":"java, golang, node, swift, elasticsearch"
}

#支持AND查询
POST users/_search
{
  "query": {
    "query_string": {
      "default_field": "name",
      "query": "Zhao AND YiHua"
    }
  }
}

#支持分组和多字段
POST users/_search
{
  "query": {
    "query_string": {
      "fields":["name","about"],
      "query": "(Zhao AND YiHua) OR (Java AND Elasticsearch)"
    }
  }
}

==============================================
#default_field相当于URI查询的df字段
GET /movies/_search
{
	"profile": true,
	"query":{
		"query_string":{
			"default_field": "title",
			"query": "Beafiful AND Mind"
		}
	}
}

# 多fields
GET /movies/_search
{
	"profile": true,
	"query":{
		"query_string":{
			"fields":[
				"title",
				"year"
			],
			"query": "2012"
		}
	}
}

3.Simple Query String Query

#Simple Query 默认的operator是 Or
POST users/_search
{
  "query": {
    "simple_query_string": {
      "query": "Zhao AND YiHua",
      "fields": ["name"]
    }
  }
}

#支持AND
POST users/_search
{
  "query": {
    "simple_query_string": {
      "query": "Zhao YiHua",
      "fields": ["name"],
      "default_operator": "AND"
    }
  }
}

#####
GET /movies/_search
{
	"profile":true,
	"query":{
		"simple_query_string":{
			"query":"Beautiful +mind",
			"fields":["title"]
		}
	}
}

四、Dynamic Mapping 和常见的字段类型

1. 什么是 Mapping?

2. 字段的数据类型?

3. 什么是 Dynamic Mapping?

4. 类型的自动识别?

#写入文档,查看 Mapping
PUT mapping_test/_doc/1
{
  "firstName":"Chan",
  "lastName": "Jackie",
  "loginDate":"2018-07-24T10:29:48.103Z"
}

#查看 Mapping文件 ,firstName和lastName设置成text,loginDate设置成了Date
GET mapping_test/_mapping

#Delete index
DELETE mapping_test

#dynamic mapping,推断字段的类型
PUT mapping_test/_doc/1
{
    "uid" : "123",
    "isVip" : false,
    "isAdmin": "true",
    "age":19,
    "heigh":180
}

#查看 Dynamic ,age,heigh设置成了long ,isVip设置成了boolean,isAdmin设置成text,uid设置成text
GET mapping_test/_mapping

5. 能否修改 Mapping 的字段类型?

#默认Mapping支持dynamic,写入的文档中加入新的字段
PUT dynamic_mapping_test/_doc/1
{
  "newField":"someValue"
}

#该字段可以被搜索,数据也在_source中出现
POST dynamic_mapping_test/_search
{
  "query":{
    "match":{
      "newField":"someValue"
    }
  }
}


===================================================
#修改为dynamic false
PUT dynamic_mapping_test/_mapping
{
  "dynamic": false
}

#新增 anotherField
PUT dynamic_mapping_test/_doc/10
{
  "anotherField":"someValue"
}

#该字段不可以被搜索,【match_all是可以的】应为dynamic已经被设置为false
POST dynamic_mapping_test/_search
{
  "query":{
    "match":{
      "anotherField":"someValue"
    }
  }
}

get dynamic_mapping_test/_doc/10


============================================
#修改为strict
PUT dynamic_mapping_test/_mapping
{
  "dynamic": "strict"
}

#写入数据出错,HTTP Code 400
PUT dynamic_mapping_test/_doc/12
{
  "lastField":"value"
}

#删除索引!!
DELETE dynamic_mapping_test

阅读:https://www.elastic.co/guide/en/elasticsearch/reference/7.1/dynamic-mapping.html

五、★显式 Mapping 的设置与常见参数介绍★

1. 如何显式顶一个一个 Mapping?

2. 自定义 Mapping 的一些建议

《1.》为了减少输入的工作量,减少出错概率,可以依照如下步骤

         ① 创建一个临时的 Index , 写入一些样本数据

         ② 通过访问 Mapping API 获得该临时文件的动态 Mapping 定义

         ③ 修改后用,使用该配置创建你的索引

         ④ 删除临时索引

3. 控制当前字段是否被索引

4.Index Options

5.null_value

6.copy_to 设置

7. 数组类型

DELETE users

#自定义mapping ,mobile设置为false,不为被搜索,设置 index 为 false
PUT users
{
    "mappings" : {
      "properties" : {
        "firstName" : {
          "type" : "text"
        },
        "lastName" : {
          "type" : "text"
        },
        "mobile" : {
          "type" : "text",
          "index": false
        }
      }
    }
}

#查看mapping
GET users/_mapping

#添加数据一
PUT users/_doc/1
{
  "firstName":"Zhao",
  "lastName": "YiDan",
  "mobile": "1358174623"
}

//搜索--提示错误!!
POST /users/_search
{
  "query": {
    "match": {
      "mobile":"1358174623"
    }
  }
}

########################## 
#设定Null_value
DELETE users
PUT users
{
    "mappings" : {
      "properties" : {
        "firstName" : {
          "type" : "text"
        },
        "lastName" : {
          "type" : "text"
        },
        "mobile" : {
          "type" : "keyword",
          "null_value": "NULL"
        }

      }
    }
}

#添加测试数据
PUT users/_doc/1
{
  "firstName":"Zhao",
  "lastName": "YiDan",
  "mobile": null
}

#测试测试数据2
PUT users/_doc/2
{
  "firstName":"Zhao2",
  "lastName": "YiDan2"
}

#搜索mobole为null的数据,而不是不存在的数据
GET users/_search
{
  "query": {
    "match": {
      "mobile":"NULL"
    }
  }
}

######################## 设置Copy to ############
DELETE users
#设置Mapping
PUT users
{
  "mappings": {
    "properties": {
      "firstName":{
        "type": "text",
        "copy_to": "fullName"
      },
      "lastName":{
        "type": "text",
        "copy_to": "fullName"
      }
    }
  }
}

#添加测试数据
PUT users/_doc/1
{
  "firstName":"Zhao",
  "lastName": "YiDan"
}


#搜索多个字段中内容,但是_source中没有fullName
GET users/_search?q=fullName:(Zhao YiDan)

POST users/_search
{
  "query": {
    "match": {
       "fullName":{
        "query": "Zhao YiDan",
        "operator": "and"
      }
    }
  }
}

############# 数组类型 ##############
DELETE users
#设置数组类型
PUT users/_doc/1
{
  "name":"onebird",
  "interests":"reading"
}

#添加测试数据
PUT users/_doc/1
{
  "name":"onebird",
  "interests":"reading"
}
PUT users/_doc/2
{
  "name":"twobirds",
  "interests":["reading","music"]
}

#查询
POST users/_search
{
  "query": {
		"match_all": {}
	}
}

#查看mapping
GET users/_mapping

https://www.elastic.co/guide/en/elasticsearch/reference/7.1/mapping-params.html

注意事项:

1. 一切文本类型的字符串可以定义成 “text” 或 “keyword” 两种类型。区别在于,text 类型会使用默认分词器分词,当然你也可以为他指定特定的分词器。如果定义成 keyword 类型,那么默认就不会对其进行分词。

es 对字符串类型的 mapping 设定,会将其定义成 text,同时为他定义一个叫做 keyword 的子字段。keyword 只是他的名字,你也可以定义成 kw。这个字段的类型是 keyword(这是一个类型的关键字)

多字段类型情况下,你可以查询 title,也可以查询 title.keyword 查询类型为 keyword 的子字段

关于电脑入门学习办公学习Excel简介电脑办公入门教程5步快速学会excel表格制作的问题我们已经讲解完毕,感谢您的阅读,如果还想了解更多关于easyexcel实现导出excel简单例子、EasyExcel简介及使用方法、Elasticsearch 简单学习 4: 入门学习 - 1、Elasticsearch 简单学习 5: 入门学习 - 2等相关内容,可以在本站寻找。

最近很多小伙伴都在问电脑各硬件之间连接使用原理介绍电脑各硬件之间连接使用原理介绍这两个问题,那么本篇文章就来给大家详细解答一下,同时本文还将给你拓展3D打印机工作原理 原理介绍、android应用层获取各硬件序列号、ceph原理介绍、FTP工作原理介绍等相关知识,下面开始了哦!

本文目录一览:

电脑各硬件之间连接使用原理介绍(电脑各硬件之间连接使用原理介绍)

电脑各硬件之间连接使用原理介绍(电脑各硬件之间连接使用原理介绍)

电脑各硬件之间连接使用原理介绍。本视频可以系统了解下电脑各配件间运行机制和原理知识。

电脑硬件,包括电脑中所有物理的零件,以此来区分它所包括或执行的数据和为硬件提供指令以完成任务的软件。 电脑硬件主要包含:机箱,主板,电源,CPU,内存,硬盘,显示器,光驱,显卡,键盘,鼠标, CPU风扇等。

3D打印机工作原理 原理介绍

3D打印机工作原理 原理介绍

3D打印原看似复杂,其实很简单,看了很多3D打印的视频和模型,你会被它神奇的克隆能力惊呆了,这太神奇了,完全是神奇的克隆机器嘛。这样的高科技到底是怎么工作的呢?

说起它的原理,它一点都不复杂,其运作原理和传统打印机工作原理基本相同,也是用喷头一点点“磨”出来的。只不过3D打印它的喷的不是墨水,而是液体或粉末等“打印材料”,利用光固化和纸层叠等技术的快速成型装置。通过电脑控制把“打印材料”一层层叠加起来,最终把计算机上的蓝图变成实物。

它的工作步骤是这样的:使用CAD软件来创建物品,如果你有现成的模型也可以,比如动物模型、人物、或者微缩建筑等等。然后通过SD卡或者USB优盘把它拷贝到3D打印机中,进行打印设置后,打印机就可以把它们打印出来,其工作结构分解图如下。3D打印机的工作原理和传统打印机基本一样,都是由控制组件、机械组件、打印头、耗材和介质等架构组成的,打印原理是一样的。3D打印机主要是在打印前在电脑上设计了一个完整的三维立体模型,然后在进行打印输出。

3D打印机工作原理 原理介绍

3D打印与激光成型技术一样,采用了分层加工、叠加成型来完成3D实体打印。每一层的打印过程分为两步,首先在需要成型的区域喷洒一层特殊胶水,胶水液滴本身很小,且不易扩散。然后是喷洒一层均匀的粉末,粉末遇到胶水会迅速固化黏结,而没有胶水的区域仍保持松散状态。这样在一层胶水一层粉末的交替下,实体模型将会被“打印”成型,打印完毕后只要扫除松散的粉末即可“刨”出模型,而剩余粉末还可循环利用。

3D打印机工作原理 原理介绍

下面我们来看看3D打印的实际过程:

3D打印机工作原理 原理介绍

3D打印机工作原理 原理介绍

3D打印机工作原理 原理介绍

3D打印机工作原理 原理介绍

3D打印机工作原理 原理介绍

3D打印机工作原理 原理介绍

android应用层获取各硬件序列号

android应用层获取各硬件序列号

各类android手机,想获取它各个组成部件的序列号(or ID什么的,唯一标示即可),譬如camera,内存,感应器等,,cpu serial可以通过 Runtime.getRuntime().exec("cat /proc/cpuinfo")读取。现在是想获取其他的部件,大神们有没啥好办法啊?

ceph原理介绍

ceph原理介绍

1      整体架构介绍

1.1      总体介绍

Ceph是一种开源的软件定义存储系统,诞生于2004年,最早致力于开发下一代高性能分布式文件系统的项目。Ceph可以部署在任意x86服务器上工作,具有良好的扩展性、兼容性和可靠性。它能对外提供文件系统服务(cephfs)、块服务(rbd)和对象存储服务(rgw),是一种统一存储系统。Ceph架构支持海量数据存储,集群可以扩展至PB容量,系统本身无热点数据,数据寻址依赖计算而不是查找,并能做到数据状态自维护,数据自修复,是一款优秀的分布式存储系统。

1.2      整体架构

图 1 ceph全景

Ceph架构主要包含了:Rados集群,librados接口层,rgw、rbd和cephfs这三种存储服务。

Rados集群:Rados是Ceph系统的核心,包含了分布式集群管理和数据管理,集群的扩展性和高可用性是在这里体现的。主要的组件有monitor、osd和mds。Monitor是集群的关键服务,它保证了集群元数据的一致性和集群的可服务性。Osd是ceph的数据服务,它负责了业务数据的落盘,数据状态的监控,数据状态恢复,数据的迁移和恢复等流程。Mds是cephfs的元数据服务,维护文件系统的超级块信息,目录结构,文件信息等。一般如果不使用cephfs,是可以不用部署mds的。

librados接口层:统一封装的接口层,提供集群连接接口,pool创建接口,obj读写接口等,作为基础库提供给上层调用,比如librbd、libcephfs和librgw。第三方的应用可以直接调用librados对ceph做二次开发。

客户端:ceph客户端包括rbd、rgw、cephfs这三种类型,同时也包括librbd、libcephfs和librgw这些开发库。对外提供存储服务,比如rbd可以导出scsi块设备,cephfs可以mount到Linux主机上做为文件系统,也可以通过cifs/nfs导出为网络文件服务,rgw对外直接提供s3或者swift对象存储服务。

2      集群管理

2.1      Monitor

Monitor服务是ceph的核心服务之一,它主要作用是为整个集群提供全局的配置和系统信息。Ceph集群其实是体现在Monitor集群上的,Monitor是一个独立部署的服务,多个Monitor组成高可用集群。Monitor采用paxos算法保证集群数据的一致性,Monitor所管理的数据包括:

1、  Monitor Map:包括集群的fsid,所有的monitor的ip和端口,以及epoch

2、  OSD Map:包括集群的fsid,所有osd状态及监听地址,pool的信息及pg数等

3、  MDS Map:包括所有的mds服务的列表和状态,data pool和metadata pool

4、  PG Map:所有pg的信息,包括状态、version等

5、  CRUSH Map:一个树形结构,包括存储设备,故障域等

2.2      心跳管理

Monitor通过心跳这种方式来获得OSD服务的工作状态,根据这种状态的变化更新相应的位图。

首先是OSD之间会有心跳检查,OSD会检查osd_heartbeat_min_peers个OSD服务,peer osd其实是指的osd相邻的osd服务,默认是10个。这些相邻的osd服务首先是包含同一个pg的osd列表,这个是从pg_map上获取,如果得到的osd列表超过osd_heartbeat_min_peers个就丢弃,不足的就补上当前osd周围状态up的osd进来。

检查过程是每osd_heartbeat_interval秒就检查一次peer端的osd,默认是6秒。如果peer端osd在osd_heartbeat_grace后没回复,默认20s,则标记这个osd状态为down。

图 2 osd peer间心跳

在不同故障域之间osd的状态变化,monitor可能不会第一时间感知到,这里设置了不同故障域的reporter个数,默认是1

图 3 不同故障域的检查

图3所示,osd1和osd2分属于两个不同的故障域。

如果一个osd不能和peer内的所有osd做心跳了,则会向monitor申请最新的osd map。超时时间为osd_mon_heartbeat_interval默认30s。

Monitor如果在mon_osd_report_timeout内收不到osd的消息,则会设置osd为down,mon_osd_report_timeout默认为900s。

正常情况下osd每隔osd_mon_report_interval_min,(最短间隔时间默认为5s)会向monitor报告一次事件,事件包括start刚启动、osd故障、up_thru的变化等。osd向monitor报告的最长时间为osd_mon_report_interval_max,默认为120s。意思是说120s无论osd有没有状态变化都需要向monitor报告。

图 4 osd向monitor报告

3      数据读写

3.1      OSD

OSD(object storage daemon)负责Ceph集群的数据读写,同时也负责向Monitor报告监控的OSD的状态。管理数据的迁移,副本,数据平衡,数据恢复。Ceph集群数据管理的核心服务,通往磁盘的数据通道。

OSD主要包含了两个主要组成部分,一个PG,另一个是ObjectStore。PG(placement group)是Ceph的数据管理的基本逻辑单位,参与数据读写,数据迁移,数据恢复等和数据相关的全部流程。ObjectStore是负责向本地存储读写的模块,现在常用的是filestore和bluestore,当前onestor版本使用的是filestore。Filestore实际上是操作的本地文件系统,将业务最终写到本地磁盘的文件中,默认是使用xfs文件系统。Bluestore是直接操作的裸盘,数据直接通过BIO下到盘上,性能相较于filestore有较大提升,Ceph的最新版本默认采用是Bluestore。

3.2      读写流程

图 5 数据读写过程

数据要存储在Ceph上需要经历几个主要步骤:

1、  Client需要获得Monitor最新的cluster map,得到map后确定osd的信息

2、  对象到pg的hash,具体为对待写的object id做hash,得到的hash值,再对当前pool的pg_num取模,最后得到该对象所在的pg id。

pg_id = hash(object_name) % pg_num

然后再将pool id加到hash值之前,比如4.f1,4就是pool id,f1是上面算出的hash值,这两部分构成一个pg id。

3、  pg到OSD的映射,数据最终需落盘,所以pg得映射到一个OSD上。这个映射过程采用的Ceph自己独有的CRUSH算法,通过计算选择一个合适OSD。CRUSH本质是一种伪随机算法。找到OSD后,Client直接与OSD通信,建立网络连接,将数据发送到OSD服务处理。

4、  OSD最后把收到的数据投递给ObjectStore,由它完成向本地存储写入的过程。同时完成主从OSD的数据落盘。

OSD的数据写入过程满足数据的强一致性,待所有数据落盘才向上返回。

图 6 主从OSD写入过程

1、  Client先将写请求发到主OSD上。

2、  主OSD在收到Client请求后,立即向从OSD发送写请求,同时也写入主OSD的本地存储上。

3、  主OSD收到从OSD写入成功的ack,再确认自己处理正确,最后再返给Client写完成ack。写过程中必须等到所有的OSD的写成功返回才能向Client返回写操作成功的消息。

3.3      POOL和PG

Pool是一种逻辑上存储资源池,Ceph对外提供的存储服务,资源都是从Pool中划分提供的。Pool分两种一种是副本模式,一种是纠删码模式。一个Pool是由许多PG构成的。Pool的信息保存在osd map中。

PG是对象数据的集合,同一个集合内的对象应用相同的存储策略。比如对象的副本都会存放到相同的OSD列表中。一个对象只属于一个PG,一个PG包含多个对象,一个PG会存放到多个OSD上,一个OSD会承载多个PG。

图7表示了一个pool是双副本,对象t1是怎么分布到pg 1.3e的。

图 7 pg与osd对应关系

3.4      CRUSH算法

CRUSH(control replication under scalable hash)算法是Ceph内部中重要的寻址算法,它主要解决对象到盘的寻址过程。同时由于是通过计算得出,因此集群不需要查询地址,所以也就没有中心节点的产生,极大的减少了元数据的体量。CRUSH可以将数据尽量的分散到各个存储上。

CRUSH算法主要使用的场景:数据io的时候,创建pool的时候,osd状态up/down,osd的添加和删除。3.2节所描述的,CRUSH主要是解决PG是如何映射到OSD列表的问题。用函数表示就是:

crush(pg.x) -> (osd.1, osd.2, osd.3,….osdN)

图 8 CRUSH Map

CRUSH map可以认为是数据中心的抽象,它的目的是寻找到合适的位置存放数据副本。CRUSH内容包括了组织结构Hierarchical CRUSH Map,副本选择规则Placement Rules以及容器Bucket。

层级化CRUSH Map,逻辑上看组织结构是个树形结构。包含device和bucket,device一般为osd服务作为叶子节点。bucket作为设备的容器,一般为CRUSH Map中的普通节点。bucket的类型有osd(device),host,chassis,rack,row,pdu,pod,room,datacenter,region,root,这些类型描述了CRUSH Map中的存储位置。每个bucket包含多个device。

Bucket Weight,权重是用来描述存储能力的指标。1T大小表示为1,采用双精度数表示。Bucket的权重大小是包含子bucket或device的权重大小。

Placement Rules决定了对象副本选择规则,它定义从哪些bucket或是device里去选择。这样可以定义不同的pool可以从不同的磁盘选择存放位置。

表格 1 bucket定义

# buckets

host cvknode146 {

        id -2           # do not change unnecessarily

        # weight 2.160

        alg straw2

        hash 0  # rjenkins1

        item osd.1 weight 1.080

        item osd.3 weight 1.080

}

host cvknode145 {

        id -3           # do not change unnecessarily

        # weight 2.160

        alg straw2

        hash 0  # rjenkins1

        item osd.0 weight 1.080

        item osd.4 weight 1.080

}

host cvknode144 {

        id -4           # do not change unnecessarily

        # weight 2.160

        alg straw2

        hash 0  # rjenkins1

        item osd.2 weight 1.080

        item osd.5 weight 1.080

}

rack rack0 {

        id -7           # do not change unnecessarily

        # weight 6.480

        alg straw2

        hash 0  # rjenkins1

        item cvknode145 weight 2.160

        item cvknode144 weight 2.160

        item cvknode146 weight 2.160

}

root partition0 {

        id -5           # do not change unnecessarily

        # weight 6.480

        alg straw2

        hash 0  # rjenkins1

        item rack0 weight 6.480

}

# rules

rule partition0_rule {

        ruleset 1

        type replicated

        min_size 1

        max_size 10

        step take partition0

        step chooseleaf firstn 0 type host

        step emit

}

rule partition0_ec_rule_1 {

        ruleset 2

        type erasure

        min_size 3

        max_size 20

        step set_chooseleaf_tries 5

        step set_choose_tries 100

        step take partition0

        step chooseleaf indep 0 type host

        step emit

}

       表1中描述的是CRUSH Map的定义的Bucket,用树形图表示就是:

图 9 crush map图形化

图9所示,root作为crush map的入口,定义了bucket rack0,其中包括3个host,每个host包括了两个device osd。bucket的定义了随机选择算法为straw2,hash算法为rjenkins1。这里的hash算法是用来计算随机值,随机选择算法是根据随机值判定选择OSD。

表1中所定义的选择规则是partition0_rule和partition0_ec_rule_1。规则原型如下:

rule <rulename> {

    ruleset <ruleset>

    type [ replicated | erasure ]

    min_size <min-size>

    max_size <max-size>

    step take <bucket-name> [class <device-class>]

    step [choose|chooseleaf] [firstn|indep] <N> <bucket-type>

    step emit

}

ruleset:当前规则的id

type:pool的存储模式

min_size:如果Pool的副本数小于min_size则不使用这个规则

max_size:如果Pool的副本数大于max_size则不使用这个规则

step take <bucket-name> [class <device-class>]:

选择一个bucket,一般是root类型bucket,以这个为查询的输入,遍历这颗树。同时也可而已指定自定义的设备类型。

step choose firstn {num} type {bucket-type}:

深度优先选择num个bucket-type类型的子bucket。

l  If {num} == 0, choose pool-num-replicas buckets (all available).

l  If {num} > 0 && < pool-num-replicas, choose that many buckets.

l  If {num} < 0, it means pool-num-replicas - {num}.

如果num为0则选择和pool副本数一样的,num大于0小于pool的副本数,则返回num个副本数,如果num小于0,则返回pool副本数减num的个数。

step chooseleaf firstn {num} type {bucket-type}:

和上一条规则一样,区别在于chooseleaf是选择叶子节点,一般就是osd。

step emit:

输出选择结果。

3.4.1  Straw算法

现在有了crush的组织结构CRUSH Map和选择规则Placement Rules,从bucket中选出合适的设备是采用随机算法来做具体的选择。当前CRUSH所支持的随机算法有:

表格 2 随机选择算法

Uniform

适用于每个item权重相同,且很少添加或删除,item的数量比较确定。

List

以链表保存item,包含的item可以是任意权重,但是会造成某些节点被选中的概率变大。

Tree

采用2分查找树,包含大量item的情况下可以快速查找,但是会造成某些节点被选中的概率变大,而在节点删除添加移除和重新修改权重会引入额外组织变动开销,查找速度O(logn)。

Straw

相对List和Tree是比较公平的算法,每个节点都有公平竞争的机会,而且权重越大的节点被选中的机会越大。

Straw2

Straw的改进算法,减少了在节点删除移动的时候数据迁移量。

具体描述Straw算法,提供各个bucket尽量公平的选择机会,权重越大选中的概率越高。执行过程其实递归遍历bucket,找到合适device。如果权限大就尽量找权限大的,如果权限一样则随机返回。

图 10 straw代码片段

       如代码所示:

1、  crush(pg_id, osd_id, r) => draw,r为常数,运算次数

2、  ( draw &0xffff ) * osd_weight => straw

3、  得到最大的high_draw,返回该item

其中draw就是随机数,然后用draw乘以权重得到一个签值,选中最大签值的OSD。要保证不能每次都选中权重最大那个,随机数的产生就很重要。

图 11 rjenkins hash算法

将3组数据传入进行混合搅拌,尽量得到一个随机值。可以看到只要传入的值是相同的,得到随机值也是相同的,所以CRUSH是一个伪随机的算法。

参考源码src/crush/mapper.c,入口函数crush_do_rule

3.5      ObjectStore模块

ObjectStore是Ceph系统落盘前的最后一个模块,它负责保证业务数据可以安全可靠高效的IO。ObjectStore定义事务操作,具体的本地存储必须实现这些操作。ObjectStore目前包括4种本地实现:

1、  FileStore:H、J版本使用较多的本地存储,采用文件系统做为对象读写的方式。

2、  BlueStore:最新L版本支持的本地存储,未来Ceph的默认方式,抛弃掉文件系统直接操作块设备,性能最好。

3、  KStore:使用KV存储系统作为本地存储。

4、  MemStore:数据和元数据都保存在内存中,主要用于测试和验证。

目前用于生产环境的是FileStore和BlueStore。

3.5.1  FileStore

FileStore默认使用xfs文件系统保存数据。利用文件系统POSIX接口实现ObjStore的接口,每个对象在底层是以文件存在。

图 12 filestore结构

FileStore包含FileJournal和DBObjectMap两个模块,FileStore为了提高ObjectStore写事务处理能力和原子性引入了FileJournal。它相当于数据库的WAL(write ahead log),为了保证每个写事务的完整性。它会使用direct io方式写到journal日志里,完成后再将事务提交到FileStore的队列中继续完成写操作,如果中途有发生crash,OSD在做recovery的时候会将日志恢复出来。

FileStore写数据顺序是,先写journal然后再写盘上。Journal写完后会返回给上层,但是要能read ready还是要等到数据落盘后才行,不过在大量小io随机写场景性能还是不错。FileStore由于先写日志再写盘,所以有个写放大的问题。

DBObjectMap是专门用来管理对象的属性的模块,有两种实现xattr和omap。xattr是用文件系统的扩展属性实现的,受限于文件系统扩展属性的长度限制,适合小量数据存放。omap是采用leveldb k-v键值存储实现,如果属性大小超过xattr的限制,则可以存放到omap中。

3.5.2  Bluestore

图 13 bluestore整体结构

Bluestore为解决filestore在写数据前先写journal产生的写放大,并针对ssd做了相应的优化。Bluestore直接操作裸盘,尽可能的避免文件系统(xfs、ext4)的开销。操作裸盘则盘空间管理由allocator(默认是BitmapAllocator)处理。Bluestore在io过程中产生的元数据,元数据则存放到rocksdb kv数据库中。rocksdb存数据依赖文件系统,但是rocksdb将底层系统相关的抽象为env,用户程序只需要实现相应的接口就可以提供底层的系统的封装。Bluestore实现了BlueRocksEnv,并实现了Bluefs支撑BlueRocksEnv。Bluefs的日志和数据文件都是保存在裸盘上,和用户数据共享裸盘设备,也可以分开指定不同设备。

图 14 osd设备数据分区

osd目录分区:默认占用100M,默认挂载xfs文件系统。提供基本的描述信息,包括whoami(osd编号),osd的type,osd的魔术字,block块设备入口等。

Block dev label分区:默认占用4K。存储bluestore_bdev_label_t结构体信息,包含osd_uuid,块设备size,设备描述信息,创建时间等。

Bluefs supper block分区:默认占用4K。存储bluefs_super_t结构体信息,包含osd_uuid,version和block_size等。

DB数据分区:默认占用MAX[1G,块设备总大小的4%],保存DB数据和日志数据。

用户数据分区:默认占用剩余空间,存放用户业务数据。

元数据映射关系:

图 15 元数据映射关系

一个对象对应一个onode,一个onode包含多个extent,多个extent存放在一个或者多个blob里,每个blob又对应到多个pextent,就是具体的物理块,这样就完成了extent到pextent的映射。

BlueStore读过程比较简单,如果有预读标志则从cache里读,如果没命中则需要从盘上读出来并且添加到cache中。

Bluestore写过程比较复杂,大致分为大写和小写。根据写入数据长度来确定是小写还是大写,通过对min_alloc_size(blob的最小分配大写默认64K)取模,如果小于64K为小写流程,如果大于64K则为大写流程。

图 16 写场景

小写分为覆盖写和非覆盖写,其中非覆盖小写和大写没有写惩罚,先写数据然后改元数据。覆盖写场景会产生WAL日志,先要完成WAL日志处理落盘后,再写入业务数据。

整体来说性能比filestore提高不少。

4      数据peering和恢复

Ceph系统中承担数据IO和数据恢复的基本逻辑单元叫PG(Placement Group),PG是Ceph中数据载体。可以理解PG为一个目录或者集合,包含了多个对象。

PG有自己的状态,PG健康度出现异常,状态会发生变迁,数据也会发生迁移。

active+clean:PG的健康时的状态。

Degraded:降级状态,如果是双副本的配置,有个osd挂掉了,PG就会进入这种状态。这种情况下PG还是可以提供IO服务的。

Recovery:一个osd出现故障下线了,但这时pg还是可读写的,当故障osd启动后,它所保存的数据比其他osd版本要旧这个时候就会产生recovery,保证数据一致。

Remapped:如果osd下线是由于硬盘故障,这个时候就是永久性故障,需要再分配新osd做重新映射。选中新osd后,数据还是为空的,需要从正常的osd上将数据全量拷贝到新osd上,所以状态一般是remapped+backfilling。

Peered:出现这种状态,是由于故障的osd数量过多,造成了pg不能读写了。这个状态可以理解为正常的osd在等待其他副本osd上线。

4.1      数据peering机制

Peering过程是一个PG对应的一组OSD的状态达到一致的过程,PG达到active时,peering过程就完成了,但是PG对应的OSD上的数据并不一定完全一致。

PG发生的场景:

n  系统初始化OSD启动重新加载PG或者创建PG,会触发PG发起一次Peering过程。

n  OSD故障或OSD增加减少,会导致PG的acting set发生变化,PG也会发起一次Peering过程。

peering概念介绍

1、  acting set和up set

acting set是一个PG活动的一组OSD,该列表是有序的,下标第一个OSD为prime OSD。up set一般与acting set相同。不相同的情况是OSD故障导致,生成临时PG。这个时候acting set和up set不一致。

2、  临时pg

原OSDacting set列表中[0,1,2]的主OSD osd.0故障了,crush重新选出的acting set为[3,1,2],但是这个时候osd3并没有该PG的数据,需要做backfill,这个时候osd3是不能读的。所以会产生一个临时PG做为prime,比如通知monitor让osd1做临时prime,这个时候up set就为[1,3,2],acting set还是[3,1,2],backfill做完,临时pg取消,两个列表就想同了。

3、  Authoritative History权威日志

指的是记录pg完整顺序的连续的操作日志记录,做为数据恢复的依据。

Peering的过程,基本分为三个步骤

l  GetInfo : pg的主osd通过发送消息获取各个从OSD的pg_info信息。

l  GetLog:根据pg_info的比较,选择一个拥有权威日志的osd(auth_log_shard) , 如果主osd不是拥有权威日志的osd,就去拥有权威日志的osd获取,获取后主osd也拥有权威日志。

l  GetMissing:拉取其它从OSD 的pg log(或者部分获取,或者全部获取FULL_LOG) , 通过本地的auth log对比,来判别从OSD 上缺失的object 信息。以用于后续recovery过程的依据。

l  Active: 激活主osd,并发想通知notify消息,激活相应的从osd。

简单来说peering并不恢复数据,只是将各个osd的状态统一起来,明确哪些对象需要恢复,为下一步做准备。

4.2      数据恢复

Peering完成后,就可以知道是否有数据需要恢复了。恢复的方式有两种recovery和backfill。

Recovery是就根据PG日志中缺失的记录来修复不一致的对象。

Backfill是PG通过重新扫描所有对象,对比发现缺失的对象,通过整体拷贝的方式修复。当OSD失效时间过长导致无法根据PG日志记录来修复,或者新OSD加入导致的数据迁移,这些都会导致Backfill流程。

5      数据端到端一致性

存储系统中io路径复杂,传统存储系统一般包括从应用层到内核文件系统、块设备、SCSI层再到HBA和磁盘控制器,每层都有出错的可能。因此传统的端到端解决方案会以数据块校验为主来解决。

 因为 Ceph 作为一个应用层的应用,这时候如果封装固定数据块并且加入校验数据会导致较严重的性能问题,因此 Ceph 在这方面只是引入 Scrub 机制(Read Verify)来保证数据的正确性。

简单来说,Ceph 的 OSD 会定时启动 Scrub 线程来扫描部分对象,通过与其他副本进行对比来发现是否一致,如果存在不一致的情况,Ceph 会抛出这个异常交给用户去解决。

Scrub按照扫描内容不同分为两种方式:

n  一种叫srub,它只是比较各个对象的副本元数据,来检查数据一致性。只是检查元数据,所以读取和计算的量都比较小,一种轻量的检查。

n  一种叫deep-srub,它要进一步检查对象的数据内容是否一致,实现深度扫描,几乎要扫描磁盘上的所有数据并计算crc32校验,所有开销很大,占用系统资源很多。

Scrub按照扫描的方式分为两种:

n  在线扫描:不影响系统正常业务。

n  离线扫描:需要系统停或冻结业务。

Ceph的Scrub是实现了在线扫描,可不中断系统业务的前提下执行scrub,但是针对具体某个对象做Scrub,是会锁定对象的,阻止客户端对它的访问,一直到Scrub执行完成才会释放。

FTP工作原理介绍

FTP工作原理介绍

文件传输协议:File Transfer Protocol 早期的三个应用级协议之一,基于C/S结构 数据传输格式:二进制(默认)和文本 双通道协议:命令和数据连接

两种模式:从服务器角度

主动(PORT style):服务器主动连接 命令(控制):客户端:随机port —> 服务器:21/tcp 数据:客户端:随机port <—服务器:20/tcp

被动(PASV style):客户端主动连接 命令(控制):客户端:随机port —> 服务器:21/tcp 数据:客户端:随机port —> 服务器:随机port /tcp

基于C/S结构有专门的客户端和专门的服务端

双通道协议:命令通道和数据通道(所谓双通道就是FTP支持两个端口)

命令通道:走TCP的21端口,用来传输指令的。

数据通道:用来传输数据的

命令通道永远是客户端主动向服务端发起请求:命令通道永远走的是TCP/21端口

数据通道走的是两个端口,通过工作模式来确定走的端口:

主动模式(post)为TCP的20端口。

被动模式走的是随机端口,所谓主动和被动都是以服务器的角色来看。

主动模式(post):服务器端主动连接客户端

被动模式(pasv):客户端主动连接服务器端(会通过命令通道相互交换信息,客户端就会知道服务端的随机端口号)

范例:服务器被动模式数据端口 227 Entering Passive Mode (172,16,0,1,224,59) 服务器数据端口为:224*256+59

FTP双通道工作原理解析

在这里插入图片描述

FTP是一种文件传输协议,它支持两种模式,一种方式叫做Standard (也就是 Active,主动方式),一种是 Passive (也就是PASV,被动方式)。 Standard模式 (主动模式)FTP的客户端发送 PORT 命令到FTP server。Passive模式(被动模式)FTP的客户端发送 PASV命令到 FTP Server。

命令通道:

是客户端主动向服务器端发起命令请求,同时服务器端开启TCP/21端口号。客户端主动发起三次握手请求。

服务器由两个端口发起链接。其中有一个叫命令通道的端口,有一个是实现数据通道的端口。命令通道是用来通过实现命令的执行。数据端口是用来实现数据的传输,命令通道走的端口是固定的TCP/21端口。如果客户端需要数据传输时,服务就会开启数据通道端口。数据通道走的端口不是固定的,是根据工作模式来判断开启的端口。

数据通道:

下面介绍一个这数据通道的两种方式的工作原理:

主动工作模式(post):服务器端主动连接客户端

FTP 客户端首先和FTP Server的TCP 21端口建立连接,通过这个通道发送命令,客户端需要接收数据的时候在这个通道上发送PORT命令。 PORT命令包含了客户端用什么端口接收数据。在传送数据的时候,服务器端通过自己数据端口的TCP 20端口发送数据。 FTP server必须和客户端建立一个新的连接用来传送数据。

被动工作模式(pasv):客户端主动连接服务器端(会通过命令通道相互交换信息,客户端就会知道服务端的随机端口号)

在建立控制通道的时候和Standard模式类似,当客户端通过这个通道发送PASV 命令的时候,FTP server打开一个位于1024和5000之间的随机端口并且通知客户端在这个端口上传送数据的请求,然后FTP server 将通过这个端口进行数据的传送,这个时候FTP server不再需要建立一个新的和客户端之间的连接。

FTP服务状态码: 1XX:信息 125:数据连接打开 2XX:成功类状态 200:命令OK 230:登录成功 3XX:补充类 331:用户名OK 4XX:客户端错误 425:不能打开数据连接 5XX:服务器错误 530:不能登录

用户认证:

匿名用户:ftp,anonymous,对应Linux用户ftp ​ 系统用户:Linux用户,用户/etc/passwd,密码/etc/shadow ​ 虚拟用户:特定服务的专用用户,独立的用户/密码文件

更多文章和资料|点击下方文字直达 ↓↓↓
阿里云K8s实战手册
[阿里云CDN排坑指南]CDN
ECS运维指南
DevOps实践手册
Hadoop大数据实战手册
Knative云原生应用开发指南
OSS 运维实战手册

关于电脑各硬件之间连接使用原理介绍电脑各硬件之间连接使用原理介绍的问题我们已经讲解完毕,感谢您的阅读,如果还想了解更多关于3D打印机工作原理 原理介绍、android应用层获取各硬件序列号、ceph原理介绍、FTP工作原理介绍等相关内容,可以在本站寻找。

对于教你怎么组装电脑感兴趣的读者,本文将提供您所需要的所有信息,我们将详细讲解教你怎么组装电脑主机,并且为您提供关于lenovo电脑怎么组装? 电脑怎么组装开机?、z型琴架怎么组装? 组装电脑成本?、京东组装电脑可靠吗? 组装电脑蓝牙怎么配?、华橙组装电脑怎么样? 组装电脑成本?的宝贵知识。

本文目录一览:

教你怎么组装电脑(教你怎么组装电脑主机)

教你怎么组装电脑(教你怎么组装电脑主机)

台式机的电脑组装还是比较简单的,但在拆装之前也要专业学习一下,你才敢动手保证拆了能正确的组装好,有时候你自己搞下电脑清理维护之类的也可以拆拆电脑的那几大件,来搞搞灰尘清理那些。发生一般的电脑小故障。自己也可以拆机来检查判断下,自己修电脑。

lenovo电脑怎么组装? 电脑怎么组装开机?

lenovo电脑怎么组装? 电脑怎么组装开机?

组装电脑看似复杂,但其实并不难。php小编百草为大家带来详细的组装教程,从零基础到熟练组装,一步步带你玩转电脑组装。无论你是想要自主组装一台高性能电脑,还是想了解了解电脑的内部结构,这份教程都能满足你的需求。下面,我们将详细介绍从准备材料到组装完成的每一个步骤,让大家轻松组装出心仪的电脑。

lenovo电脑怎么组装? 电脑怎么组装开机?

lenovo电脑怎么组装?

具体安装步骤如下

1,CPU安装

CPU要平稳放下,然后盖上铁盖,用力压下铁杆到位,CPU就安装完成。

然后在CPU上均匀涂抹cpu散热硅胶

2,CPU散热器安装

首先,要把四个脚钉位置转动到上面箭头相反的方向,然后对准主板四个空位,用力下压,即可完成一个位置的安装,重复四次即可。

如果要拆卸散热器,把四个脚钉位置向上面箭头相的方向转动,然后用力拉,重复四次即可拆卸。

3,内存的安装很容易,对准内存与内存插槽上得凹凸位,分别左/右用力下,听到“啪”的一小声,左/右卡位会自动口上,然后再用同样方法压好另一边即可。

4,电源安装

安装电源的四个螺丝钉

5,主板安装 用螺丝刀把螺丝按预留的螺丝孔固定好主板就可以了。

6,硬盘安装

硬盘可以选择舱位来安装,一般原则是靠中间,保证更多位置散热,上四个螺丝,偷懒的话上对角线两颗也行。

7,显卡安装

现在独立显卡不是必须安装的,CPU或主板都集成了显卡,满足基本要求是没问题的。安装显卡没什么难度,把机箱挡板暴力拆下,对准PCI-E插槽插上,然后上螺丝即可。如果主板有多条PCI-E X16插槽(最长的那种),优先接到靠近CPU端那条,这样保证显卡是全速运行。

8,主板接线

1、主板电源/CPU辅助供电:对准卡口位接上

2、前置音频和前置USB:对准防呆接口插上即可

3、硬盘灯、电源灯、开机键、重启键 按照主板标示安装(彩色线正极,黑白线负极)

HDD LED代表硬盘灯,POWER LED是电源灯,RESET SW是重启键,POWER SW是开关,PC SPEAKER是PC小喇叭。

4、现在硬盘基本都是SATA接口了,接上SATA电源线(5PIN扁口线)和数据线即可

5、中高端显卡,别忘了要接上6PIN或8PIN的辅助供电

电脑怎么组装开机?

组装电脑的话,第一步要选择主板cpu,内存。硬盘。显卡。机箱以及电源。

第二部键盘,鼠标,显示器,摄像头等外设。

第三部组装。将cpu,硬盘,显卡。电源等按要求连接。键盘,鼠标,显示器的外设分别连接到对应的接口。

第四步制作系统盘是选择windows系统还是linux系统,第五步,安装系统。

第六部开机。

philips电脑怎么组装?

正常的把三大件凑齐,塞主机箱里,挂在飞利浦显示器上,点亮,应该就欧克!

aco电脑怎么组装?

组装电脑步骤一

首先是机箱的安装,主要是对机箱进行拆封,并且将电源安装在机箱里,然后进行安装主板,将主板安装在机箱主板上,组装电脑然后进行CPU的安装,在主板处理器插座上插入安装所需的CPU,并且安装上散热风扇,组装电脑中内存条的安装,将内存条插入主板内存插槽中。

组装电脑步骤二

接着是显卡的安装,根据显卡总线选择合适的插槽;组装电脑进行声卡的安装,现在市场主流声卡多为PCI插槽的声卡;驱动器的安装,主要针对硬盘、光驱和软驱进行安装;然后就是组装电脑的机箱与主板间的连线,即各种指示灯、电源开关线。PC喇叭的连接,以及硬盘、光驱和软驱电源线和数据线的连接。

组装电脑步骤三

进行组装电脑第三大步,盖上机箱盖,理论上在安装完主机后,是可以盖上机箱盖了,但为了此后出问题的检查,最好先不加盖,而等系统安装完毕后再盖,然后就是输入设备的安装,组装电脑还要进行连接键盘鼠标与主机一体化;输出设备的安装,即显示器的安装;再重新检查各个接线,准备进行测试。

组装电脑步骤四

组装电脑还有给机器加电,若显示器能够正常显示,表明初装已经正确,此时进入BIOS进行系统初始设置。进行了上述组装电脑的步骤,一般硬件的安装就已基本完成了,但要使电脑运行起来,还需要进行下面的安装步骤。

组装电脑步骤五

接着就是组装电脑的分区硬盘和格式化硬盘,安装操作系统,如Windows 98或者Windows XP系统。组装电脑安装操作系统后,安装驱动程序,如显卡、声卡等驱动程序;进行72小时的烤机,如果硬件有问题,在72小时的烤机中会被发现。

noc电脑怎么组装?

组装一台电脑的步骤如下1.第一步,将所有配件打开,将机箱打开。

2.第二步,装置CPU和CPU风扇,将内存条安置在对应的卡槽之中。

3.第三步,先上主板垫脚螺母,接着将主板放入平稳的机箱中固定。

4.第四步,根据说明书进行排线操作。

5.第五步,连接电源,主机组装完成了。

6.第六步,开始连接主机与显示器,先在显示器上接上VGA线,接上后要把后面的两个螺丝固定。

7.第七步,固定完毕之后,把VGA线的另一端接电脑主机。

8.第八步,给显示器接上电源线,电脑组装过程就基本完成了。

普通电脑怎么组装?

1.选择零部件:选择适合自己需求的CPU、主板、内存、硬盘、显卡、电源等零部件,可以参考网上的硬件评测和比较。

2.准备工具:组装电脑需要用到螺丝刀、镊子、手套等工具,根据需要准备好。

3.安装CPU:打开主板,找到CPU插槽,按照指示将CPU插入,注意方向与插口相同。按下CPU扣子将CPU固定在主板上。

4.安装内存:在主板上找到内存插槽,先将内存插进去,然后两边用手按住,听到“咔擦”一声说明已经插好。

5.安装硬盘:将硬盘插上数据线和电源线,然后将硬盘插入主板上的SATA插槽即可。

6.安装显卡:将显卡插在主板上的PCIE插槽中,用螺丝固定好。

7.连接电源:将电源插入主板专用插口,注意正确连接。

8.连接显示器:将显示器数据线插入显卡的输出口。

9.温故知新:在插入零部件之前要认真查看主板说明书和零部件说明书,特别是插口和开关的使用说明。

10.启动测试:将电源插入插座,按下电脑开机按钮,若出现画面,则电脑组装成功,否则需要反复检查。

acer台式电脑怎么组装?

宏基电脑重装系统的步骤:

1、电脑进入系统后打开小白一键重装,等待本地检测完成2、接着选择需要重装系统版本后点击

3、下面的步骤一直点击下一步,耐心等待系统安装成功重启4、电脑重启后开始安装,经过多次重启正式进入宏基电脑系统。

清华同方电脑怎么组装?

组装台式电脑时过程如下:

(1) 机箱的安装,主要是对机箱进行拆封,并且将电源安装在机箱里。

(2) 主板的安装,将主板安装在机箱主板上。

(3) CPU的安装,在主板处理器插座上插入安装所需的CPU,并且安装上散热风扇。

(4) 内存条的安装,将内存条插入主板内存插槽中。

(5) 显卡的安装,根据显卡总线选择合适的插槽。

(6) 声卡的安装,现在市场主流声卡多为PCI插槽的声卡。

(7) 驱动器的安装,主要针对硬盘、光驱和软驱进行安装。

(8) 机箱与主板间的连线,即各种指示灯、电源开关线。PC喇叭的连接,以及硬盘、光驱和软驱电源线和数据线的连接。

(9) 盖上机箱盖(理论上在安装完主机后,是可以盖上机箱盖了,但为了此后出问题的检查,最好先不加盖,而等系统安装完毕后再盖)。

(10) 输入设备的安装,连接键盘鼠标与主机一体化。

(11) 输出设备的安装,即显示器的安装。

(12) 再重新检查各个接线,准备进行测试。

(13) 给机器加电,若显示器能够正常显示,表明初装已经正确,此时进入BIOS进行系统初始设置。

硬件的安装结束了。

下面是操作系统的安装:

(14) 分区硬盘和格式化硬盘。

(15) 安装操作系统,如win7或者Windows XP系统。

(16) 安装操作系统后,安装驱动程序,如显卡、声卡等驱动程序。

电脑怎么组装插线?

1.

机箱前面板连线,一般有前置音频,前置USB,电源指示灯,硬盘指示灯,开机,重新启动。

这些连线,的接线图,主板说明书上面一般都有说明的。

如果没有,看主板上面的也有写的,注意针脚的位置,

基本都是这样连接,主板上面的HD -LED 是硬盘工作指示灯,就把线头写有:H..D.D.LED 的插在上面,主板上面的SP-LED 是电源工作指示灯,就把线头写有,P LED的正负端插上去, 这2个指示灯如果插反了正负级,通电后灯不会亮, 那个不亮的,就换下正负方向就可以了

2.

主板上面的RST是重启按钮,把线头写有RESET SW的插上去,主板上面 的PW-BN是开机按钮,把线头上面写有POWER SW 的插上去

3.

SPEAKER是前置的蜂鸣器,分为“+”“-”相位;普通的扬声器无论如何接都是可以发生的,但这里比较特殊。由于“+”相上提供了+5V的电压值,因此我们必须正确安装,以确保蜂鸣器发声 。

4.

下面是前置音频,主板上面的F-AUDIO 就是前置音频的接口位置,跟USB的不一样,USB是边上少一针,前置音频是在弟4棵少一针,插在相应的位置就可以了

5.

前置面版连接就完成了,最后进行电源和硬盘的连线,SATA数据线是一个反7字行状的,不要担心插错了,错了插不进去的,硬盘电影线,比数据线要宽,型装差不多,连线到硬盘上面

6.

就这样对准插进去就可以了,SATA数据线的另一端插在主板的SATA接口上面。就完成了,接下来电源连到主板。

7.

主板供电24P,以前的老主板是20P的,就取下来,边上4个活动的

8.

CPU有8P供电,也有4P的,主板和CPU供电,都有防呆设计的,不要担心插错,方向错了你插不下去的。 

9.

连到对于的接口,看上面的主板接口图,显卡供电是6P的,也有8P的,可以拆解,显卡电源接口插上去就完事了。

10.

装机就完成 了,如果你机箱是侧透的,可以装条旋光灯,就好看多了,不是侧透的就没有毕要了,可以走背线的机箱,线就放后面,这样看起来美观,装完后理下线,该绑起来的用扎带绑好,看起来也舒服。

联想台式电脑怎么组装?

联想台式机组装是在原来的标准配置里面加内存条或固态硬盘。

以上就是lenovo电脑怎么组装? 电脑怎么组装开机?的详细内容,更多请关注php中文网其它相关文章!

z型琴架怎么组装? 组装电脑成本?

z型琴架怎么组装? 组装电脑成本?

组装电脑或组装z型琴架时,如何才能省时省力、确保稳定性?php小编子墨为您解答这些问题。以下详细内容将引导您一步步组装电脑和z型琴架,并提供专业建议和技巧,帮助您打造牢固稳定的设备。

z型琴架怎么组装? 组装电脑成本?

z型琴架怎么组装?

Z型支架左右两边有四个卡子,卡子下面有固定螺丝,琴放上去后再调整卡子把琴卡好后拧紧下面的螺丝就可以了。

组装电脑成本?

显卡 rtx2060 2500元(支持光线追踪)

cpu R5 3600 1400元

主板:B450 600元

m.2 固态硬盘500G 600元

+4T机械硬盘 600元

主机箱配风扇+电源600w 500元

内存条8G两条,500元

键鼠100元

组装电脑清单?

组装电脑的确需要一个清单,因为我们组装电脑的时候对于电脑的配置运行要求确定以后就可以在网上选购一些适合的主板,然后根据主板再确定电源和显卡以及其他配置的要求了,把清单列出来直接问电脑厂或者是经销商购买就行

组装电脑好吗?

组装电脑可以有一些好处,例如:

1. 自定义配置:组装电脑可以根据个人需求选择适合的硬件配置,可以根据自己的使用目的和预算来选择更适合的组件。

2. 性价比:组装电脑相对于购买品牌机更具性价比,可以通过选择性价比更高的硬件来节省成本。

3. 可升级性:组装电脑通常更容易进行硬件的升级,可以根据需要随时升级或更换硬件,提升电脑的性能。

4. 自由度高:组装电脑可以根据个人的喜好选择外观设计、配色等,可以制作出独特的电脑。

然而,组装电脑也存在一些挑战和风险,例如需要一定的专业知识和技能,选择不合适的硬件可能会导致兼容性问题或性能不佳,组装过程中可能存在的风险等。因此,如果没有足够的经验和技能,或者对于电脑硬件不太了解,可能更适合购买品牌机。

电脑床组装?

买电脑桌时有图纸,按照图纸组装就可以了

如何组装电脑?

1、先在显示器上接上VGA线,接上后要把后面的两个螺丝固定。固定主要是担心在移时造成连接线脱落。

2、然后把VGA线的另一端接电脑主机。

3、接下来给显示器接上电源线,(注意只是和显示器想连,电源线另一端先别接上插座,等所有连接完成后再通电。)

4、接下来给主机接上鼠标。

5、把键盘也连接上。(绿色的是鼠标,紫色的是键盘。同时注意鼠标和键盘插头内部针脚要和接口内针孔的位置对准才能插入。)把网线一端接电脑主机的RJ45接口,然后另一端接交换机或路由器或调制解调器。

6、接下来把主机的电源线接上。

7、接下来就可以把主机和显示器的电源插头接上插座给主机和显示器通电了。就可以正常开机与使用了。

组装电脑配置?

CPU 内存 主板 固态硬盘 电源和机箱

2021最具性价比组装电脑组装推荐?

2021年性价比最高的要组装这种电脑我推荐还是组装华为的,电脑比较好因为华维的电子产品,了它的质量是特别好的,也是比较靠谱的,尤其是华维的这种电脑零配件的目前国产的是特别好的,所以我推荐用这种华为的电脑组装,尤其是它的性价比是比较高的,而且组装的这种配置也是比较高的

怎么在线模拟组装电脑_模拟组装电脑配置清单?

1、现在可以在线模拟装机的地方太多了,这里搜索中关村在线模拟装机打开进入。

2、打开以后,我们可以看看大家的方案,然后自己模拟攒机,这里我们一样一样的选择电脑配置。比如CPU,主板,内存,显卡,硬盘,电源等,配件。如图所示。

3、处理器CPU,这个是比较关键的,我们根据自己的需要选择是INTEL核心处理器还是AMD核心处理器,选择CPU系列,然后将自己喜欢的CPU添加到配置单中。现在的CPU通常有盒装和散装的区别,建议大家选择盒装的CPU。

4、将CPU加入配置单以后,接下来选择主板,这样一个一个的进行设置和选择。

5、主板这里大家要决定是购买集成显卡的主板还是非集成主板显卡,如果主板集成了显卡,这样我们后面就可以省略购买独立显卡的开支,如果平时不完大游戏,家用办公等,我们选择集成显卡的主板就可以了,应该够我们自己平时使用的,小编见过很多人,自己根本不完什么网络游戏,非要购买独立显卡的主板,增加开支。

6、这样就将需要的配件全部添加到了装机配置单,键盘鼠标家用的话50左右一套即可。

7、最后在右边会显示我们的装机配置单,当然如果你感觉价格便宜了,你可以删除这里的配件,然后重新选择更好的硬件配置,更换CPU或者主板等等。让价格符合自己心里预期,并且电脑可以满足自己的日常需要即可。

组装平板电脑和台式组装电脑,区别大吗?

台式电脑:包括品牌机和组装机,品牌机一般配置都比较差,性价比低,卖个牌子。组装机性价比高,性能好,当然前提是你懂DIY配置硬件方面的知识。

笔记本电脑:便携性高,一般用来办公,游戏性差,同等价格的组装电脑配置比笔记本高很多。

一体机电脑:即品牌机,价格贵,配置低,不推荐购买。

平板电脑:是一种小型、比笔记本电脑更方便携带的个人电脑,以触摸屏作为基本的输入设备。但和前者系统是不同的,功能要少很多。

以上就是z型琴架怎么组装? 组装电脑成本?的详细内容,更多请关注php中文网其它相关文章!

京东组装电脑可靠吗? 组装电脑蓝牙怎么配?

京东组装电脑可靠吗? 组装电脑蓝牙怎么配?

京东组装电脑是否可靠,以及组装电脑后的蓝牙配置方法,一直是困扰许多用户的问题。php小编香蕉将为您详细介绍京东组装电脑的可靠性以及 组装电脑后蓝牙配对的具体步骤。请继续阅读文章,了解更多信息。

京东组装电脑可靠吗? 组装电脑蓝牙怎么配?

京东组装电脑可靠吗?

京东组装电脑是可靠的。电脑是现代一种用于高速计算的电子计算机器,可以进行数值计算,又可以进行逻辑计算,还具有存储记忆功能。是能够按照程序运行,自动、高速处理海量数据的现代化智能电子设备。

组装电脑蓝牙怎么配?

只需购买一个外置式的蓝牙装置就可以了。

台式机,一般是不会自带蓝牙的,所以要购置一个通过usb口匹配及供电的蓝牙装置:

然后安装下驱动,待需要时候,打开应用软件,即可连接蓝牙设备与台式机了。

连接的设备,首先和蓝牙耳机连接手机是一样的道理,需要配对,然后才能互相连接,实现数据交换的

如何在京东组装电脑?

你自己会装的话,就购买配件回来自己安装,不会安装就购买配件的时候顺便购买一个京东上门安装电脑服务,一百多块钱的样子,会有人上门服务给你把电脑安装调试好,并装好系统。

京东组装电脑哪个牌子好?

根据消费者反馈和市场调查,MSI和华硕是比较靠谱的牌子MSI和华硕在制造高品质、高品质的经验方面更加专业化且两个牌子有超过一个世纪的电脑制造经验,他们在组装电脑时不仅能提供更好的兼容性,还能提供更好的质量和可靠性此外,在性价比方面,这两个品牌相对实惠且非常适合普通消费者鉴于个人用户的需求和使用情况不同,建议在购买时进行更多的市场比较和产品研究,以找到适合自己的产品

京东买电脑,给组装吗?

京东有装机服务,只需在京东购买好硬件之后,再花99元,就可以让京东帮你组装硬件和安装系统。不过运输途中有各种各样的情况会出来,甚至直接造成硬件的损坏。所以个人并不推荐这样的装机方式。建议:在购买齐硬件之后,自己把硬件拿到当地的实体店,让店家帮你组装硬件和安装系统。一般都在30-50元左右。由于新买的硬件基本都包装盒货海绵等等这些保护措施,所以也基本能保证硬件在运输途中的安全性。

而且拿到当地的实体店组装,也可以马上测试出硬件是否有质量问题。

京东的组装电脑哪家好?

御龙者,机械革命,雷霆一些自营品牌等等。

还有一些诸如联想一类的品牌机,质量确实不错,但是性价比差的不是一点半点,实在是划不来,土豪可以试试。

怎样在京东商城组装电脑?

1、首先在浏览器中打开京东商城主页。

2、打开主页最右上角的“网站导航”,选择“行业频道”下的“数码”。

3、在新打开的页面中选择“自助装机”。

4、这样就可以随便选择配件了,同时配件的价格也都能看到,最后配置单以及总的价格都很方便的显示,装机就是如此简单。

京东卖组装电脑的哪家好?

京东自营和天猫旗舰店。京东自营是京东公司自己开的自营店,所有京东自营店的产品都是官方正品,都是很好的,所以组装电脑在京东自营店中也是相当的好!在京东中搜索天猫旗舰店,组装电脑是天猫旗舰店的招牌,所以也是相当好的!所以推荐京东自营店和天猫旗舰店。

京东上买组装电脑可靠吗?

京东上买组装电脑可靠。

京东自营的组装电脑各方面还是很可靠的,第三方的卖家的组装电脑就不怎么可靠,建议在京东自营购买电脑。

若是有时间,可以去取购买电脑的配件来进行组织,买全新的配件,不仅质量放心,而且价格会更优惠,不建议去实体店购买电脑。

京东买组装电脑靠谱吗?

如果没有组装经验,还是建议去实体店购买,京东可以购买零件自己组装

以上就是京东组装电脑可靠吗? 组装电脑蓝牙怎么配?的详细内容,更多请关注php中文网其它相关文章!

华橙组装电脑怎么样? 组装电脑成本?

华橙组装电脑怎么样? 组装电脑成本?

组装电脑是许多人省钱并获得定制化机器的好方法。但是,在组装电脑之前,了解潜在成本非常重要,以便您做出明智的决定。php小编苹果将为您分解组装一台电脑的成本,并探讨影响这些成本的因素。了解如何节省组装成本的秘诀,并避免常见的陷阱。继续阅读以了解更多信息!

华橙组装电脑怎么样? 组装电脑成本?

华橙组装电脑怎么样?

华橙是一家提供电脑组装和维修服务的公司,其组装电脑的服务质量会受到各种因素的影响,包括所选配件的质量、技术水平、服务态度等等。

因此,如果您需要华橙的组装电脑服务,可以先了解他们的服务质量、配件品质等方面的评价,可以通过搜索相关的评价、点评信息来了解。另外,在选择电脑组装服务时,建议您仔细了解具体的配置需求和预算,以便选择最适合的组装方案。

组装电脑成本?

显卡 rtx2060 2500元(支持光线追踪)

cpu R5 3600 1400元

主板:B450 600元

m.2 固态硬盘500G 600元

+4T机械硬盘 600元

主机箱配风扇+电源600w 500元

内存条8G两条,500元

键鼠100元

组装电脑清单?

组装电脑的确需要一个清单,因为我们组装电脑的时候对于电脑的配置运行要求确定以后就可以在网上选购一些适合的主板,然后根据主板再确定电源和显卡以及其他配置的要求了,把清单列出来直接问电脑厂或者是经销商购买就行

组装电脑好吗?

组装电脑可以有一些好处,例如:

1. 自定义配置:组装电脑可以根据个人需求选择适合的硬件配置,可以根据自己的使用目的和预算来选择更适合的组件。

2. 性价比:组装电脑相对于购买品牌机更具性价比,可以通过选择性价比更高的硬件来节省成本。

3. 可升级性:组装电脑通常更容易进行硬件的升级,可以根据需要随时升级或更换硬件,提升电脑的性能。

4. 自由度高:组装电脑可以根据个人的喜好选择外观设计、配色等,可以制作出独特的电脑。

然而,组装电脑也存在一些挑战和风险,例如需要一定的专业知识和技能,选择不合适的硬件可能会导致兼容性问题或性能不佳,组装过程中可能存在的风险等。因此,如果没有足够的经验和技能,或者对于电脑硬件不太了解,可能更适合购买品牌机。

电脑床组装?

买电脑桌时有图纸,按照图纸组装就可以了

如何组装电脑?

1、先在显示器上接上VGA线,接上后要把后面的两个螺丝固定。固定主要是担心在移时造成连接线脱落。

2、然后把VGA线的另一端接电脑主机。

3、接下来给显示器接上电源线,(注意只是和显示器想连,电源线另一端先别接上插座,等所有连接完成后再通电。)

4、接下来给主机接上鼠标。

5、把键盘也连接上。(绿色的是鼠标,紫色的是键盘。同时注意鼠标和键盘插头内部针脚要和接口内针孔的位置对准才能插入。)把网线一端接电脑主机的RJ45接口,然后另一端接交换机或路由器或调制解调器。

6、接下来把主机的电源线接上。

7、接下来就可以把主机和显示器的电源插头接上插座给主机和显示器通电了。就可以正常开机与使用了。

组装电脑配置?

CPU 内存 主板 固态硬盘 电源和机箱

2021最具性价比组装电脑组装推荐?

2021年性价比最高的要组装这种电脑我推荐还是组装华为的,电脑比较好因为华维的电子产品,了它的质量是特别好的,也是比较靠谱的,尤其是华维的这种电脑零配件的目前国产的是特别好的,所以我推荐用这种华为的电脑组装,尤其是它的性价比是比较高的,而且组装的这种配置也是比较高的

怎么在线模拟组装电脑_模拟组装电脑配置清单?

1、现在可以在线模拟装机的地方太多了,这里搜索中关村在线模拟装机打开进入。

2、打开以后,我们可以看看大家的方案,然后自己模拟攒机,这里我们一样一样的选择电脑配置。比如CPU,主板,内存,显卡,硬盘,电源等,配件。如图所示。

3、处理器CPU,这个是比较关键的,我们根据自己的需要选择是INTEL核心处理器还是AMD核心处理器,选择CPU系列,然后将自己喜欢的CPU添加到配置单中。现在的CPU通常有盒装和散装的区别,建议大家选择盒装的CPU。

4、将CPU加入配置单以后,接下来选择主板,这样一个一个的进行设置和选择。

5、主板这里大家要决定是购买集成显卡的主板还是非集成主板显卡,如果主板集成了显卡,这样我们后面就可以省略购买独立显卡的开支,如果平时不完大游戏,家用办公等,我们选择集成显卡的主板就可以了,应该够我们自己平时使用的,小编见过很多人,自己根本不完什么网络游戏,非要购买独立显卡的主板,增加开支。

6、这样就将需要的配件全部添加到了装机配置单,键盘鼠标家用的话50左右一套即可。

7、最后在右边会显示我们的装机配置单,当然如果你感觉价格便宜了,你可以删除这里的配件,然后重新选择更好的硬件配置,更换CPU或者主板等等。让价格符合自己心里预期,并且电脑可以满足自己的日常需要即可。

组装平板电脑和台式组装电脑,区别大吗?

台式电脑:包括品牌机和组装机,品牌机一般配置都比较差,性价比低,卖个牌子。组装机性价比高,性能好,当然前提是你懂DIY配置硬件方面的知识。

笔记本电脑:便携性高,一般用来办公,游戏性差,同等价格的组装电脑配置比笔记本高很多。

一体机电脑:即品牌机,价格贵,配置低,不推荐购买。

平板电脑:是一种小型、比笔记本电脑更方便携带的个人电脑,以触摸屏作为基本的输入设备。但和前者系统是不同的,功能要少很多。

以上就是华橙组装电脑怎么样? 组装电脑成本?的详细内容,更多请关注php中文网其它相关文章!

关于教你怎么组装电脑教你怎么组装电脑主机的问题我们已经讲解完毕,感谢您的阅读,如果还想了解更多关于lenovo电脑怎么组装? 电脑怎么组装开机?、z型琴架怎么组装? 组装电脑成本?、京东组装电脑可靠吗? 组装电脑蓝牙怎么配?、华橙组装电脑怎么样? 组装电脑成本?等相关内容,可以在本站寻找。

如果您对教你组装电脑台式机感兴趣,那么本文将是一篇不错的选择,我们将为您详在本文中,您将会了解到关于教你组装电脑台式机的详细内容,我们还将为您解答教你组装电脑台式机视频的相关问题,并且为您提供关于DIY装机组装电脑(如何组装电脑主机线)、京东组装电脑可靠吗? 组装电脑蓝牙怎么配?、全家桶电脑配置? 台式机组装电脑配置?、台式原装电脑和组装电脑哪个比较好?的有价值信息。

本文目录一览:

教你组装电脑台式机(教你组装电脑台式机视频)

教你组装电脑台式机(教你组装电脑台式机视频)

台式机的电脑组装还是比较简单的,但在拆装之前也要专业学习一下,你才敢动手保证拆了能正确的组装好,有时候你自己搞下电脑清理维护之类的也可以拆拆电脑的那几大件,来搞搞灰尘清理那些。发生一般的电脑小故障。自己也可以拆机来检查判断下,自己修电脑。这个教程和前面的那个组装类似。大家可以顺便学学。

DIY装机组装电脑(如何组装电脑主机线)

DIY装机组装电脑(如何组装电脑主机线)

DIY装机组装电脑(如何组装电脑主机线)

DIY装机自己组装电脑《电源安装与主机线的连接方法终结篇》

由于主板设备本身就没有多数东西,并且安装似乎也不复杂,所以介绍到这里已经差不多结束了,那我们就开始主机安装的最后的流程吧。

由于在前面我们已经介绍了cpu的安装、硅脂的涂抹方法、内存的安装、主板的安装、硬盘的安装,很多同学可能觉得我应该一篇文章全部介绍完,其实我分开发有分开发的好处,这样我介绍的更加细化一些!不图多专业,只求自己动手丰衣足食,看完这篇你就可以毕业了!

DIY装机自己组装电脑cpu安装cpu

电脑主机cpu导热硅脂的正确涂抹方法

DIY装机自己组装电脑内存安装内存

DIY装机自己组装电脑《主板与硬盘的安装》

最后一篇,主机电源的安装与线的接法,老司机可以略过,新司机请根据顺序观看参考!

还剩下电源没有安装了,拆开电源包装,取出电源:

将电源放入电源仓,主机风扇对着主机电源出风口,并固定电源螺丝:


这样电源就安装完成了,我们下面开始接线,我们首先看看电源带着的电源接口有ATX 24-pin、ESP/ATX 12v 8p、PCI 6p、4p、SATA、和floppy connectors :

将ATX 24p插入主板、将cpu供电接口插入cpu 接口为EPS/ATX 如图:

接下来将SATA电源线插入硬盘,对硬盘进行供电:

有显卡的将PCI供电接口插入显卡!电源的连接就完成了!下面我们介绍跳线的接法。

这款主机的跳线一共如下:

首先将USB3.0插入主板usb3.0接口。

插入前置USB接口和前置音频接口,这些接口都具有防呆设计,所以错了是无法插入的,放心的插吧。

好了下面接开关机跳线,主板上面已经有明确的表示,根据标识插入即可:


根据标示以此插入,led灯分正负极的,不要插反了,还有就是最后一组重启跳线,主板已经画上白线表示为一组,所以不要插到旁边的针脚上!我是不是担心过头了?好吧。我知道你们是不会这样做的。

完工

是不是还差什么?对的,还有硬盘的数据线没有接啊!

这下真的结束了,不相信你看我开机测试:

至于走线么将就看吧,我尽力了!

还等什么开机做系统:

进pe 分区做系统 就不在这篇进行介绍了。

这样一台主机的组装就完成了,接下来为硬盘进行分区,并做系统!我写的有点啰嗦了。如果你是一位新司机我建议是从第一篇开始看起!如果你是一位老司机,那请忽略吧!

此文一共5篇点击下面访问更多文章:

DIY装机自己组装电脑cpu安装cpu

电脑主机cpu导热硅脂的正确涂抹方法

DIY装机自己组装电脑内存安装内存

DIY装机自己组装电脑《主板与硬盘的安装》

DIY装机自己组装电脑《电源安装与主机线的连接方法完结篇》

关注科技100分,好玩又涨知识!

申明: 此文由《科技100分》精心收集与创作!并发布至相同名称栏目如:今日头条、百度百家、搜狐、企鹅、UC、微信公众号等!

京东组装电脑可靠吗? 组装电脑蓝牙怎么配?

京东组装电脑可靠吗? 组装电脑蓝牙怎么配?

京东组装电脑是否可靠,以及组装电脑后的蓝牙配置方法,一直是困扰许多用户的问题。php小编香蕉将为您详细介绍京东组装电脑的可靠性以及 组装电脑后蓝牙配对的具体步骤。请继续阅读文章,了解更多信息。

京东组装电脑可靠吗? 组装电脑蓝牙怎么配?

京东组装电脑可靠吗?

京东组装电脑是可靠的。电脑是现代一种用于高速计算的电子计算机器,可以进行数值计算,又可以进行逻辑计算,还具有存储记忆功能。是能够按照程序运行,自动、高速处理海量数据的现代化智能电子设备。

组装电脑蓝牙怎么配?

只需购买一个外置式的蓝牙装置就可以了。

台式机,一般是不会自带蓝牙的,所以要购置一个通过usb口匹配及供电的蓝牙装置:

然后安装下驱动,待需要时候,打开应用软件,即可连接蓝牙设备与台式机了。

连接的设备,首先和蓝牙耳机连接手机是一样的道理,需要配对,然后才能互相连接,实现数据交换的

如何在京东组装电脑?

你自己会装的话,就购买配件回来自己安装,不会安装就购买配件的时候顺便购买一个京东上门安装电脑服务,一百多块钱的样子,会有人上门服务给你把电脑安装调试好,并装好系统。

京东组装电脑哪个牌子好?

根据消费者反馈和市场调查,MSI和华硕是比较靠谱的牌子MSI和华硕在制造高品质、高品质的经验方面更加专业化且两个牌子有超过一个世纪的电脑制造经验,他们在组装电脑时不仅能提供更好的兼容性,还能提供更好的质量和可靠性此外,在性价比方面,这两个品牌相对实惠且非常适合普通消费者鉴于个人用户的需求和使用情况不同,建议在购买时进行更多的市场比较和产品研究,以找到适合自己的产品

京东买电脑,给组装吗?

京东有装机服务,只需在京东购买好硬件之后,再花99元,就可以让京东帮你组装硬件和安装系统。不过运输途中有各种各样的情况会出来,甚至直接造成硬件的损坏。所以个人并不推荐这样的装机方式。建议:在购买齐硬件之后,自己把硬件拿到当地的实体店,让店家帮你组装硬件和安装系统。一般都在30-50元左右。由于新买的硬件基本都包装盒货海绵等等这些保护措施,所以也基本能保证硬件在运输途中的安全性。

而且拿到当地的实体店组装,也可以马上测试出硬件是否有质量问题。

京东的组装电脑哪家好?

御龙者,机械革命,雷霆一些自营品牌等等。

还有一些诸如联想一类的品牌机,质量确实不错,但是性价比差的不是一点半点,实在是划不来,土豪可以试试。

怎样在京东商城组装电脑?

1、首先在浏览器中打开京东商城主页。

2、打开主页最右上角的“网站导航”,选择“行业频道”下的“数码”。

3、在新打开的页面中选择“自助装机”。

4、这样就可以随便选择配件了,同时配件的价格也都能看到,最后配置单以及总的价格都很方便的显示,装机就是如此简单。

京东卖组装电脑的哪家好?

京东自营和天猫旗舰店。京东自营是京东公司自己开的自营店,所有京东自营店的产品都是官方正品,都是很好的,所以组装电脑在京东自营店中也是相当的好!在京东中搜索天猫旗舰店,组装电脑是天猫旗舰店的招牌,所以也是相当好的!所以推荐京东自营店和天猫旗舰店。

京东上买组装电脑可靠吗?

京东上买组装电脑可靠。

京东自营的组装电脑各方面还是很可靠的,第三方的卖家的组装电脑就不怎么可靠,建议在京东自营购买电脑。

若是有时间,可以去取购买电脑的配件来进行组织,买全新的配件,不仅质量放心,而且价格会更优惠,不建议去实体店购买电脑。

京东买组装电脑靠谱吗?

如果没有组装经验,还是建议去实体店购买,京东可以购买零件自己组装

以上就是京东组装电脑可靠吗? 组装电脑蓝牙怎么配?的详细内容,更多请关注php中文网其它相关文章!

全家桶电脑配置? 台式机组装电脑配置?

全家桶电脑配置? 台式机组装电脑配置?

电脑配置千变万化,组装电脑时如何选择合适的全家桶配置或台式机组装配置令人头疼。php小编草莓为大家带来了详细的全家桶电脑配置和台式机组装电脑配置挑选指南,帮助大家解决组装电脑时的配置难题。详情请继续阅读下文。

全家桶电脑配置? 台式机组装电脑配置?

全家桶电脑配置?

Adobe全家桶对CPU、内存要求较高,流畅运行的话,现在一般例如用十代酷睿I5 10400F散片+B460M MORTAR主板套装约1500左右,搭配东海X5散热器+16G DDR4 2666骇客神条内存(8GX2)+西数SN750 500G固态硬盘(NVme m.2)+Quadro P620 2G专业制图显卡+VX400(额定400W)电源+暗夜猎手5机箱约2600左右,主机一共约4100左右。

台式机组装电脑配置?

1台式电脑基本硬件组成部分

  要组装一台完整的台式电脑,首先从了解它的硬件组成部件开始,依次的顺序是机箱、电源、主板、CPU、内存、硬盘、 显示器 、键盘鼠标。以上是核心,必不可以少的硬件。其余的辅助硬件,可根据自己实际情况去评估,如光驱、音箱、 风扇等。

2CPU和内存选购

  作为核心的中央处理器,可以实际的需求出发,如玩游戏需求,至少应该配置4核,四核加速比例应该在2.2倍上下。这样对于玩游戏的顺畅度和体验感都会有提高。目前CPU的属于AMD和Intel的天下,两者选其一均可以,而内存,一般来说是越大越好,处理的数据能力也就越快。不过这个还是得结合CPU速度,避免过剩浪费。  

3主板选购

  主板的品牌选择性要比CPU大很多,主要是相对于CPU比较,主板的制造 门槛 要低很多,因此生产厂家多了额,选择性也就变大了。目前主流被技嘉,微星,华硕等所占据,如果玩游戏的话建议选其一牌子购买。  

4显卡选购

  这个部件对于游戏的玩家来说,尤为重要,绝对不能手软,影驰或微星显卡都值得去考虑,而且显卡内存至少2G。

5硬盘选购

  硬盘相对于其他主要硬件来说,是更新比较快的一个部件,价格随着逐年的下降,目前已经到了一个接近白菜价的地步,更重要的是固态硬盘价格已经逐步可以被大家所接受,很多朋友都已经选购固态硬盘来代替传统的机械硬盘。硬盘知名的除了西数,就是希捷,价格差别不大,可根据自身喜好选购。  

6显示器选购

  显示器作为电脑的输出界面,价格已经不再是问题,所以现在追求的是越大越好,对于玩家来书哦,选上一款三星的显示器,来个23.6英寸,保证让你体验感满满的。

7除了以上的关键硬件部件的选购外,其余的电源机箱,这两者要求并不是特别的高,基本上是外观精美外,只要能满足正常的散热即可,当然散热风扇的声音也是一个考虑的因素;最后配上一款逻辑的键盘和鼠标,甚至可以考虑无线键鼠,瞬间可以让你组装的台式机提升一个档次。和品牌机相比较,组装的台式机更像是一个大家庭,虽然以前不认识,但成了家人后相处会更好。

rog全家桶和普通组装的区别?

Rog全家桶和普通组装的区别很大。其中一方面是硬件配置方面,ROG全家桶通常采用的是高端的组件,而普通组装则可以选择一些性价比更高的组件。这会导致价格的差异比较大。另一方面是品牌和服务方面,ROG是华硕旗下的高端品牌,其品牌认知度和售后服务质量都比较高,而普通组装则需要自己去购买各个品牌的组件,售后服务相对来说要差一些。综上所述,如果你有足够的预算并追求高端品质和品牌认知度,选择ROG全家桶是不错的选择;如果预算较为有限并且不在意品牌,那么选择普通组装就可以满足需求。

adobe全家桶电脑配置?

推荐i5四核以上处理器,显卡2g独立显卡以上推荐游戏显卡。

rpg全家桶电脑配置?

CPU

Intel 酷睿i9 9900K

购买

1

4499

主板

华硕ROG RAMPAGE VI EXTREME OMEGA

购买

1

10001

内存

芝奇皇家戟 32GB DDR4 3200(F4-3200C16D-32GTRS)

购买

4

3599

硬盘

希捷BarraCuda 2TB 7200转 256MB(ST2000DM008)

购买

1

389

固态硬盘

三星970 EVO Plus NVMe M.2(1TB)

购买

1

1999

显卡

华硕ROG-MATRIX-RTX2080Ti-P11G-GAMING

1

29999

机箱

华硕玩家国度ROG Strix Helios

购买

1

1999

电源

华硕ROG-THOR-1200P

购买

1

2799

散热器

ROG 龙神360

购买

1

2499

电脑全家桶里都有什么?

ROG全家桶指的是ROG电脑是由各个品牌的硬件组成,比如说电脑的CPU是英特尔的,显卡是ROG自家产的,内存条是七彩虹的,硬盘是三星的,主板是微星的,这种组装机就成为“全家桶”。

电脑组成部分:1、电源--电源是电脑中不可缺少的供电设备,它的作用是将220V交流电转换为电脑中使用的5V、12V、3.3V直流电,其性能的好坏,直接影响到其他设备工作的稳定性,进而会影响整机的稳定性。

2、CPU--CPU是一台电脑的核心部件,是一台电脑的运算核心和控制核心,主要是解释计算机指令以及处理计算机软件中的数据。

3、主板--它把电脑的各个部件连接在一起,使用同时发挥各自的作用。

4、内存--电脑中所有的应用程序都要经过内存的处理,它是与CPU进行沟通的桥梁。

5、硬盘--它可以存储电脑产生的所有数据,并且不会丢失,在用户需要使用这些数据的时候,可以进入硬盘中进行查找。

6、显卡--将计算机系统所需要的显示信息进行转换驱动,并向显示器提供行扫描信号,控制显示器的正确显示。

买电脑全家桶划算吗?

不划算。

个人建议如果预算吃紧或者会影响日常生活的话还是稍降标准吧,毕竟ROG还是有一定的溢价的性价比真的谈不上,要是同样配置贵个几千并不是很在意那一步到位还是很省心的。

配全家桶的主要是两类人。一是重度游戏和超频玩家,钱包充足的情况下为信仰和用料买单;二是预算充足懒得折腾各种品牌性价比什么的一步到位配齐省心,买回来也不太追求性能是否溢出大部分时间拿来刷剧加班顺便欣赏一下全套rgb灯光做装饰。

对于diy方面的土豪加上略知一二的人,ROG是个极好的选择,因为华硕在主机方面的售后很不错,ROG的服务更好一筹要说差多少,其实性能就只会差一点点,但价格差很多。

组一台5950x+3090,64g内存带2t固态的主机(3090用中等水平的)三万差不多就能搞定,但ROG全家桶大概得四万起步,这差的一万拿去买显示器桌子椅子还有外设也许还有多的

电脑全家桶什么意思?

可能只是商家的推销手段而已,他们自己批量组装或者搭配购买的电脑或配件组合。

电脑配件含有 CPU 显卡 主板 硬盘 内存条 电源 机箱,外设有 屏幕 鼠标 键盘

所谓全家桶可能是 整机加外设 ,也可能是一些配件组合

当然可能是当地的一些人耍你玩起来的梗。毕竟全家桶的定义范围太宽,还可以定义为软件全家桶

rog全家桶买整机好还是自己组装好?

1 自己组装好2 因为自己组装可以根据自己的需求和喜好选择每个配件,可以更好地匹配自己的使用场景和预算。而且可以自由升级和维护,不受整机限制。3 如果你对电脑硬件有一定的了解和经验,并且有足够的时间和耐心,自己组装整机是一个不错的选择。但如果没有相关经验或者时间紧迫,可以考虑购买整机。

r电脑全家桶什么意思?

ROG全家桶指的是ROG电脑是由各个品牌的硬件组成,比如说电脑的CPU是英特尔的,显卡是ROG自家产的,内存条是七彩虹的,硬盘是三星的,主板是微星的,这种组装机就成为“全家桶”。

以上就是全家桶电脑配置? 台式机组装电脑配置?的详细内容,更多请关注php中文网其它相关文章!

台式原装电脑和组装电脑哪个比较好?

台式原装电脑和组装电脑哪个比较好?

组装电脑和原装台式机哪个更胜一筹?不少小伙伴在购买电脑时都纠结于此,今天php小编苹果就带大家深入剖析它们的优劣势,帮助大家做出明智选择。以下文章将详细阐述不同需求下的最佳选择,指导大家根据自己的需求和预算做出最佳决策。

台式原装电脑和组装电脑哪个比较好?

原装机是生产厂家把显示器、机箱(主板、硬盘、CPU、内存条、显卡、网卡、电源、光驱、软驱)、键盘、鼠标、音箱都组装好了。

哪个器件坏了可以找厂家进行保修的,组装机是自己将购买的各个配件组装起来。但是正规厂家的配件都是会有保修期的。

个人喜欢用组装机,可以量身定做,经济实惠 品牌机的优势,无非就是电脑做工比较细致,售后服务比较好,在保修期内,只要是硬件方面的问题,一个电话,第二天就能上门检测/维修/更换,比较适合于对电脑硬件不是很熟悉的人士使用。

组装机的优势,就是灵活配置,依个人的偏好,只要是兼容的,那都可以搭配,而且可以自己添加更改里边的配件,还有就是价格上的便宜,所以比较适合于对电脑硬件熟悉的玩家自己动手改造。

但是各自都有缺点,品牌机的缺点,就是同档次相似配置的电脑,整体价格要贵上一截,组装机的缺点,其实也很明显,比如售后,一般只保1年,不会给你多保的,而且是有条件保修。 1,稳定性和售后: 对于菜鸟和DIY知识及经验不多的玩家,品牌机好(当然要买知名的,比如联想,dell;国内很多山寨品牌机不能算),因为品牌机都是经过稳定和兼容性测试的,而且联想,dell这类名牌选的三大关键性部件(主板,显卡,电源)基本都是富士康等一线代工厂给生产,品质有保证。

保修,组装机的出售商和厂家只负责给你调换件,而且问题都要自己找。

品牌机则多有上门或在线服务。

不过对于有经验的玩家,尤其是老鸟,稳定性和售后都不是问题,买件前略微扫下市场信息就知道买什么牌子,哪种型号,搭配起来不会有问题(现在一线品牌的硬件,很少有不兼容或出故障的现象了)。

万一出了故障,自己用排除法也可以找到病根。

2,性能: 组装机,如果你没被JS黑掉,有懂行的高手帮助或是本身就是老鸟,那么性能强于同等价格的品牌机的一倍甚至更多。

品牌机的利润空间决定了选用硬件的性能,不能是中上等。

主要集中在:显卡,比如组装机一般900块买R9 270X,但组装机就降为R7 260X;硬盘,同样价格自己装可以买2TB的,但品牌机一般为1TB;内存,自己装可以买16G DDR3 1866的,品牌机一般是8G DDR3 1600的。

电源,品牌机是够用,比如整机耗能200瓦,就装250瓦的电源,但自己买可以买350瓦的以后升级硬件有余量。

3,可升级性: 品牌机的升级性一般不太好,比如电源尺寸和机箱是定制,以后你要升级电源就麻烦。 4,菜鸟也组装的窍门: 找高手出配件单,把每一样的牌子和型号定好后,写在纸上,去电脑城严格按单买件。

硬件都要“全国联保行货”或有800电话查询的“行货”。

买时要商家开票写明每款的牌子和型号,以及“行货”。

随身带U盘,装几个检测软件:GPU-Z,CPU-Z,HD TUNE Pro,装机后用软件检测下是否对得上。

给商家组装费不要抠门,比如他报150元就不要砍价了,否则以免他偷换件来赚你的钱。

即便多给100组装费也比品牌机便宜。

这样就ok了。 拓展资料: 组装电脑也称兼容机或DIY电脑。即根据个人需要,选择电脑所需要的兼容配件,然后把各种互不冲突的配件组装在一起,就成了一台组装电脑,组装电脑的配件一般有:CPU、主板、内存、显卡、硬盘、光驱、显示器、机箱、电源、键盘和鼠标。 :—组装电脑

以上就是台式原装电脑和组装电脑哪个比较好?的详细内容,更多请关注php中文网其它相关文章!

今天的关于教你组装电脑台式机教你组装电脑台式机视频的分享已经结束,谢谢您的关注,如果想了解更多关于DIY装机组装电脑(如何组装电脑主机线)、京东组装电脑可靠吗? 组装电脑蓝牙怎么配?、全家桶电脑配置? 台式机组装电脑配置?、台式原装电脑和组装电脑哪个比较好?的相关知识,请在本站进行查询。

在本文中,我们将为您详细介绍Tagxp_电脑维修视频教程20的相关知识,并且为您解答关于电脑维修视频教程20讲的疑问,此外,我们还会提供一些关于ibm有哪些电脑维修点 ibm电脑维修方法及维修点介绍、Tagxp_电脑维修视频教程1、Tagxp_电脑维修视频教程10、Tagxp_电脑维修视频教程11的有用信息。

本文目录一览:

Tagxp_电脑维修视频教程20(电脑维修视频教程20讲)

Tagxp_电脑维修视频教程20(电脑维修视频教程20讲)

现在电脑已经开始普及到千家万户,如同电视机一样,慢慢的几乎每家每户都会买电脑。电脑用久了自然也会出一些小毛病,电脑维修的需求也是很大的,不管你是想专业学修电脑,还是自己学点电脑维修知识,本教程都非常适合你看看,本教程是栾京老师的电脑维修视频教程,讲得非常好。容易理解,可以带你学修电脑入门。学完本教程,以后再经过实践,相信你的经验会越来越多。

ibm有哪些电脑维修点 ibm电脑维修方法及维修点介绍

ibm有哪些电脑维修点 ibm电脑维修方法及维修点介绍

ibm电脑是属于商务型的电脑,由于ibm电脑在相同情况下比其他品牌的电脑安全性更高,因此在更多的商务人士更更愿意使用ibm电脑。但是我们应该知道,任何一款产品,即便质量品牌再怎么好,使用的时间久了,难免会有一些小故障出现。所以今天小编重点想为大家介绍一下ibm电脑维修方法的相关信息,希望在您在使用ibm电脑的工作之余,可以帮助到您。

ibm电脑的故障判断:

1.ibm电脑议案假如在开机后没有影像,或者是影像一直在闪烁,偶尔还有就是ibm电脑的屏幕会在闪光,这时候最有可能的是ibm电脑的背光板出现问题了。

2.ibm电脑如有出现开不了机的情况,主要可能是ibm电脑的cpu程序出现紊乱,程序的紊乱是很多电脑很常见的一种问题。

3.在使用ibm电脑的时候,当ibm 电脑开机 后,ibm电脑的屏幕上出现了 马赛克 了,有时候可以重启消失,偶尔一直在屏幕上。这主要可能是这ibm电脑内连线交错的情况。

4.ibm电脑在开始或者是使用一段时间后出现突然图像没有了的状况,需要检查电源电路有没有断路,如果没有。有可能是电源板烧坏了。

@H_301_19@

ibm电脑维修方法:

1.在ibm电脑出现黑屏或者是花屏的时候,首先进行ibm电脑的重启,如果正常了就搞定。如果还是存在这样的状况,不要随意的拆开机身,这时候需要找到专业的维修人士。当然啦,也有可能是温度过高导致的黑屏,可以给ibm电脑降温,然后再开机。

2.如果ibm电脑的屏幕有出现部分图像花掉的情况,检查逻辑 电路板 是否接触不良,也有可能是信号板出现问题,需要更换。

3.当ibm电脑出现在使用或者是开机后出现没光,没声音,查看光管老化程度如何,如果自己有关管可以自己进行更换的。注意这时候需要将高压板上的电路的取消,主要是为了保护ibm电脑。

4.ibm电脑的屏幕出现彩色的斑点,这样的情况可以先选择检查电路是否短路。假如电路正常,可能需要在ibm电脑里面更换一个电源保护器或者类型的装置。

ibm电脑维修点:

深圳市 深圳

电话:0755-26450457

地址:深圳市南山大道1175号新绿岛大厦4A03室

广州市 广州

电话:020-82607276

地址:广州市新塘镇新塘大道6号新康 花园 南 门 B区38号铺

最后,我们都想要自己的一些空间与秘密,相对于其他的电脑,ibm电脑的安全性上是肯定有保障的。如果的有自己需要保护的商务文件之类的,这款电脑是很适合的,而且不要是在工作还是生活的娱乐方面,ibm电脑的电脑也是在其他功能上得到的充分的体现。以上所列举的关于ibm电脑维修方法介绍,希望对大家有帮助。

Tagxp_电脑维修视频教程1

Tagxp_电脑维修视频教程1

现在电脑已经开始普及到千家万户,如同电视机一样,慢慢的几乎每家每户都会买电脑。电脑用久了自然也

会出一些小毛病,的需求也是很大的,不管你是想专业学修电脑,还是自己学点电脑维修知识,本教程都

非常适合你看看,本教程是栾京老师的电脑维修视频教程,讲得非常好。容易理解,可以带你学修电脑入门。

学完本教程,以后再经过实践,相信你的经验会越来越多。

Tagxp_电脑维修视频教程10

Tagxp_电脑维修视频教程10

现在电脑已经开始普及到千家万户,如同电视机一样,慢慢的几乎每家每户都会买电脑。电脑用久了自然也

会出一些小毛病,电脑维修的需求也是很大的,不管你是想专业学修电脑,还是自己学点电脑维修知识,本教程都

非常适合你看看,本教程是栾京老师的电脑维修视频教程,讲得非常好。容易理解,可以带你学修电脑入门。

学完本教程,以后再经过实践,相信你的经验会越来越多。

Tagxp_电脑维修视频教程11

Tagxp_电脑维修视频教程11

现在电脑已经开始普及到千家万户,如同电视机一样,慢慢的几乎每家每户都会买电脑。电脑用久了自然也

会出一些小毛病,电脑维修的需求也是很大的,不管你是想专业学修电脑,还是自己学点维修知识,本教程都

非常适合你看看,本教程是栾京老师的电脑维修视频教程,讲得非常好。容易理解,可以带你学修电脑入门。

学完本教程,以后再经过实践,相信你的经验会越来越多。


今天关于Tagxp_电脑维修视频教程20电脑维修视频教程20讲的分享就到这里,希望大家有所收获,若想了解更多关于ibm有哪些电脑维修点 ibm电脑维修方法及维修点介绍、Tagxp_电脑维修视频教程1、Tagxp_电脑维修视频教程10、Tagxp_电脑维修视频教程11等相关知识,可以在本站进行查询。

在本文中,您将会了解到关于Tagxp_电脑维修视频教程19的新资讯,同时我们还将为您解释电脑维修视频教程20讲的相关在本文中,我们将带你探索Tagxp_电脑维修视频教程19的奥秘,分析电脑维修视频教程20讲的特点,并给出一些关于ibm有哪些电脑维修点 ibm电脑维修方法及维修点介绍、Tagxp_电脑维修视频教程1、Tagxp_电脑维修视频教程10、Tagxp_电脑维修视频教程11的实用技巧。

本文目录一览:

Tagxp_电脑维修视频教程19(电脑维修视频教程20讲)

Tagxp_电脑维修视频教程19(电脑维修视频教程20讲)

现在电脑已经开始普及到千家万户,如同电视机一样,慢慢的几乎每家每户都会买电脑。电脑用久了自然也

会出一些小毛病,电脑维修的需求也是很大的,不管你是想专业学修电脑,还是自己学点维修知识,本教程都

非常适合你看看,本教程是栾京老师的电脑维修视频教程,讲得非常好。容易理解,可以带你学修电脑入门。

学完本教程,以后再经过实践,相信你的经验会越来越多。

ibm有哪些电脑维修点 ibm电脑维修方法及维修点介绍

ibm有哪些电脑维修点 ibm电脑维修方法及维修点介绍

ibm电脑是属于商务型的电脑,由于ibm电脑在相同情况下比其他品牌的电脑安全性更高,因此在更多的商务人士更更愿意使用ibm电脑。但是我们应该知道,任何一款产品,即便质量品牌再怎么好,使用的时间久了,难免会有一些小故障出现。所以今天小编重点想为大家介绍一下ibm电脑维修方法的相关信息,希望在您在使用ibm电脑的工作之余,可以帮助到您。

ibm电脑的故障判断:

1.ibm电脑议案假如在开机后没有影像,或者是影像一直在闪烁,偶尔还有就是ibm电脑的屏幕会在闪光,这时候最有可能的是ibm电脑的背光板出现问题了。

2.ibm电脑如有出现开不了机的情况,主要可能是ibm电脑的cpu程序出现紊乱,程序的紊乱是很多电脑很常见的一种问题。

3.在使用ibm电脑的时候,当ibm 电脑开机 后,ibm电脑的屏幕上出现了 马赛克 了,有时候可以重启消失,偶尔一直在屏幕上。这主要可能是这ibm电脑内连线交错的情况。

4.ibm电脑在开始或者是使用一段时间后出现突然图像没有了的状况,需要检查电源电路有没有断路,如果没有。有可能是电源板烧坏了。

@H_301_19@

ibm电脑维修方法:

1.在ibm电脑出现黑屏或者是花屏的时候,首先进行ibm电脑的重启,如果正常了就搞定。如果还是存在这样的状况,不要随意的拆开机身,这时候需要找到专业的维修人士。当然啦,也有可能是温度过高导致的黑屏,可以给ibm电脑降温,然后再开机。

2.如果ibm电脑的屏幕有出现部分图像花掉的情况,检查逻辑 电路板 是否接触不良,也有可能是信号板出现问题,需要更换。

3.当ibm电脑出现在使用或者是开机后出现没光,没声音,查看光管老化程度如何,如果自己有关管可以自己进行更换的。注意这时候需要将高压板上的电路的取消,主要是为了保护ibm电脑。

4.ibm电脑的屏幕出现彩色的斑点,这样的情况可以先选择检查电路是否短路。假如电路正常,可能需要在ibm电脑里面更换一个电源保护器或者类型的装置。

ibm电脑维修点:

深圳市 深圳

电话:0755-26450457

地址:深圳市南山大道1175号新绿岛大厦4A03室

广州市 广州

电话:020-82607276

地址:广州市新塘镇新塘大道6号新康 花园 南 门 B区38号铺

最后,我们都想要自己的一些空间与秘密,相对于其他的电脑,ibm电脑的安全性上是肯定有保障的。如果的有自己需要保护的商务文件之类的,这款电脑是很适合的,而且不要是在工作还是生活的娱乐方面,ibm电脑的电脑也是在其他功能上得到的充分的体现。以上所列举的关于ibm电脑维修方法介绍,希望对大家有帮助。

Tagxp_电脑维修视频教程1

Tagxp_电脑维修视频教程1

现在电脑已经开始普及到千家万户,如同电视机一样,慢慢的几乎每家每户都会买电脑。电脑用久了自然也

会出一些小毛病,的需求也是很大的,不管你是想专业学修电脑,还是自己学点电脑维修知识,本教程都

非常适合你看看,本教程是栾京老师的电脑维修视频教程,讲得非常好。容易理解,可以带你学修电脑入门。

学完本教程,以后再经过实践,相信你的经验会越来越多。

Tagxp_电脑维修视频教程10

Tagxp_电脑维修视频教程10

现在电脑已经开始普及到千家万户,如同电视机一样,慢慢的几乎每家每户都会买电脑。电脑用久了自然也

会出一些小毛病,电脑维修的需求也是很大的,不管你是想专业学修电脑,还是自己学点电脑维修知识,本教程都

非常适合你看看,本教程是栾京老师的电脑维修视频教程,讲得非常好。容易理解,可以带你学修电脑入门。

学完本教程,以后再经过实践,相信你的经验会越来越多。

Tagxp_电脑维修视频教程11

Tagxp_电脑维修视频教程11

现在电脑已经开始普及到千家万户,如同电视机一样,慢慢的几乎每家每户都会买电脑。电脑用久了自然也

会出一些小毛病,电脑维修的需求也是很大的,不管你是想专业学修电脑,还是自己学点维修知识,本教程都

非常适合你看看,本教程是栾京老师的电脑维修视频教程,讲得非常好。容易理解,可以带你学修电脑入门。

学完本教程,以后再经过实践,相信你的经验会越来越多。


今天关于Tagxp_电脑维修视频教程19电脑维修视频教程20讲的分享就到这里,希望大家有所收获,若想了解更多关于ibm有哪些电脑维修点 ibm电脑维修方法及维修点介绍、Tagxp_电脑维修视频教程1、Tagxp_电脑维修视频教程10、Tagxp_电脑维修视频教程11等相关知识,可以在本站进行查询。

本篇文章给大家谈谈Tagxp_电脑维修视频教程18,以及电脑维修视频教程20讲的知识点,同时本文还将给你拓展ibm有哪些电脑维修点 ibm电脑维修方法及维修点介绍、Tagxp_电脑维修视频教程1、Tagxp_电脑维修视频教程10、Tagxp_电脑维修视频教程11等相关知识,希望对各位有所帮助,不要忘了收藏本站喔。

本文目录一览:

Tagxp_电脑维修视频教程18(电脑维修视频教程20讲)

Tagxp_电脑维修视频教程18(电脑维修视频教程20讲)

现在电脑已经开始普及到千家万户,如同电视机一样,慢慢的几乎每家每户都会买电脑。电脑用久了自然也

会出一些小毛病,电脑维修的需求也是很大的,不管你是想专业学修电脑,还是自己学点维修知识,本教程都

非常适合你看看,本教程是栾京老师的电脑维修视频教程,讲得非常好。容易理解,可以带你学修电脑入门。

学完本教程,以后再经过实践,相信你的经验会越来越多。

ibm有哪些电脑维修点 ibm电脑维修方法及维修点介绍

ibm有哪些电脑维修点 ibm电脑维修方法及维修点介绍

ibm电脑是属于商务型的电脑,由于ibm电脑在相同情况下比其他品牌的电脑安全性更高,因此在更多的商务人士更更愿意使用ibm电脑。但是我们应该知道,任何一款产品,即便质量品牌再怎么好,使用的时间久了,难免会有一些小故障出现。所以今天小编重点想为大家介绍一下ibm电脑维修方法的相关信息,希望在您在使用ibm电脑的工作之余,可以帮助到您。

ibm电脑的故障判断:

1.ibm电脑议案假如在开机后没有影像,或者是影像一直在闪烁,偶尔还有就是ibm电脑的屏幕会在闪光,这时候最有可能的是ibm电脑的背光板出现问题了。

2.ibm电脑如有出现开不了机的情况,主要可能是ibm电脑的cpu程序出现紊乱,程序的紊乱是很多电脑很常见的一种问题。

3.在使用ibm电脑的时候,当ibm 电脑开机 后,ibm电脑的屏幕上出现了 马赛克 了,有时候可以重启消失,偶尔一直在屏幕上。这主要可能是这ibm电脑内连线交错的情况。

4.ibm电脑在开始或者是使用一段时间后出现突然图像没有了的状况,需要检查电源电路有没有断路,如果没有。有可能是电源板烧坏了。

@H_301_19@

ibm电脑维修方法:

1.在ibm电脑出现黑屏或者是花屏的时候,首先进行ibm电脑的重启,如果正常了就搞定。如果还是存在这样的状况,不要随意的拆开机身,这时候需要找到专业的维修人士。当然啦,也有可能是温度过高导致的黑屏,可以给ibm电脑降温,然后再开机。

2.如果ibm电脑的屏幕有出现部分图像花掉的情况,检查逻辑 电路板 是否接触不良,也有可能是信号板出现问题,需要更换。

3.当ibm电脑出现在使用或者是开机后出现没光,没声音,查看光管老化程度如何,如果自己有关管可以自己进行更换的。注意这时候需要将高压板上的电路的取消,主要是为了保护ibm电脑。

4.ibm电脑的屏幕出现彩色的斑点,这样的情况可以先选择检查电路是否短路。假如电路正常,可能需要在ibm电脑里面更换一个电源保护器或者类型的装置。

ibm电脑维修点:

深圳市 深圳

电话:0755-26450457

地址:深圳市南山大道1175号新绿岛大厦4A03室

广州市 广州

电话:020-82607276

地址:广州市新塘镇新塘大道6号新康 花园 南 门 B区38号铺

最后,我们都想要自己的一些空间与秘密,相对于其他的电脑,ibm电脑的安全性上是肯定有保障的。如果的有自己需要保护的商务文件之类的,这款电脑是很适合的,而且不要是在工作还是生活的娱乐方面,ibm电脑的电脑也是在其他功能上得到的充分的体现。以上所列举的关于ibm电脑维修方法介绍,希望对大家有帮助。

Tagxp_电脑维修视频教程1

Tagxp_电脑维修视频教程1

现在电脑已经开始普及到千家万户,如同电视机一样,慢慢的几乎每家每户都会买电脑。电脑用久了自然也

会出一些小毛病,的需求也是很大的,不管你是想专业学修电脑,还是自己学点电脑维修知识,本教程都

非常适合你看看,本教程是栾京老师的电脑维修视频教程,讲得非常好。容易理解,可以带你学修电脑入门。

学完本教程,以后再经过实践,相信你的经验会越来越多。

Tagxp_电脑维修视频教程10

Tagxp_电脑维修视频教程10

现在电脑已经开始普及到千家万户,如同电视机一样,慢慢的几乎每家每户都会买电脑。电脑用久了自然也

会出一些小毛病,电脑维修的需求也是很大的,不管你是想专业学修电脑,还是自己学点电脑维修知识,本教程都

非常适合你看看,本教程是栾京老师的电脑维修视频教程,讲得非常好。容易理解,可以带你学修电脑入门。

学完本教程,以后再经过实践,相信你的经验会越来越多。

Tagxp_电脑维修视频教程11

Tagxp_电脑维修视频教程11

现在电脑已经开始普及到千家万户,如同电视机一样,慢慢的几乎每家每户都会买电脑。电脑用久了自然也

会出一些小毛病,电脑维修的需求也是很大的,不管你是想专业学修电脑,还是自己学点维修知识,本教程都

非常适合你看看,本教程是栾京老师的电脑维修视频教程,讲得非常好。容易理解,可以带你学修电脑入门。

学完本教程,以后再经过实践,相信你的经验会越来越多。


关于Tagxp_电脑维修视频教程18电脑维修视频教程20讲的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于ibm有哪些电脑维修点 ibm电脑维修方法及维修点介绍、Tagxp_电脑维修视频教程1、Tagxp_电脑维修视频教程10、Tagxp_电脑维修视频教程11等相关知识的信息别忘了在本站进行查找喔。

在这里,我们将给大家分享关于Tagxp_电脑维修视频教程17的知识,让您更了解电脑维修视频教程20讲的本质,同时也会涉及到如何更有效地excel2007视频教程17_获取外部数据、ibm有哪些电脑维修点 ibm电脑维修方法及维修点介绍、Tagxp_电脑维修视频教程1、Tagxp_电脑维修视频教程10的内容。

本文目录一览:

Tagxp_电脑维修视频教程17(电脑维修视频教程20讲)

Tagxp_电脑维修视频教程17(电脑维修视频教程20讲)

现在电脑已经开始普及到千家万户,如同电视机一样,慢慢的几乎每家每户都会买电脑。电脑用久了自然也

会出一些小毛病,电脑维修的需求也是很大的,不管你是想专业学修电脑,还是自己学点电脑维修知识,本教程都

非常适合你看看,本教程是栾京老师的电脑维修视频教程,讲得非常好。容易理解,可以带你学修电脑入门。

学完本教程,以后再经过实践,相信你的经验会越来越多。


excel2007视频教程17_获取外部数据

excel2007视频教程17_获取外部数据

Excel是Microsoft Office system中的电子表格程序。您可以使用 Excel 创建工作簿(电子表格集合)并设置工作簿格式,以便分析数据和做出更明智的业务决策。特别是,您可以使用 Excel 跟踪数据,生成数据分析模型,编写公式以对数据进行计算,以多种方式分析数据,并以各种具有专业外观的图表来显示数据。简而言之:Excel是用来更方便处理数据的办公软件。
  Excel的一般用途包括:会计专用、预算、帐单和销售、报表、计划跟踪 、使用日历等。

Excel2007视频教程包括34小节。高清视频讲解,老师讲课风格幽默风趣。

excel2007视频教程17_获取外部数据

ibm有哪些电脑维修点 ibm电脑维修方法及维修点介绍

ibm有哪些电脑维修点 ibm电脑维修方法及维修点介绍

ibm电脑是属于商务型的电脑,由于ibm电脑在相同情况下比其他品牌的电脑安全性更高,因此在更多的商务人士更更愿意使用ibm电脑。但是我们应该知道,任何一款产品,即便质量品牌再怎么好,使用的时间久了,难免会有一些小故障出现。所以今天小编重点想为大家介绍一下ibm电脑维修方法的相关信息,希望在您在使用ibm电脑的工作之余,可以帮助到您。

ibm电脑的故障判断:

1.ibm电脑议案假如在开机后没有影像,或者是影像一直在闪烁,偶尔还有就是ibm电脑的屏幕会在闪光,这时候最有可能的是ibm电脑的背光板出现问题了。

2.ibm电脑如有出现开不了机的情况,主要可能是ibm电脑的cpu程序出现紊乱,程序的紊乱是很多电脑很常见的一种问题。

3.在使用ibm电脑的时候,当ibm 电脑开机 后,ibm电脑的屏幕上出现了 马赛克 了,有时候可以重启消失,偶尔一直在屏幕上。这主要可能是这ibm电脑内连线交错的情况。

4.ibm电脑在开始或者是使用一段时间后出现突然图像没有了的状况,需要检查电源电路有没有断路,如果没有。有可能是电源板烧坏了。

@H_301_19@

ibm电脑维修方法:

1.在ibm电脑出现黑屏或者是花屏的时候,首先进行ibm电脑的重启,如果正常了就搞定。如果还是存在这样的状况,不要随意的拆开机身,这时候需要找到专业的维修人士。当然啦,也有可能是温度过高导致的黑屏,可以给ibm电脑降温,然后再开机。

2.如果ibm电脑的屏幕有出现部分图像花掉的情况,检查逻辑 电路板 是否接触不良,也有可能是信号板出现问题,需要更换。

3.当ibm电脑出现在使用或者是开机后出现没光,没声音,查看光管老化程度如何,如果自己有关管可以自己进行更换的。注意这时候需要将高压板上的电路的取消,主要是为了保护ibm电脑。

4.ibm电脑的屏幕出现彩色的斑点,这样的情况可以先选择检查电路是否短路。假如电路正常,可能需要在ibm电脑里面更换一个电源保护器或者类型的装置。

ibm电脑维修点:

深圳市 深圳

电话:0755-26450457

地址:深圳市南山大道1175号新绿岛大厦4A03室

广州市 广州

电话:020-82607276

地址:广州市新塘镇新塘大道6号新康 花园 南 门 B区38号铺

最后,我们都想要自己的一些空间与秘密,相对于其他的电脑,ibm电脑的安全性上是肯定有保障的。如果的有自己需要保护的商务文件之类的,这款电脑是很适合的,而且不要是在工作还是生活的娱乐方面,ibm电脑的电脑也是在其他功能上得到的充分的体现。以上所列举的关于ibm电脑维修方法介绍,希望对大家有帮助。

Tagxp_电脑维修视频教程1

Tagxp_电脑维修视频教程1

现在电脑已经开始普及到千家万户,如同电视机一样,慢慢的几乎每家每户都会买电脑。电脑用久了自然也

会出一些小毛病,的需求也是很大的,不管你是想专业学修电脑,还是自己学点电脑维修知识,本教程都

非常适合你看看,本教程是栾京老师的电脑维修视频教程,讲得非常好。容易理解,可以带你学修电脑入门。

学完本教程,以后再经过实践,相信你的经验会越来越多。

Tagxp_电脑维修视频教程10

Tagxp_电脑维修视频教程10

现在电脑已经开始普及到千家万户,如同电视机一样,慢慢的几乎每家每户都会买电脑。电脑用久了自然也

会出一些小毛病,电脑维修的需求也是很大的,不管你是想专业学修电脑,还是自己学点电脑维修知识,本教程都

非常适合你看看,本教程是栾京老师的电脑维修视频教程,讲得非常好。容易理解,可以带你学修电脑入门。

学完本教程,以后再经过实践,相信你的经验会越来越多。

关于Tagxp_电脑维修视频教程17电脑维修视频教程20讲的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于excel2007视频教程17_获取外部数据、ibm有哪些电脑维修点 ibm电脑维修方法及维修点介绍、Tagxp_电脑维修视频教程1、Tagxp_电脑维修视频教程10等相关知识的信息别忘了在本站进行查找喔。

对于Tagxp_电脑维修视频教程16感兴趣的读者,本文将提供您所需要的所有信息,我们将详细讲解电脑维修视频教程20讲,并且为您提供关于ibm有哪些电脑维修点 ibm电脑维修方法及维修点介绍、Tagxp_电脑维修视频教程1、Tagxp_电脑维修视频教程10、Tagxp_电脑维修视频教程11的宝贵知识。

本文目录一览:

Tagxp_电脑维修视频教程16(电脑维修视频教程20讲)

Tagxp_电脑维修视频教程16(电脑维修视频教程20讲)

现在电脑已经开始普及到千家万户,如同电视机一样,慢慢的几乎每家每户都会买电脑。电脑用久了自然也

会出一些小毛病,电脑维修的需求也是很大的,不管你是想专业学修电脑,还是自己学点维修知识,本教程都

非常适合你看看,本教程是栾京老师的电脑维修视频教程,讲得非常好。容易理解,可以带你学修电脑入门。

学完本教程,以后再经过实践,相信你的经验会越来越多。

ibm有哪些电脑维修点 ibm电脑维修方法及维修点介绍

ibm有哪些电脑维修点 ibm电脑维修方法及维修点介绍

ibm电脑是属于商务型的电脑,由于ibm电脑在相同情况下比其他品牌的电脑安全性更高,因此在更多的商务人士更更愿意使用ibm电脑。但是我们应该知道,任何一款产品,即便质量品牌再怎么好,使用的时间久了,难免会有一些小故障出现。所以今天小编重点想为大家介绍一下ibm电脑维修方法的相关信息,希望在您在使用ibm电脑的工作之余,可以帮助到您。

ibm电脑的故障判断:

1.ibm电脑议案假如在开机后没有影像,或者是影像一直在闪烁,偶尔还有就是ibm电脑的屏幕会在闪光,这时候最有可能的是ibm电脑的背光板出现问题了。

2.ibm电脑如有出现开不了机的情况,主要可能是ibm电脑的cpu程序出现紊乱,程序的紊乱是很多电脑很常见的一种问题。

3.在使用ibm电脑的时候,当ibm 电脑开机 后,ibm电脑的屏幕上出现了 马赛克 了,有时候可以重启消失,偶尔一直在屏幕上。这主要可能是这ibm电脑内连线交错的情况。

4.ibm电脑在开始或者是使用一段时间后出现突然图像没有了的状况,需要检查电源电路有没有断路,如果没有。有可能是电源板烧坏了。

@H_301_19@

ibm电脑维修方法:

1.在ibm电脑出现黑屏或者是花屏的时候,首先进行ibm电脑的重启,如果正常了就搞定。如果还是存在这样的状况,不要随意的拆开机身,这时候需要找到专业的维修人士。当然啦,也有可能是温度过高导致的黑屏,可以给ibm电脑降温,然后再开机。

2.如果ibm电脑的屏幕有出现部分图像花掉的情况,检查逻辑 电路板 是否接触不良,也有可能是信号板出现问题,需要更换。

3.当ibm电脑出现在使用或者是开机后出现没光,没声音,查看光管老化程度如何,如果自己有关管可以自己进行更换的。注意这时候需要将高压板上的电路的取消,主要是为了保护ibm电脑。

4.ibm电脑的屏幕出现彩色的斑点,这样的情况可以先选择检查电路是否短路。假如电路正常,可能需要在ibm电脑里面更换一个电源保护器或者类型的装置。

ibm电脑维修点:

深圳市 深圳

电话:0755-26450457

地址:深圳市南山大道1175号新绿岛大厦4A03室

广州市 广州

电话:020-82607276

地址:广州市新塘镇新塘大道6号新康 花园 南 门 B区38号铺

最后,我们都想要自己的一些空间与秘密,相对于其他的电脑,ibm电脑的安全性上是肯定有保障的。如果的有自己需要保护的商务文件之类的,这款电脑是很适合的,而且不要是在工作还是生活的娱乐方面,ibm电脑的电脑也是在其他功能上得到的充分的体现。以上所列举的关于ibm电脑维修方法介绍,希望对大家有帮助。

Tagxp_电脑维修视频教程1

Tagxp_电脑维修视频教程1

现在电脑已经开始普及到千家万户,如同电视机一样,慢慢的几乎每家每户都会买电脑。电脑用久了自然也

会出一些小毛病,的需求也是很大的,不管你是想专业学修电脑,还是自己学点电脑维修知识,本教程都

非常适合你看看,本教程是栾京老师的电脑维修视频教程,讲得非常好。容易理解,可以带你学修电脑入门。

学完本教程,以后再经过实践,相信你的经验会越来越多。

Tagxp_电脑维修视频教程10

Tagxp_电脑维修视频教程10

现在电脑已经开始普及到千家万户,如同电视机一样,慢慢的几乎每家每户都会买电脑。电脑用久了自然也

会出一些小毛病,电脑维修的需求也是很大的,不管你是想专业学修电脑,还是自己学点电脑维修知识,本教程都

非常适合你看看,本教程是栾京老师的电脑维修视频教程,讲得非常好。容易理解,可以带你学修电脑入门。

学完本教程,以后再经过实践,相信你的经验会越来越多。

Tagxp_电脑维修视频教程11

Tagxp_电脑维修视频教程11

现在电脑已经开始普及到千家万户,如同电视机一样,慢慢的几乎每家每户都会买电脑。电脑用久了自然也

会出一些小毛病,电脑维修的需求也是很大的,不管你是想专业学修电脑,还是自己学点维修知识,本教程都

非常适合你看看,本教程是栾京老师的电脑维修视频教程,讲得非常好。容易理解,可以带你学修电脑入门。

学完本教程,以后再经过实践,相信你的经验会越来越多。


今天关于Tagxp_电脑维修视频教程16电脑维修视频教程20讲的介绍到此结束,谢谢您的阅读,有关ibm有哪些电脑维修点 ibm电脑维修方法及维修点介绍、Tagxp_电脑维修视频教程1、Tagxp_电脑维修视频教程10、Tagxp_电脑维修视频教程11等更多相关知识的信息可以在本站进行查询。

本文将介绍Tagxp_电脑维修视频教程15的详细情况,特别是关于电脑维修视频教程20讲的相关信息。我们将通过案例分析、数据研究等多种方式,帮助您更全面地了解这个主题,同时也将涉及一些关于ibm有哪些电脑维修点 ibm电脑维修方法及维修点介绍、Tagxp_电脑维修视频教程1、Tagxp_电脑维修视频教程10、Tagxp_电脑维修视频教程11的知识。

本文目录一览:

Tagxp_电脑维修视频教程15(电脑维修视频教程20讲)

Tagxp_电脑维修视频教程15(电脑维修视频教程20讲)

现在电脑已经开始普及到千家万户,如同电视机一样,慢慢的几乎每家每户都会买电脑。电脑用久了自然也

会出一些小毛病,电脑维修的需求也是很大的,不管你是想专业学修电脑,还是自己学点维修知识,本教程都

非常适合你看看,本教程是栾京老师的电脑维修视频教程,讲得非常好。容易理解,可以带你学修电脑入门。

学完本教程,以后再经过实践,相信你的经验会越来越多。

ibm有哪些电脑维修点 ibm电脑维修方法及维修点介绍

ibm有哪些电脑维修点 ibm电脑维修方法及维修点介绍

ibm电脑是属于商务型的电脑,由于ibm电脑在相同情况下比其他品牌的电脑安全性更高,因此在更多的商务人士更更愿意使用ibm电脑。但是我们应该知道,任何一款产品,即便质量品牌再怎么好,使用的时间久了,难免会有一些小故障出现。所以今天小编重点想为大家介绍一下ibm电脑维修方法的相关信息,希望在您在使用ibm电脑的工作之余,可以帮助到您。

ibm电脑的故障判断:

1.ibm电脑议案假如在开机后没有影像,或者是影像一直在闪烁,偶尔还有就是ibm电脑的屏幕会在闪光,这时候最有可能的是ibm电脑的背光板出现问题了。

2.ibm电脑如有出现开不了机的情况,主要可能是ibm电脑的cpu程序出现紊乱,程序的紊乱是很多电脑很常见的一种问题。

3.在使用ibm电脑的时候,当ibm 电脑开机 后,ibm电脑的屏幕上出现了 马赛克 了,有时候可以重启消失,偶尔一直在屏幕上。这主要可能是这ibm电脑内连线交错的情况。

4.ibm电脑在开始或者是使用一段时间后出现突然图像没有了的状况,需要检查电源电路有没有断路,如果没有。有可能是电源板烧坏了。

@H_301_19@

ibm电脑维修方法:

1.在ibm电脑出现黑屏或者是花屏的时候,首先进行ibm电脑的重启,如果正常了就搞定。如果还是存在这样的状况,不要随意的拆开机身,这时候需要找到专业的维修人士。当然啦,也有可能是温度过高导致的黑屏,可以给ibm电脑降温,然后再开机。

2.如果ibm电脑的屏幕有出现部分图像花掉的情况,检查逻辑 电路板 是否接触不良,也有可能是信号板出现问题,需要更换。

3.当ibm电脑出现在使用或者是开机后出现没光,没声音,查看光管老化程度如何,如果自己有关管可以自己进行更换的。注意这时候需要将高压板上的电路的取消,主要是为了保护ibm电脑。

4.ibm电脑的屏幕出现彩色的斑点,这样的情况可以先选择检查电路是否短路。假如电路正常,可能需要在ibm电脑里面更换一个电源保护器或者类型的装置。

ibm电脑维修点:

深圳市 深圳

电话:0755-26450457

地址:深圳市南山大道1175号新绿岛大厦4A03室

广州市 广州

电话:020-82607276

地址:广州市新塘镇新塘大道6号新康 花园 南 门 B区38号铺

最后,我们都想要自己的一些空间与秘密,相对于其他的电脑,ibm电脑的安全性上是肯定有保障的。如果的有自己需要保护的商务文件之类的,这款电脑是很适合的,而且不要是在工作还是生活的娱乐方面,ibm电脑的电脑也是在其他功能上得到的充分的体现。以上所列举的关于ibm电脑维修方法介绍,希望对大家有帮助。

Tagxp_电脑维修视频教程1

Tagxp_电脑维修视频教程1

现在电脑已经开始普及到千家万户,如同电视机一样,慢慢的几乎每家每户都会买电脑。电脑用久了自然也

会出一些小毛病,的需求也是很大的,不管你是想专业学修电脑,还是自己学点电脑维修知识,本教程都

非常适合你看看,本教程是栾京老师的电脑维修视频教程,讲得非常好。容易理解,可以带你学修电脑入门。

学完本教程,以后再经过实践,相信你的经验会越来越多。

Tagxp_电脑维修视频教程10

Tagxp_电脑维修视频教程10

现在电脑已经开始普及到千家万户,如同电视机一样,慢慢的几乎每家每户都会买电脑。电脑用久了自然也

会出一些小毛病,电脑维修的需求也是很大的,不管你是想专业学修电脑,还是自己学点电脑维修知识,本教程都

非常适合你看看,本教程是栾京老师的电脑维修视频教程,讲得非常好。容易理解,可以带你学修电脑入门。

学完本教程,以后再经过实践,相信你的经验会越来越多。

Tagxp_电脑维修视频教程11

Tagxp_电脑维修视频教程11

现在电脑已经开始普及到千家万户,如同电视机一样,慢慢的几乎每家每户都会买电脑。电脑用久了自然也

会出一些小毛病,电脑维修的需求也是很大的,不管你是想专业学修电脑,还是自己学点维修知识,本教程都

非常适合你看看,本教程是栾京老师的电脑维修视频教程,讲得非常好。容易理解,可以带你学修电脑入门。

学完本教程,以后再经过实践,相信你的经验会越来越多。


关于Tagxp_电脑维修视频教程15电脑维修视频教程20讲的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于ibm有哪些电脑维修点 ibm电脑维修方法及维修点介绍、Tagxp_电脑维修视频教程1、Tagxp_电脑维修视频教程10、Tagxp_电脑维修视频教程11的相关信息,请在本站寻找。

针对Tagxp_电脑维修视频教程14电脑维修视频教程20讲这两个问题,本篇文章进行了详细的解答,同时本文还将给你拓展excel2007视频教程14_分类汇总、ibm有哪些电脑维修点 ibm电脑维修方法及维修点介绍、Tagxp_电脑维修视频教程1、Tagxp_电脑维修视频教程10等相关知识,希望可以帮助到你。

本文目录一览:

Tagxp_电脑维修视频教程14(电脑维修视频教程20讲)

Tagxp_电脑维修视频教程14(电脑维修视频教程20讲)

现在电脑已经开始普及到千家万户,如同电视机一样,慢慢的几乎每家每户都会买电脑。电脑用久了自然也

会出一些小毛病,电脑维修的需求也是很大的,不管你是想专业学修电脑,还是自己学点电脑维修知识,本教程都

非常适合你看看,本教程是栾京老师的电脑维修视频教程,讲得非常好。容易理解,可以带你学修电脑入门。

学完本教程,以后再经过实践,相信你的经验会越来越多。

excel2007视频教程14_分类汇总

excel2007视频教程14_分类汇总

Excel是Microsoft Office system中的电子表格程序。您可以使用 Excel 创建工作簿(电子表格集合)并设置工作簿格式,以便分析数据和做出更明智的业务决策。特别是,您可以使用 Excel 跟踪数据,生成数据分析模型,编写公式以对数据进行计算,以多种方式分析数据,并以各种具有专业外观的图表来显示数据。简而言之:Excel是用来更方便处理数据的办公软件。
  Excel的一般用途包括:会计专用、预算、帐单和销售、报表、计划跟踪 、使用日历等。

Excel2007视频教程包括34小节。高清视频讲解,老师讲课风格幽默风趣。

excel2007视频教程14_分类汇总

ibm有哪些电脑维修点 ibm电脑维修方法及维修点介绍

ibm有哪些电脑维修点 ibm电脑维修方法及维修点介绍

ibm电脑是属于商务型的电脑,由于ibm电脑在相同情况下比其他品牌的电脑安全性更高,因此在更多的商务人士更更愿意使用ibm电脑。但是我们应该知道,任何一款产品,即便质量品牌再怎么好,使用的时间久了,难免会有一些小故障出现。所以今天小编重点想为大家介绍一下ibm电脑维修方法的相关信息,希望在您在使用ibm电脑的工作之余,可以帮助到您。

ibm电脑的故障判断:

1.ibm电脑议案假如在开机后没有影像,或者是影像一直在闪烁,偶尔还有就是ibm电脑的屏幕会在闪光,这时候最有可能的是ibm电脑的背光板出现问题了。

2.ibm电脑如有出现开不了机的情况,主要可能是ibm电脑的cpu程序出现紊乱,程序的紊乱是很多电脑很常见的一种问题。

3.在使用ibm电脑的时候,当ibm 电脑开机 后,ibm电脑的屏幕上出现了 马赛克 了,有时候可以重启消失,偶尔一直在屏幕上。这主要可能是这ibm电脑内连线交错的情况。

4.ibm电脑在开始或者是使用一段时间后出现突然图像没有了的状况,需要检查电源电路有没有断路,如果没有。有可能是电源板烧坏了。

@H_301_19@

ibm电脑维修方法:

1.在ibm电脑出现黑屏或者是花屏的时候,首先进行ibm电脑的重启,如果正常了就搞定。如果还是存在这样的状况,不要随意的拆开机身,这时候需要找到专业的维修人士。当然啦,也有可能是温度过高导致的黑屏,可以给ibm电脑降温,然后再开机。

2.如果ibm电脑的屏幕有出现部分图像花掉的情况,检查逻辑 电路板 是否接触不良,也有可能是信号板出现问题,需要更换。

3.当ibm电脑出现在使用或者是开机后出现没光,没声音,查看光管老化程度如何,如果自己有关管可以自己进行更换的。注意这时候需要将高压板上的电路的取消,主要是为了保护ibm电脑。

4.ibm电脑的屏幕出现彩色的斑点,这样的情况可以先选择检查电路是否短路。假如电路正常,可能需要在ibm电脑里面更换一个电源保护器或者类型的装置。

ibm电脑维修点:

深圳市 深圳

电话:0755-26450457

地址:深圳市南山大道1175号新绿岛大厦4A03室

广州市 广州

电话:020-82607276

地址:广州市新塘镇新塘大道6号新康 花园 南 门 B区38号铺

最后,我们都想要自己的一些空间与秘密,相对于其他的电脑,ibm电脑的安全性上是肯定有保障的。如果的有自己需要保护的商务文件之类的,这款电脑是很适合的,而且不要是在工作还是生活的娱乐方面,ibm电脑的电脑也是在其他功能上得到的充分的体现。以上所列举的关于ibm电脑维修方法介绍,希望对大家有帮助。

Tagxp_电脑维修视频教程1

Tagxp_电脑维修视频教程1

现在电脑已经开始普及到千家万户,如同电视机一样,慢慢的几乎每家每户都会买电脑。电脑用久了自然也

会出一些小毛病,的需求也是很大的,不管你是想专业学修电脑,还是自己学点电脑维修知识,本教程都

非常适合你看看,本教程是栾京老师的电脑维修视频教程,讲得非常好。容易理解,可以带你学修电脑入门。

学完本教程,以后再经过实践,相信你的经验会越来越多。

Tagxp_电脑维修视频教程10

Tagxp_电脑维修视频教程10

现在电脑已经开始普及到千家万户,如同电视机一样,慢慢的几乎每家每户都会买电脑。电脑用久了自然也

会出一些小毛病,电脑维修的需求也是很大的,不管你是想专业学修电脑,还是自己学点电脑维修知识,本教程都

非常适合你看看,本教程是栾京老师的电脑维修视频教程,讲得非常好。容易理解,可以带你学修电脑入门。

学完本教程,以后再经过实践,相信你的经验会越来越多。

今天的关于Tagxp_电脑维修视频教程14电脑维修视频教程20讲的分享已经结束,谢谢您的关注,如果想了解更多关于excel2007视频教程14_分类汇总、ibm有哪些电脑维修点 ibm电脑维修方法及维修点介绍、Tagxp_电脑维修视频教程1、Tagxp_电脑维修视频教程10的相关知识,请在本站进行查询。

针对Tagxp_电脑维修视频教程13电脑维修视频教程20讲这两个问题,本篇文章进行了详细的解答,同时本文还将给你拓展excel2007视频教程13_打印、ibm有哪些电脑维修点 ibm电脑维修方法及维修点介绍、Tagxp_电脑维修视频教程1、Tagxp_电脑维修视频教程10等相关知识,希望可以帮助到你。

本文目录一览:

Tagxp_电脑维修视频教程13(电脑维修视频教程20讲)

Tagxp_电脑维修视频教程13(电脑维修视频教程20讲)

现在电脑已经开始普及到千家万户,如同电视机一样,慢慢的几乎每家每户都会买电脑。电脑用久了自然也

会出一些小毛病,电脑维修的需求也是很大的,不管你是想专业学修电脑,还是自己学点维修知识,本教程都

非常适合你看看,本教程是栾京老师的电脑维修视频教程,讲得非常好。容易理解,可以带你学修电脑入门。

学完本教程,以后再经过实践,相信你的经验会越来越多。

excel2007视频教程13_打印

excel2007视频教程13_打印

Excel是Microsoft Office system中的电子表格程序。您可以使用 Excel 创建工作簿(电子表格集合)并设置工作簿格式,以便分析数据和做出更明智的业务决策。特别是,您可以使用 Excel 跟踪数据,生成数据分析模型,编写公式以对数据进行计算,以多种方式分析数据,并以各种具有专业外观的图表来显示数据。简而言之:Excel是用来更方便处理数据的办公软件。
  Excel的一般用途包括:会计专用、预算、帐单和销售、报表、计划跟踪 、使用日历等。

Excel2007视频教程包括34小节。高清视频讲解,老师讲课风格幽默风趣。

excel2007视频教程13_打印

ibm有哪些电脑维修点 ibm电脑维修方法及维修点介绍

ibm有哪些电脑维修点 ibm电脑维修方法及维修点介绍

ibm电脑是属于商务型的电脑,由于ibm电脑在相同情况下比其他品牌的电脑安全性更高,因此在更多的商务人士更更愿意使用ibm电脑。但是我们应该知道,任何一款产品,即便质量品牌再怎么好,使用的时间久了,难免会有一些小故障出现。所以今天小编重点想为大家介绍一下ibm电脑维修方法的相关信息,希望在您在使用ibm电脑的工作之余,可以帮助到您。

ibm电脑的故障判断:

1.ibm电脑议案假如在开机后没有影像,或者是影像一直在闪烁,偶尔还有就是ibm电脑的屏幕会在闪光,这时候最有可能的是ibm电脑的背光板出现问题了。

2.ibm电脑如有出现开不了机的情况,主要可能是ibm电脑的cpu程序出现紊乱,程序的紊乱是很多电脑很常见的一种问题。

3.在使用ibm电脑的时候,当ibm 电脑开机 后,ibm电脑的屏幕上出现了 马赛克 了,有时候可以重启消失,偶尔一直在屏幕上。这主要可能是这ibm电脑内连线交错的情况。

4.ibm电脑在开始或者是使用一段时间后出现突然图像没有了的状况,需要检查电源电路有没有断路,如果没有。有可能是电源板烧坏了。

@H_301_19@

ibm电脑维修方法:

1.在ibm电脑出现黑屏或者是花屏的时候,首先进行ibm电脑的重启,如果正常了就搞定。如果还是存在这样的状况,不要随意的拆开机身,这时候需要找到专业的维修人士。当然啦,也有可能是温度过高导致的黑屏,可以给ibm电脑降温,然后再开机。

2.如果ibm电脑的屏幕有出现部分图像花掉的情况,检查逻辑 电路板 是否接触不良,也有可能是信号板出现问题,需要更换。

3.当ibm电脑出现在使用或者是开机后出现没光,没声音,查看光管老化程度如何,如果自己有关管可以自己进行更换的。注意这时候需要将高压板上的电路的取消,主要是为了保护ibm电脑。

4.ibm电脑的屏幕出现彩色的斑点,这样的情况可以先选择检查电路是否短路。假如电路正常,可能需要在ibm电脑里面更换一个电源保护器或者类型的装置。

ibm电脑维修点:

深圳市 深圳

电话:0755-26450457

地址:深圳市南山大道1175号新绿岛大厦4A03室

广州市 广州

电话:020-82607276

地址:广州市新塘镇新塘大道6号新康 花园 南 门 B区38号铺

最后,我们都想要自己的一些空间与秘密,相对于其他的电脑,ibm电脑的安全性上是肯定有保障的。如果的有自己需要保护的商务文件之类的,这款电脑是很适合的,而且不要是在工作还是生活的娱乐方面,ibm电脑的电脑也是在其他功能上得到的充分的体现。以上所列举的关于ibm电脑维修方法介绍,希望对大家有帮助。

Tagxp_电脑维修视频教程1

Tagxp_电脑维修视频教程1

现在电脑已经开始普及到千家万户,如同电视机一样,慢慢的几乎每家每户都会买电脑。电脑用久了自然也

会出一些小毛病,的需求也是很大的,不管你是想专业学修电脑,还是自己学点电脑维修知识,本教程都

非常适合你看看,本教程是栾京老师的电脑维修视频教程,讲得非常好。容易理解,可以带你学修电脑入门。

学完本教程,以后再经过实践,相信你的经验会越来越多。

Tagxp_电脑维修视频教程10

Tagxp_电脑维修视频教程10

现在电脑已经开始普及到千家万户,如同电视机一样,慢慢的几乎每家每户都会买电脑。电脑用久了自然也

会出一些小毛病,电脑维修的需求也是很大的,不管你是想专业学修电脑,还是自己学点电脑维修知识,本教程都

非常适合你看看,本教程是栾京老师的电脑维修视频教程,讲得非常好。容易理解,可以带你学修电脑入门。

学完本教程,以后再经过实践,相信你的经验会越来越多。

今天关于Tagxp_电脑维修视频教程13电脑维修视频教程20讲的分享就到这里,希望大家有所收获,若想了解更多关于excel2007视频教程13_打印、ibm有哪些电脑维修点 ibm电脑维修方法及维修点介绍、Tagxp_电脑维修视频教程1、Tagxp_电脑维修视频教程10等相关知识,可以在本站进行查询。

对于想了解Tagxp_电脑维修视频教程12的读者,本文将是一篇不可错过的文章,我们将详细介绍电脑维修视频教程20讲,并且为您提供关于ibm有哪些电脑维修点 ibm电脑维修方法及维修点介绍、Tagxp_电脑维修视频教程1、Tagxp_电脑维修视频教程10、Tagxp_电脑维修视频教程11的有价值信息。

本文目录一览:

Tagxp_电脑维修视频教程12(电脑维修视频教程20讲)

Tagxp_电脑维修视频教程12(电脑维修视频教程20讲)

现在电脑已经开始普及到千家万户,如同电视机一样,慢慢的几乎每家每户都会买电脑。电脑用久了自然也

会出一些小毛病,电脑维修的需求也是很大的,不管你是想专业学修电脑,还是自己学点电脑维修知识,本教程都

非常适合你看看,本教程是栾京老师的电脑维修视频教程,讲得非常好。容易理解,可以带你学修电脑入门。

学完本教程,以后再经过实践,相信你的经验会越来越多。

ibm有哪些电脑维修点 ibm电脑维修方法及维修点介绍

ibm有哪些电脑维修点 ibm电脑维修方法及维修点介绍

ibm电脑是属于商务型的电脑,由于ibm电脑在相同情况下比其他品牌的电脑安全性更高,因此在更多的商务人士更更愿意使用ibm电脑。但是我们应该知道,任何一款产品,即便质量品牌再怎么好,使用的时间久了,难免会有一些小故障出现。所以今天小编重点想为大家介绍一下ibm电脑维修方法的相关信息,希望在您在使用ibm电脑的工作之余,可以帮助到您。

ibm电脑的故障判断:

1.ibm电脑议案假如在开机后没有影像,或者是影像一直在闪烁,偶尔还有就是ibm电脑的屏幕会在闪光,这时候最有可能的是ibm电脑的背光板出现问题了。

2.ibm电脑如有出现开不了机的情况,主要可能是ibm电脑的cpu程序出现紊乱,程序的紊乱是很多电脑很常见的一种问题。

3.在使用ibm电脑的时候,当ibm 电脑开机 后,ibm电脑的屏幕上出现了 马赛克 了,有时候可以重启消失,偶尔一直在屏幕上。这主要可能是这ibm电脑内连线交错的情况。

4.ibm电脑在开始或者是使用一段时间后出现突然图像没有了的状况,需要检查电源电路有没有断路,如果没有。有可能是电源板烧坏了。

@H_301_19@

ibm电脑维修方法:

1.在ibm电脑出现黑屏或者是花屏的时候,首先进行ibm电脑的重启,如果正常了就搞定。如果还是存在这样的状况,不要随意的拆开机身,这时候需要找到专业的维修人士。当然啦,也有可能是温度过高导致的黑屏,可以给ibm电脑降温,然后再开机。

2.如果ibm电脑的屏幕有出现部分图像花掉的情况,检查逻辑 电路板 是否接触不良,也有可能是信号板出现问题,需要更换。

3.当ibm电脑出现在使用或者是开机后出现没光,没声音,查看光管老化程度如何,如果自己有关管可以自己进行更换的。注意这时候需要将高压板上的电路的取消,主要是为了保护ibm电脑。

4.ibm电脑的屏幕出现彩色的斑点,这样的情况可以先选择检查电路是否短路。假如电路正常,可能需要在ibm电脑里面更换一个电源保护器或者类型的装置。

ibm电脑维修点:

深圳市 深圳

电话:0755-26450457

地址:深圳市南山大道1175号新绿岛大厦4A03室

广州市 广州

电话:020-82607276

地址:广州市新塘镇新塘大道6号新康 花园 南 门 B区38号铺

最后,我们都想要自己的一些空间与秘密,相对于其他的电脑,ibm电脑的安全性上是肯定有保障的。如果的有自己需要保护的商务文件之类的,这款电脑是很适合的,而且不要是在工作还是生活的娱乐方面,ibm电脑的电脑也是在其他功能上得到的充分的体现。以上所列举的关于ibm电脑维修方法介绍,希望对大家有帮助。

Tagxp_电脑维修视频教程1

Tagxp_电脑维修视频教程1

现在电脑已经开始普及到千家万户,如同电视机一样,慢慢的几乎每家每户都会买电脑。电脑用久了自然也

会出一些小毛病,的需求也是很大的,不管你是想专业学修电脑,还是自己学点电脑维修知识,本教程都

非常适合你看看,本教程是栾京老师的电脑维修视频教程,讲得非常好。容易理解,可以带你学修电脑入门。

学完本教程,以后再经过实践,相信你的经验会越来越多。

Tagxp_电脑维修视频教程10

Tagxp_电脑维修视频教程10

现在电脑已经开始普及到千家万户,如同电视机一样,慢慢的几乎每家每户都会买电脑。电脑用久了自然也

会出一些小毛病,电脑维修的需求也是很大的,不管你是想专业学修电脑,还是自己学点电脑维修知识,本教程都

非常适合你看看,本教程是栾京老师的电脑维修视频教程,讲得非常好。容易理解,可以带你学修电脑入门。

学完本教程,以后再经过实践,相信你的经验会越来越多。

Tagxp_电脑维修视频教程11

Tagxp_电脑维修视频教程11

现在电脑已经开始普及到千家万户,如同电视机一样,慢慢的几乎每家每户都会买电脑。电脑用久了自然也

会出一些小毛病,电脑维修的需求也是很大的,不管你是想专业学修电脑,还是自己学点维修知识,本教程都

非常适合你看看,本教程是栾京老师的电脑维修视频教程,讲得非常好。容易理解,可以带你学修电脑入门。

学完本教程,以后再经过实践,相信你的经验会越来越多。


今天的关于Tagxp_电脑维修视频教程12电脑维修视频教程20讲的分享已经结束,谢谢您的关注,如果想了解更多关于ibm有哪些电脑维修点 ibm电脑维修方法及维修点介绍、Tagxp_电脑维修视频教程1、Tagxp_电脑维修视频教程10、Tagxp_电脑维修视频教程11的相关知识,请在本站进行查询。

本文标签: