SQLite Database
SQLite is an embedded relational database engine. Its developers call it a self-contained, serverless, zero-configuration and transactional SQL database engine. 其实只需要记住SQLite不需要数据库服务器,不需要额外配置,其数据库本身就是一个文件的一个小型数据库。 通常情况下在android中创建数据库,系统会在”DATA/data/APP_NAME/databases”.目录为我们创建数据库文件。
SQLite BasicDataTypes
SQLite支持的数据类型有很多,但他们总共可以分为以下几类:
1. desc //查看表结构
2. select * from //查询所有更
3. select , from table ;//查看指定列
4. select distinct , from table ;//非重复查询
5. insert into users(_id,username,password) select * from users;//复制
6. select username from users where username like 'S%' ;//非重名字首字母为大写S的用户
7. select username from users where username like '__S%' ;//非重名字第三个字母为大写S的用户
8. select * from users where _id in(001,220,230);
9. select * from user order by _id;//以id的顺序排列
10. select * from user order by _id desc;//以id反的顺序排
复制代码
常用Select语句
1. desc //查看表结构
2. select * from //查询所有更
3. select , from table ;//查看指定列
4. select distinct , from table ;//非重复查询
5. insert into users(_id,username,password) select * from users;//复制
6. select username from users where username like 'S%' ;//非重名字首字母为大写S的用户
7. select username from users where username like '__S%' ;//非重名字第三个字母为大写S的用户
8. select * from users where _id in(001,220,230);
9. select * from user order by _id;//以id的顺序排列
10. select * from user order by _id desc;//以id反的顺序排
复制代码
图形环境
很少有人直接在程序当中直接编写SQL语句,麻烦且容易出错。所以最好应该先在一个图形化的环境把SQL语句写好,测试好再加入到代码当中。 而且,SQLite数据库本身就是一个独立的文件,很容易从模拟器上抓取出来。可以使用图形化界面进行分析,和修改 etc.
SQLite expert 是个简单小巧的SQLite数据库管理软件,有免费版和,收费版两种,一般来讲免费版足以应付我们需求。
sqliteexpert官方网址
软件界面截图
使用SQLite expert 创建一张table,并让它为我们生成所需的sql语句
下面的例子,我们创建一张表用来存储用户的用户名和密码;数据库名"users",表名"user_accounts",有三个列:row_id INTEGER自增类型的主键,usernameTEXT类型 用来保存用户名,passwordTEXT类型,用来保存用户密码;
创建表格
为了创建一张table 首先要有一个数据库文件,点击"File"->""New Database然后选择文件的路径,点击OK便创建了一个数据库文件 创建完数据库之后创建表格,右击数据库文件名选择"New Table"如下图所示:
这时我们便进入了"设计状态",填写表名(user_accounts),点击"Add",在Name中填写"row_id",Type选择Integer,如下图所示:
因为row_id这个列比较特殊是我们的索引的主键,所以还要点击"Index",之后会看到下图:
左边的Available Fields 中有我们刚刚创建的row_id,点击"Add"把row_id加入右边的Index Fields当中。这时上面的Primary和AutoIncrement会变成可先状态 ,勾选Primary和AutoIncrement点击OK;
再回到Field当中创建其它两列,分别为username类型为TEXT,password类型也为TEXT,但不需要创建Index; 完成之后点击Apply,这样我们便使用SQLite expert创建一张表格,点击DDL,我们可以看到SQLite expert已经为我们生成好了生成这张表格所需的SQL语句:
在android中需要代码生成表格时,只要把这段代码复制过去,就可以了。
增加用户
点击SQL,执行以下SQL语句,为表格增加一个用户:
1. INSERT INTO user_accounts(row_id,username,password) VALUES(001,'John','abcdef');
复制代码
点击Data会发现数据库里边增加了一个用户名为John的用户。为了练习,我们不妨再增加两个用户,David和Sarah
1. INSERT INTO user_accounts(row_id,username,password) VALUES(002,'David','123456');
2.
3. INSERT INTO user_accounts(row_id,username,password) VALUES(003,'Sarah','00000000');
复制代码
删除用户
执行下面的语句删除用户David:
- DELETE FROM user_accounts WHERE username = 'David';
复制代码
修改密码
执行以下语句修改Sarah的密码:
1. update user_accounts SET password='666666' WHERE username = 'Sarah';
复制代码
查看所用户信息可以使用如下语句查看表内所有用户的信息:
- SELECT * FROMM user_accounts;
复制代码
一般来讲select * 的语句只在测试的时候时候,在正式代码中不推荐使用。
查看指定列的内容执行以下语句查看所有用户的用户名和密码:
- SELECT username,password FROM user_accounts;
复制代码
这时个就发现row_id列没有显示出来。
查询特定条件的信息
SQL可以通过给定查询条件进行精确查找,比如我们只需要John的密码。就可以使用这样的语句
1. SELECT password FROM user_accounts WHERE username = 'John';
复制代码
以下流程图,来源于SQLite官方文档
Create Table Statement
column-def
type-name
column-constraint
table-constraint
foriegn-key-clause
Insert Statement
Delete Statement
qualified-table-name
Update Statement
qualified-table-name
Select Statement
select-core
result-column
join-source
single-source
join-op
join-constraint
ordering-term
compound-operator
Dealing with large amount of data分页当数据库数据量很大时,分页显示是个很简单且符合人们习惯的一种处理方法。
获取数据行总数:
最简单的方法是:SELECT所有的行,再调用curosr.getCount() ;取得行数,但这样效率会很低。 SQLite为我们提供了一个函数很容易查出总共有多少行。有个名为cet6_table的表格,我们想知道总共有多少行的word;可以使用如下 语句来完成:
1. SELECT count(word) AS number FROM cet6_table;
复制代码
count()函数为我们返回一个Int整形,代表有多少行数据。返回的列的名字叫count(word),为了方便阅读和处理用as number给这个列取个 别名number;
1. SELECT [word],[explanation] FROM cet6_table ORDER BY word LIMIT 100 OFFSET 200"
复制代码
上语句,返回自第200行的最多100条数据。分页时我们只要修改offset 后面的数据即可取得对应页面的数据。
详情见示例程序!
多线程自带数据库
有些程序比如,字典,输入法等程序会在apk中带有数据库。思路很简单,把预先准备好的数据库放入asset或者raw目录当中 使用时复制到对应的手机目录上;再打开。以下代码会把raw目录中的名为cet6的数据库文件写入sd卡根目录并打开。 对于一些常用或者比较重要的数据建议放在程序的私有目录当中。
1. public void init(Context context) {
2. try {
3. String databasePath = Environment.getExternalStorageDirectory().getAbsolutePath();
4. String databaseFilename = databasePath + "/" + DATABASE_FILENAME;
5. File dir = new File(databasePath);
6. if (!dir.exists()){
7. dir.mkdir();
8. }
9. if (!(new File(databaseFilename)).exists()) {
10. InputStream is = context.getResources().openRawResource(
11. R.raw.cet6);
12. FileOutputStream fos = new FileOutputStream(databaseFilename);
13. byte[] buffer = new byte[1024];
14. int count = 0;
15. while ((count = is.read(buffer)) > 0) {
16. fos.write(buffer, 0, count);
17. }
18. fos.flush();
19. fos.close();
20. is.close();
21. }
22. mCet6Db = SQLiteDatabase.openOrCreateDatabase(databaseFilename,
23. null);
24. } catch (Exception e) {
25. e.printStackTrace();
26. }
27. }
复制代码
单词提示,IME使用AutoCompleteText + SQLite很容易实现类似于baidu ,Google等搜索时出现的提示文字。 输入法也是同样的原理,以拼音或五笔等作为索引,非常容易实现。可以加一个列标明一个字被选择的次数, 在select的时候可以按照这个列来排序,这样可以保存用户的习惯;作出来的输入法将更人性化。因为输入法的查询量比较大 可以考虑把数据库文件放入内存当中,SQLite本身是支持内存数据库的。但android中封装上没有提供这一功能,而且SQLiteDataBase类 很多核心功能都是通过JNI实现的,所以要把数据库搬入内存还需编写c/c++的代码。也可以考虑使用Lucene的全文搜索功能来实现。Date
SQLite有很多函数支持日期的方便处理。
1. %d day of month: 00
2. %f fractional seconds: SS.SSS
3. %H hour: 00-24
4. %j day of year: 001-366
5. %J Julian day number
6. %m month: 01-12
7. %M minute: 00-59
8. %s seconds since 1970-01-01
9. %S seconds: 00-59
10. %w day of week 0-6 with Sunday==0
11. %W week of year: 00-53
12. %Y year: 0000-9999
13. %% %
复制代码
SQLite支持以下格式的日期:
1. YYYY-MM-DD
2. YYYY-MM-DD HH:MM
3. YYYY-MM-DD HH:MM:SS
4. YYYY-MM-DD HH:MM:SS.SSS
5. YYYY-MM-DDTHH:MM //T 就是字母T,用于分开日期和时间
6. YYYY-MM-DDTHH:MM:SS
7. YYYY-MM-DDTHH:MM:SS.SSS
8. HH:MM
9. HH:MM:SS
10. HH:MM:SS.SSS
11. now
12. DDDDDDDDDD //is the Julian day number expressed as a floating point value.
复制代码
strftime('%Y-%m-%d', column_name)方法可以很方便的对日期进行格式化,而不用Java对String进行再处理。
ContentValues 不支持直接把datetime('now')之类函数作为值插入数据库。 比如想把当前系统时间插件数据库使用ContentValues:
1. SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
2. Date date = new Date();
3. ContentValues initialValues = new ContentValues();
4. initialValues.put("date_created", dateFormat.format(date));
5. long rowId = mDb.insert(DATABASE_TABLE, null, initialValues);
复制代码
或者如附带程序记事本程序一样使用exeSQL(sql);
SqliteOpenHelper
上流程图来自O'REILLY 视频公开课"Developing Android Applications with Java"中的视频截图
SqliteOpenHelper是android框架为我们提供的一个数据库助手类。对于数据库的操作一般都是从这个类继承。它主要负责数据库的创建,打开,更新 等一些操作。
Singleton DAO
很多有j2ee背景的开发者都喜欢建立一个单例模式的数据库操作类,专门处理数据库之间的交流。也有很多人把这个习惯带到的Android的开发当中。 而且我们也经常需要在几个Activity,Service同时访问一个数据库文件,所以经常能看到类似于这样的代码:
1. public class DbAccess {
2.
3. class DbHelper extends SQLiteOpenHelper {
4. //此处代码被省略
5. }
6. private static DB_NAME = "users";
7. private mDbHelper = null;
8. private static mDbAccess;//to make sure there is only one instance exist;
9.
10. private DbAccess(Context context){
11. //private constructer;
12. if(mDbHelper == null){
13. mDbHelper = new DbHelper(context,DB_NAME);
14. }
15. }
16.
17. public DbAccess getInstance(Context context){
18. if(mDbAccess == null){
19. mDbAccess = new DbAccess(context);
20. }
21. return mDbAccess;
22. }
23.
24. //部分代码被省略
25. //insert
26. //delete
27. //update
28. //query
29. }
30.
31. public class ActivityA extends Activity{
32. @Override
33. protected void onCreate(Bundle savedInstanceState) {
34. super.onCreate(savedInstanceState);
35. dao = DbAccess.getInstance(this);
36. 部分代码被省略
37. }
38. 部分代码被省略
39. }
复制代码
程序的流程应该是这样的:
假设ActivityA创建了Dao的对象,又开启了ServiceA,A使用了一段时间再跳转到了ActivityB与B再接着使用同一个Dao对象。ActivityA创建Dao对象的时候 把自己的引用向上转型成一个Context对象,Dao又用这个context创建了SQLiteOpenHelper,所以SQLiteOpenHelper就持有了ActivityA的引用。当ActivityA被销毁 之后因为单例的Dao保留有ActivityA的引用,所以ActivityA不能被GC所回收,造成整个Acitivity内存的泄漏。
解决方案
1,最简单的,不使用单例模式,因为SQLiteOpenHelper保证了数据库的单例,所以实际上我们只是创建了多个SQLiteOpenHelper的对象,数据库 对象本身还是单例的。缺点:会有一些重复的代码,并生成多个SQLiteOpenHelper的子类对象。
2,把Dao对象放入Application当中,在Application的onCreate()中使用Application的Context进行初始化。优点,Application对象的创建在Activity和Service之前 所以保证了,Activity和Service等等使用时数据库已经准备好了。缺点:Application的生命周期是最长的,并且Android会尽量不让程序关闭,也就是尽量不 去销毁Application对象,所以数据库一直保持打开状态,依靠Application的onDestroy()关闭数据库,不确定的因素比较大,并且因为打开数据库的时候直接 影响程序启动时间。
3,先看一个问题,为什么SQLiteOpenHelper需要一个Context对象?查看SQLiteOpenHelper的源码发现如下代码:
1. SQLiteDatabase db = null;
2. try {
3. mIsInitializing = true;
4. String path = mContext.getDatabasePath(mName).getPath();
5. db = SQLiteDatabase.openDatabase(path, mFactory, SQLiteDatabase.OPEN_READONLY);
6. if (db.getVersion() != mNewVersion) {
7. throw new SQLiteException("Can't upgrade read-only database from version " +
8. db.getVersion() + " to " + mNewVersion + ": " + path);
9. }
10. onOpen(db);
11. Log.w(TAG, "Opened " + mName + " in read-only mode");
12. mDatabase = db;
复制代码
所以我们可以自己仿照SQLiteOpenHelper写一个不需要Context的助手类,大constructer当中把路径传进行,而不是一个context对象。缺点:需要考虑多线程同步等 很多因素,有一定的复杂度。
4,在创建Dao对象时,不使用Activity的引用作为Context,而是把Application作为Context传入Dao的构造函数中进行创建。优点,不会影响程序的启动时间。 缺点:对于数据库的关闭还是不确定。
5,在第四种方案的基础上加入计数器。第调用getInstance计数器自增,再加入一个release()方法,计数器自减,当计数器为0时,关闭数据库(或者当计数器为零且 过一段时间没有连接时关闭)。
-
赞
-
收藏
-
评论
-
举报
上一篇:How program works
下一篇:Linux C编程--string.h函数解析
全部评论
()
最热
最新
相关文章
-
Android SQLite总结[转载]
最近在做的项目涉及到了SQLite,大学时没有好好学习数据库,趁这次项目学习总结下。SQLite是一款轻量级数据库,它的设计目的是嵌入式,而且它占用的资源非常少,在嵌入式设备中,可能只需要几百KB,这也是 Android 系统采用 SQLite 数据库的原因之一。下面给出SQLite的数据类型。一般数据采用的固定的静态数据类型,而SQLite采用的是动态数据类型,会根据存入值自动判断。
嵌入式
资源
是
Android
-
Android SQLite总结(一)
Android SQLite总结(一) 郑海波 2012-08-21 前言对于Android平台来说,系统内置了丰富的API来供开发人员操作SQLite,我们可以轻松的完成对数据的存取。下面就向大家介绍一下SQLite常用的操作方法。本篇文章主要用到SQLiteDatabase的一些函数。废话少说,直接贴代码!由于数据库中操作的对象时Student类,因此我们看一下Studen
android
sqlite
string
button
layout
-
android SQLite操作方法总结,SQLite用法,SQLiteOpenHelper
android中的数据存取:SQLite 1.Android中通过SQLite数据库引擎来实现结构化数iteOpenHelper工具
sqlite
android
数据库
string
database
-
sqlite3使用总结
OS X自从10.4后把SQLite这套相当出名的数据库软件,放进了作业系统工具集里。OS X包装的是第三版的SQLite,又称SQLite3。这套软件有几个特色:软件属于公共财(public domain),SQLite可说是某种「美德软件」(virtueware),作者本人放弃着作权,而给使用SQLite的人以下的「祝福」(blessing
函数
数据库
应用
休闲
sqlite3
-
sqlite3操作总结
里面对Makefile的说明很详细,通过make的参数指定是gcc编译还是arm-linux-g
gcc编译
linux
-
Qt数据库sqlite总结
QSqlDatabase类实现了数据库连接的操作QSqlQuery类用来执行SQL语句QSqlRecord类封装数据库所有记录
sql
数据库
数据
结果集
可编辑
-
SQLite3使用总结备忘
1、多线程下使用 rc = sqlite3_open_v2(DBFILENAME, &db, SQLITE_OP
sqlite3
多线程
服务器
java
sqlite
-
Qt数据库(sqlite) — 总结
#include QT += sqlQSqlDatabase类实现了数据库连接的操作QSqlQuery类用来执行SQL语句QSqlRecord类 封装数据库所有记录第一:QSqlDatabase类QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE...
sql
数据库
数据
结果集
数据模型
-
SQLITE3 使用总结(转)
前序:Sqlite3 的确很好用。小巧、速度快。但是因为非微软的产品,帮助文档总觉得不够。这些天再次研究它,又有一些收获,这里把我对 sqlite3 的研究列出来,以备忘记。这里要注明,我是一个跨平台专注者,并不喜欢只用 windows 平台。我以前的工作就是为 unix 平台写代码。下面我所写的东西,虽然没有验证,但是我已尽量不使用任何 windows 的东西,只使用标准 C 或标准C++。
sqlite
数据库
#define
数据
sql
-
iphone SQLite3使用总结
SQLite3的确很好用。小巧、速度快。这些天正在研究它,将它移植到ARM系统里面,又有一些收获,这里把我对sqlite3的研究列出来,以备忘记。【其中有摘抄自互联网】 SQLite3提供的是一些C函数接口,你可以用这些函数操作数据库。通过使用这些接口,传递一些标准sql语句(以char *类型)给SQLite3函数,SQLite3就会为你操作数据库。 SQLite3跟MS的access一样是...
sqlite
数据库
字段
数据
sql语句
-
paip.sqlite 管理最好的工具 SQLite Expert 最佳实践总结
paip.sqlite 管理最好的工具 SQLite Expert 最佳实践总结 一般的管理工具斗可以。。。就是要是sqlite没正常地关闭哈,有shm跟wal文件..例如ff的place.sqlite..结束进程常常...这个时候儿,普通的管理工具就不行兰.认不得兰...子能SQLite Expert...就是se有点儿大..66M...作者: 老哇的爪子At
sqlite
管理工具
开源中国
.net
结束进程
-
iphone Sqlite3学习实践总结
本文摘自:http://www.cnblogs.com/GoGoagg/archive/2011/08/12/2136280.html 【实践环境】操作系统:mac 10.6工具:终端,Xcode【资料和实践】官方网址:http://www.sqlite.org/index.html当前版本3.7.7.1在mac 10.6上,版本是
职场
数据库
iphone
休闲
-
Sqlite数据库加密方法总结
今天来讨论一下关于Sqlite数据库加密的事。方法一:对sqlite中的数据进行加密 就是对数据
字段
数据库
数据
-
Sqlite3源码之前端总结
SQLIte在使用时,前端的主要API是sqlite3_prepare函数,该函数的主要功能是把sql编译成sqlite虚拟机代码。1-语法分析sqlite的语法分析阶段把sql转换成内部的抽象语法树AST结构,这部分工作采用lemon工具进行完成。《Sqlite3源码---Parser(1)》介绍了lemon工具;《Sqlite3源码---Parser(2)》介绍了insert、update、d
java
-
sqlite3遇到问题总结
rowid和 Integer主键及自增属性大多数情况下,sqlite3的表都有一个rowid(也叫oid,_rowid_),这是一个64位的整数,并作为sqlite存储结构B树的主键.因此使用rowid查询会比以其他设定的主键查询,速度会非常快.在做插入操作的时候,对于rowid的值通常情况下不要去指定,让系统自己去决定该去何值。因为sqlite会通过SQLITE_SEQUENCE来追踪表的rowid取值情况.而且sqlite定义了rowid的取值算法:在未超出rowid的范围内,待插入记录的rowid总是表中存在过的的rowid最大值+1。比如依次插入5条记录,此时最后一条记录的rowid是
主键
sqlite
取值
数据
软件开发
-
SQLITE3 使用总结(1~2)
******************************************前序:一、版本二、基本编译三、SQ
sqlite
数据库
字段
-
SQLITE3 使用总结(3~5)
SQLITE3 使用总结(3~5) jackyhwei 上面介绍的 sqlite3_exec 是使用回调来执行 select 操作。还有一个方法可以直接查询而不需要回调。但是,我个人感觉还是回调好,因为代码可以更加整齐,只不过用回调很麻烦,你得声明一个函数,如果这个函数是类成员函数,你还不得不把它声明成 static 3 不使用回
sqlite
字段
sql
-
SQLite不支持的SQL语法总结
1 TOP这是一个大家经常问到的问题,例如在SQLSERVER中可以使用如下语句来取得记录集中的前十条记录:SELECT TOP 10 * FROM [index] ORDER BY indexid DESC;但是这条SQL语句在SQLite中是无法执行的,应该改为:SELECT * FROM [index] ORDER BY indexid DESC limit 0,10;其中limit 0,10表示从第0条记录开始,往后一共读取10条2创建视图(Create View)SQLite在创建多表视图的时候有一个BUG,问题如下:CREATE VIEW watch_single AS SELEC
SQLite
数据库
轻量级
内存数据库
不支持的SQL
-
sqlite and 安装sqlite
1.介绍:sqlite3是linux上的小巧的数据库,一个文件就是一个数据库。
sqlite
sql
数据库
sql语句
html
brucezhang
分类列表
-
# 《UNIX环境高级编程》12篇
-
# Linux内核设计与实现44篇
-
# C/C++81篇
近期文章
-
1.C++ ---->再谈构造函数(升级版)_01
-
2.Linux C编程--string.h函数解析
-
3.UNIX下C语言的图形编程-curses.h函数库
-
4.Java之Javassistの常用API-yellowcong
-
5.可能是网工ansible的最强入门教程
-
-
-
意见
反馈
-
举报文章
请选择举报类型
内容侵权
涉嫌营销
内容抄袭
违法信息
其他
补充说明
0/200
上传截图
格式支持JPEG/PNG/JPG,图片不超过1.9M
-
赞
-
收藏
-
评论
如有误判或任何疑问,可联系 「51CTO博客客服 」申诉及反馈。
我知道了
51CTO首页
内容精选
博客
学堂
精培
企业培训
CTO训练营
智能汽车
开源基础软件社区
WOT全球技术创新大会
公众号矩阵
移动端
51CTO博客
-
首页
- 关注
- 排行榜
-
订阅专栏
-
搜索历史
清空
热门搜索
查看【
】的结果
-
首发福利
写文章
- 创作中心
-
登录注册
var userId="";
var uid="";
var user_id=251583;
var isLogin=0;
var imgpath="https://s2.51cto.com/";
var BLOG_URL="https://blog.51cto.com/";
var HOME_URL="https://home.51cto.com/";
var STATICPATH="https://static2.51cto.com/edu/";
var SA_SERVER_URL_YM="https://sc.51cto.com/sa?project=production";
var cururl="https://blog.51cto.com/brucezhang/6268529";
var login_url="https://home.51cto.com/mobile/client-login?reback=https://blog.51cto.com/brucezhang/6268529";
var praise_url="https://blog.51cto.com/praise/praise";
var qrcodeSid="";
var qr_code="";
var router="blog/index";
var csrfParam="_csrf";
var csrfToken="ZTqUb2-vYCLPELW2WRnmK-Kpl2RWPsEDUF6PVfO_kRHcx3Xh_X3RmWtwL5LyamDAEfP9hgj2TG5ZpSqDXxAynw==";
var is_load=0;
var uc_url="https://ucenter.51cto.com/";
var blog_url="https://blog.51cto.com/";
var isBuy=1;
var isPc=0;
var writeMessage="©著作权归作者所有:来自51CTO博客作者brucezhang的原创作品,请联系作者获取转载授权,否则将追究法律责任rnSQLite总结rnhttps://blog.51cto.com/brucezhang/6268529";
var isCodeCopy=0;
var cid="";
var fid=0;
var commentListPage="";
var originalUrl="https://blog.51cto.com/brucezhang/original";
var followersUrl="https://blog.51cto.com/brucezhang/followers";
var translateUrl="https://blog.51cto.com/brucezhang/translate";
var reproduceUrl="https://blog.51cto.com/brucezhang/reproduce";
var followingUrl="https://blog.51cto.com/brucezhang/following";
var page="detail";
var tipStatus=1;
var addReply_url="https://blog.51cto.com/addBlogComment";
var removeUrl="https://blog.51cto.com/delBlogComment";
var blog_id=6268529;
var is_comment=0;
var comment_list="https://blog.51cto.com/getBlogCommentList";
var index_url="https://blog.51cto.com/brucezhang";
var img_url="https://static2.51cto.com/edu/blog/";
var i_user_id="";
var c_user_id=251583;
var collect_url="https://blog.51cto.com/addUserCollect";
var is_old=2;
var nicknameurl="https://blog.51cto.com/brucezhang";
var nickname="brucezhang";
var shareimgUrl="/qr/qr-url?url=https%3A%2F%2Fblog.51cto.com%2Fbrucezhang%2F6268529";
var checkFollow=1;
var seoTitle="";
var articleABtest=0;
!function(f,p){"use strict";var h=new RegExp(".css"),y=p.head||p.getElementsByTagName("head")[0],r=+navigator.userAgent.replace(/.*(?:AppleWebKit|AndroidWebKit)/?(d+).*/i,"$1")<536;function s(e){return"complete"===e.readyState||"loaded"===e.readyState}function v(e,t,n){var o="onload"in e;function a(){e.onload=e.onreadystatechange=null,e=null,t()}"css"!==n||!r&&o?o?(e.onload=a,e.onerror=function(){e.onerror=null}):e.onreadystatechange=function(){s(e)&&a()}:setTimeout(function(){!function e(t,n){var o;t.sheet&&(o=!0),setTimeout(function(){o?n():e(t,n)},20)}(e,t)},1)}function u(t,n,e,o){if(t)if(h.test(t)){var a=t,r=e,c=u,i=p.createElement("link");if(r.attrs)for(var l in r.attrs)i.setAttribute(l,r.attrs[l]);r.prefetch?(i.href=a,i.rel="prefetch",c&&c()):(i.rel="stylesheet",v(i,c,"css"),i.href=a),y.appendChild(i)}else{var c=t,d=e,a=u,f=d.prefetch?p.createElement("link"):p.createElement("script");if(d.attrs)for(var s in d.attrs)f.setAttribute(s,d.attrs[s]);d.prefetch?(f.href=c,f.rel="prefetch",a&&a()):(f.charset="utf-8",v(f,a,"js"),f.async=!1,f.src=c),y.appendChild(f)}else setTimeout(function(){u()});function u(){var e=n.indexOf(t);-1<e&&n.splice(e,1),0===n.length&&o()}}function c(e="load",t){var n="object"==typeof t.option?t.option:{},t="function"==typeof t.callback?t.callback:null;return n.attrs="object"==typeof n.attrs?n.attrs:{},n.loaded="boolean"==typeof n.loaded&&n.loaded,n[e]=!0,{option:n,cb:t}}function i(c,e,t="load"){var n,o,a,r,i,l;function d(){var e=c,t=i,n=l;function o(){n&&n()}if(0===(e=Array.prototype.slice.call(e||[])).length)o();else for(var a=0,r=e.length;a<r;a++)u(e[a],e,t,o)}c&&c.length&&(i=e.option,l=e.cb,e=p,n=function(){"load"===t&&i.loaded?setTimeout(d,2e3):d()},("ready"===(o=t)?"loading"!==e.readyState:s(e))?n():(a=!1,r=function(){a||(n(),a=!0)},"load"===o?f.addEventListener("load",r):"ready"===o&&p.addEventListener("DOMContentLoaded",r),setTimeout(function(){r()},1500)))}f.PsLoader={ready:function(e,t,n={}){var o=[],a=[];e.forEach(function(e){(h.test(e)?o:a).push(e)}),n.loaded=!1,i(o,c("ready",{option:n,callback:function(){t(o)}}),"ready"),i(a,c("load",{option:n,callback:function(){t(a)}}))},load:function(e,t,n={}){i(e,c("load",{option:n,callback:t}))},prefetch:function(e,t,n={}){i(e,c("prefetch",{option:n,callback:t}))}}}(window,document); !function(m,g){var t=["scroll","wheel","mousewheel","resize","animationend","transitionend","touchmove"];function n(e){if("object"!=typeof e)throw new Error("CLazy option is not Object");var f={defaultImg:e.defaultImg||"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7",preLoad:e.preLoad||1.3,preLoadTop:e.preLoadTop||0,complete:e.complete||null,events:e.events||t,capture:e.capture||!1},v=0,p={},h={},i={},A=this;function l(e){var t=e;if("object"!=typeof t)return!1;if(!t.el)for(var r in p)if(e===p[r].el){t=p[r];break}return t}function c(e){var e=e.getBoundingClientRect(),t=f.preLoad,r=f.preLoadTop;return e.topr&&e.left<m.innerWidth*t&&0<e.right}function u(e,t){var r,n=e.bindType,o=e.el;switch(t){case"loading":case"error":r=f.defaultImg;break;default:r=e.src}n?e.src&&(o.style[n]='url("'+r+'")'):o.getAttribute("src")!==r&&o.setAttribute("src",r),o.setAttribute("lazy",t)}this.add=function(e,t){var r=function(e){var t,r=!1;for(t in p)if(p[t].el===e){r=p[t];break}return r}(e);if(r)return this.check(r),!1;r="e_"+ ++v;if(p[r])return this.check(p[r]),!1;for(var n,o={id:r,el:e,bindType:"IMG"===e.tagName?null:"background-image",src:(n=e,(t=t)?t.value:n.getAttribute("ps-lazy")),$parent:function(e){if(!(e instanceof HTMLElement))return m;var t=e;for(;t&&t!==g.body&&t!==g.documentElement&&t.parentNode;){if(/(scroll|auto)/.test(function(e){return y(e,"overflow")+y(e,"overflow-y")+y(e,"overflow-x")}(t)))return t;t=t.parentNode}return m}(e)},a=(h[r]=function(e){A.check(o)},p[r]=o),i=h[r],c=0;c<f.events.length;c++){s=d=u=l=void 0;var[l,u,d,s=!1]=[a.$parent,f.events[c],i,f.capture];l&&l.addEventListener(u,d,s),m!==l&&m.addEventListener(u,d,s)}this.check(o)},this.remove=function(e){for(var e=l(e),t=(e.el&&e.el.removeAttribute("ps-lazy"),e),r=h[e.id],n=0;n<f.events.length;n++){c=i=a=o=void 0;var[o,a,i,c=!1]=[t.$parent,f.events[n],r,f.capture];o&&o.removeEventListener(a,i,c),m!==o&&m.removeEventListener(a,i,c)}delete h[e.id],delete p[e.id]},this.check=function(e){var t,r,n,o,a=l(e);c(a.el)&&(m===a.$parent||c(a.$parent))?(e=function(e){u(a,e),A.remove(a),f.complete&&f.complete({el:a.el,src:a.src,state:e})},a.src?(t=a.src,r=e,n=encodeURIComponent(t),i[n]?r(i[n]):((o=new Image).onload=function(){i[n]="loaded",r(i[n])},o.onerror=function(){i[n]="error",r(i[n])},o.src=t)):e("loaded")):u(a,"loading")},this.checkAll=function(){for(var e in p)A.check(p[e])}}function y(e,t){return"undefined"!=typeof getComputedStyle?getComputedStyle(e,null).getPropertyValue(t):e.style[t]}m.PsLazy=function(e={}){function t(e){for(var t=e.path||event.composedPath&&event.composedPath()||e._getPath&&e._getPath(),r=0;r<t.length;r++){var n=t[r];if(n&&"hasAttribute"in n&&n.hasAttribute("ps-lazy-check")){o.format();break}}}function r(){var e=g.querySelector("img[data-share]");e&&!e.getAttribute("src")&&e.setAttribute("src",e.getAttribute("data-share"))}var o=this;n.call(o,e),g.addEventListener("click",t),g.addEventListener("mouseover",t),this.format=function(){var e=g.querySelectorAll("[ps-lazy]");if(!e.length)return!1;for(var t=0;t<e.length;t++)o.add(e[t])},this.format();"complete"===(e=g).readyState||"loaded"===e.readyState?r():m.addEventListener("load",r,!1)}}(window,document); PsLoader.load(["https://static2.51cto.com/edu/blog/blog-static/static/css/pc_detailinline.min.css?v=5c7f42dbda","https://static2.51cto.com/edu/blog/blog-static/static/css/pc_detail.min.css?v=118252b566","https://cdn.51cto.com/jquery/jquery-2.2.4.min.js","https://static2.51cto.com/edu/center/js/interaction_iframe.js","https://cdn.51cto.com/jquery/swiper-4.5.3.js","https://static2.51cto.com/edu/blog/blog-static/static/js/pc_base.min.js?v=300bc61215","https://static2.51cto.com/edu/blog/blog-static/js/mprime.js?v=2cb70144db","https://static2.51cto.com/edu/blog/blog-static/static/js/pc_detail.min.js?v=2535acb529"], function() {})
PsLoader.prefetch(["https://static2.51cto.com/edu/blog/blog-static/static/css/pc_base.min.css?v=2731609498","https://static2.51cto.com/edu/blog/blog-static/static/css/pc_indexinline.min.css?v=e40c304555","https://static2.51cto.com/edu/blog/blog-static/static/css/pc_newIndexinline.min.css?v=7cd4246e43","https://static2.51cto.com/edu/blog/blog-static/static/css/pc_listinline.min.css?v=a365759c73","https://static2.51cto.com/edu/blog/blog-static/static/css/pc_newListinline.min.css?v=fcde138dd1","https://static2.51cto.com/edu/blog/blog-static/static/css/pc_topicinline.min.css?v=47a9bc571c","https://static2.51cto.com/edu/blog/blog-static/static/css/pc_topicdetailinline.min.css?v=512bf305aa","https://static2.51cto.com/edu/blog/blog-static/static/css/pc_bloggerinline.min.css?v=0e63931398","https://static2.51cto.com/edu/blog/blog-static/markdown/dist/js/main.js?v=9fee5bb838","https://static2.51cto.com/edu/blog/blog-static/static/js/pc_index_js.min.js?v=5331660aa2","https://static2.51cto.com/edu/blog/blog-static/static/js/pc_list_js.min.js?v=8973c321c1","https://static2.51cto.com/edu/blog/blog-static/static/js/pc_topic.min.js?v=873da4210c","https://static2.51cto.com/edu/blog/blog-static/static/js/pc_topic_static.min.js?v=8533cb9e02","https://static2.51cto.com/edu/blog/blog-static/static/js/pc_topicdetail.min.js?v=901345e7d5","https://static2.51cto.com/edu/blog/blog-static/static/js/pc_blogger_js.min.js?v=c7a4e3d003"]);
var Lazy = new PsLazy({
defaultImg: "https://s2.51cto.com/images/100/base/empty.png?x-oss-process=image/ignore-error,1",
preLoad: 1.3,
complete: function(opt) {},
})
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
机房租用,北京机房租用,IDC机房托管, http://www.fwqtg.net
相关推荐: Excel常用快捷键,你也可以成为大家口中的大神
掌握复制、粘贴,相信每个职场人都能骄傲地说“自己熟练使用Excel”,果真如此不害臊吗?不出10秒钟,肯定被面试官问得哑口无言。快捷键太多,记住几个常用的,收藏起来,需要的时候过来查看。 “学Excel”系列的其它文章也介绍了一些快捷键的用法,可以去找找看。 …
评论