FMDB的简单应用(4篇)
转截地址:http://blog.csdn.net/demon1900demon/article/details/23602535
转截地址:http://www.mobiledevor.com/post/34.html
转截地址:http://blog.devtang.com/blog/2012/04/22/use-fmdb/
转截地址:http://www.cnblogs.com/wuhenke/archive/2012/02/07/2341656.html
FMDB
https://github.com/ccgus/fmdb
This is an Objective-C wrapper around SQLite: http://sqlite.org/
这是对 SQLite 的封装:http://sqlite.org/
Read the SQLite FAQ:
http://www.sqlite.org/faq.html
因为 FMDB 建立在 SQLite 之上,所以,你至少应该把 SQLite 文档看一遍。看的时候,将 http://www.sqlite.org/docs.html 网址添加到你的浏览器书签中吧。
FMDB Class Reference:
http://ccgus.github.io/fmdb/html/index.html
Automatic Reference Counting (ARC) or Manual Memory Management?
Usage
There are three main classes in FMDB:
FMDB 包含了 3 个主要的类:
FMDatabase
- Represents a single SQLite database. Used for executing SQL statements.FMResultSet
- Represents the results of executing a query on anFMDatabase
.FMDatabaseQueue
- If you're wanting to perform queries and updates on multiple threads, you'll want to use this class. It's described in the "Thread Safety" section below.- FMDatabase - 代表了单一的一个 SQLite 数据库。用来执行 SQL 语句的。
- FMResultSet - 在 FMDatabase 上执行了查询操作后展示的结果。
- FMDatabaseQueue - 如果你想在不同的线程中同时执行查询和更新操作,你会用到这个类。在最下面有对其的描述。
Database Creation
An FMDatabase
is created with a path to a SQLite database file. This path can be one of these three:
通过给定一个 SQLite 数据库文件的路径来创建 FMDatabase,这个文件路径可由下面 3 种方式提供:
- A file system path. The file does not have to exist on disk. If it does not exist, it is created for you.
- An empty string (
@""
). An empty database is created at a temporary location. This database is deleted with theFMDatabase
connection is closed. NULL
. An in-memory database is created. This database will be destroyed with theFMDatabase
connection is closed.- 一个系统文件路径,这个文件路径不一定需要存在,如果不存在,它会自动为你创建。
- 一个空的字符串 @“”,它会为你创建一个临时的数据库文件。当 FMDatabase 关闭后,这个数据库就会被删除掉。
- 如果参数为 NULL ,那就会在内存中创建一个数据库,当 FMDatabase 关闭后,这个数据库就会被删除掉。
FMDatabase *db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];
Opening
在你能使用数据库之前,你必须先打开它。如果系统资源不足,或者你没有权限打开或者创建数据库都会导致打开失败。
if (![db open]) {[db release];return;
}
Executing Updates(执行更新)
执行更新操作会返回一个 BOOL 值。YES 代表更新成功,NO 表示出现了某些错误。你可以调用 -lastErrorMessage
和 -lastErrorCode 方法来寻找错误的信息。
Executing Queries(执行查询)
A SELECT
statement is a query and is executed via one of the -executeQuery...
methods.
查询语句 SELECT 通过 -executeQuery.. 中的一些方法来实现。
为了能迭代检索处所有你的查询结果,你可以使用 while() 循环。你需要使用 “step” 来从一条记录跳到另外一条记录。在 FMDB 当中,下面展示的就是最简单的方式。
FMResultSet *s = [db executeQuery:@"SELECT * FROM myTable"];
while ([s next]) {//retrieve values for each record
}
你必须经常调用方法 -[FMResultSet next] ,哪怕你只是查找一条记录。
FMResultSet *s = [db executeQuery:@"SELECT COUNT(*) FROM myTable"];
if ([s next]) {int totalCount = [s intForColumnIndex:0];
}
FMResultSet
has many methods to retrieve data in an appropriate format:
intForColumn:
longForColumn:
longLongIntForColumn:
boolForColumn:
doubleForColumn:
stringForColumn:
dateForColumn:
dataForColumn:
dataNoCopyForColumn:
UTF8StringForColumnName:
objectForColumnName:
上面的每一个方法中都有一个 {type}ForColumnIndex:自己的版本,用来匹配数据,基于查询结果中的记录。
尤其注意,你不要自己关闭 FMResultSet 。当父数据库关闭,或者是结果集被丢弃,它会自动关闭。
Closing(关闭)
当你已经执行了查询,更新了数据库,你应该使用 -close 来关闭数据库的连接,让 SQLite 释放你执行那些操作的资源而提高效率。
[db close];
Transactions(事务)
FMDatabase 可以提交一个事务,通过调用 begin/end 事务语句。
Data Sanitization(数据处理)
当你提供一条 SQL 语句给 FMDB 时,你不要直接给语句中的变量附上值。你应该使用标准的 SQLite 绑定的语法规则:
INSERT INTO myTable VALUES (?, ?, ?)
?会被识别成一个将要被替换的值。所有的的执行方法都接受不同类型的变量(包括 NSArray , NSDictionary 或者一个 va_list),你会喜欢的。
Alternatively, you may use named parameters syntax:
INSERT INTO myTable VALUES (:id, :name, :value)
参数之前必须加上冒号。 SQLite 本身支持很多种字符,但是 OC 中字典对象的前缀就是冒号,所以,不要在你的字典 key 值前包含冒号。
NSDictionary *argsDict = [NSDictionary dictionaryWithObjectsAndKeys:@"My Name", @"name", nil];
[db executeUpdate:@"INSERT INTO myTable (name) VALUES (:name)" withParameterDictionary:argsDict];
Thus, you SHOULD NOT do this (or anything like this):
[db executeUpdate:[NSString stringWithFormat:@"INSERT INTO myTable VALUES (%@)", @"this has \" lots of ' bizarre \" quotes '"]];
[db executeUpdate:@"INSERT INTO myTable VALUES (?)", @"this has \" lots of ' bizarre \" quotes '"];
所有提供给 -executeUpdate:方法的参数必须是一个对象。下面的写法是错误的,会导致崩溃。
[db executeUpdate:@"INSERT INTO myTable VALUES (?)", 42];
The proper way to insert a number is to box it in an NSNumber
object:
[db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:42]];
Alternatively, you can use the -execute*WithFormat:
variant to use NSString
-style substitution:
作为一项选择,你可以使用 -exexute*WithFormat:来提交 NSString 方式的语句:
[db executeUpdateWithFormat:@"INSERT INTO myTable VALUES (%d)", 42];
Using FMDatabaseQueue and Thread Safety.(使用数据库队列以及线程安全)
So don't instantiate a single FMDatabase object and use it across multiple threads.
所以,不要创建一个 FMDatabase 单例对象,然后在不同的线程中访问。
Instead, use FMDatabaseQueue. It's your friend and it's here to help. Here's how to use it:
你可以使用 FMDatabaseQueue,线程安全就靠它了:
FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:aPath];
[queue inDatabase:^(FMDatabase *db) {[db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]];[db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]];[db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]];FMResultSet *rs = [db executeQuery:@"select * from foo"];while ([rs next]) {…}
}];
An easy way to wrap things up in a transaction can be done like this:
[queue inTransaction:^(FMDatabase *db, BOOL *rollback) {[db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]];[db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]];[db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]];if (whoopsSomethingWrongHappened) {*rollback = YES;return;}// etc…[db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:4]];
}];
注意:调用 FMDatabaseQueue 方法是一个 block 。即使你在 block 中使用了 block,它也不会在其它线程中运行。
Making custom sqlite functions, based on blocks.(定制 sqlite 函数,基于 blocks)
You can do this! For an example, look for "makeFunctionNamed:" in main.m
ios数据存储中关于Sqlite3使用第三方框架FMDB
ios数据存储中关于Sqlite 3使用第三方框架FMDB是本文要介绍的内容,主要讲述在iPhone上是采用sqlite进行数据存储是我一种比较习惯性的做法。一般在其他平台也比较习惯用sqlite,比如android。
而ios开发上有一些封装好的第三方框架提供使用,更节省了许多时间。如:Sqlitepersistentobjects ,FMDB 。今天查找了这个两个框架,感觉FMDB的风格更符合我的使用,其实两者是各有优点的,只是看个人喜好而已。以下是FMDB的一些基本使用,FMDB框架其实只是一层很薄的封装,主要的类也就两个:FMDatabase和FMResultSet ;
其中的FMResultSet对象让我想起了android中sqlite的cursor集合啊。
FMDB的github地址是,https://github.com/ccgus/fmdb。
1、首先得实例化一个FMDatabase对象,这跟 Sqlitepersistentobjects 派生一个子类进行操作是不同。接着打开一个数据库(如果没有会创建一个数据库)
- //paths: ios下Document路径,Document为ios中可读写的文件夹
- NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
- NSString *documentDirectory = [paths objectAtIndex:0];
- //dbPath: 数据库路径,在Document中。
- NSString *dbPath = [documentDirectory stringByAppendingPathComponent:@"Test.db"];
- //创建数据库实例 db 这里说明下:如果路径中不存在"Test.db"的文件,sqlite会自动创建"Test.db"
- FMDatabase *db= [FMDatabase databaseWithPath:dbPath] ;
- if (![db open]) {
- NSLog(@"Could not open db.");
- return ;
- }
- //paths: ios下Document路径,Document为ios中可读写的文件夹
- NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
- NSString *documentDirectory = [paths objectAtIndex:0];
- //dbPath: 数据库路径,在Document中。
- NSString *dbPath = [documentDirectory stringByAppendingPathComponent:@"Test.db"];
- //创建数据库实例 db 这里说明下:如果路径中不存在"Test.db"的文件,sqlite会自动创建"Test.db"
- FMDatabase *db= [FMDatabase databaseWithPath:dbPath] ;
- if (![db open]) {
- NSLog(@"Could not open db.");
- return ;
- }
接下来,我们可以通过这个数据库对象进行操作了。操作主要是update和queries。
首先是创建表。
- //创建一个名为User的表,有两个字段分别为string类型的Name,integer类型的 Age
- [db executeUpdate:@"CREATE TABLE User (Name text,Age integer)"];
- //创建一个名为User的表,有两个字段分别为string类型的Name,integer类型的 Age
- [db executeUpdate:@"CREATE TABLE User (Name text,Age integer)"];
这样我们就有了一张表了。接下我们对表进行操作。插入数据!注意插入的数据使用了通配符,这跟iphone直接使用sqlite借口的绑定变量是一样的,后面的通配符匹配的数据。
- //插入数据使用OC中的类型 text对应为NSString integer对应为NSNumber的整形
- [db executeUpdate:@"INSERT INTO User (Name,Age) VALUES (?,?)",@"老婆",[NSNumber numberWithInt:20]]
- //插入数据使用OC中的类型 text对应为NSString integer对应为NSNumber的整形
- [db executeUpdate:@"INSERT INTO User (Name,Age) VALUES (?,?)",@"老婆",[NSNumber numberWithInt:20]]
接下来是更新数据。
- //更新数据 将“老婆”更改为“宝贝”
- [db executeUpdate:@"UPDATE User SET Name = ? WHERE Name = ? ",@"老婆",@"宝贝"];
- //更新数据 将“老婆”更改为“宝贝”
- [db executeUpdate:@"UPDATE User SET Name = ? WHERE Name = ? ",@"老婆",@"宝贝"];
再接下来,就是删除数据啦。
- //删除数据
- [db executeUpdate:@"DELETE FROM User WHERE Name = ?",@"老婆"];
- //删除数据
- [db executeUpdate:@"DELETE FROM User WHERE Name = ?",@"老婆"];
update的基本操作就这几个,接下来是queries!
- //返回数据库中第一条满足条件的结果
- NSString *aa=[db stringForQuery:@"SELECT Name FROM User WHERE Age = ?",@"20"];
- //返回数据库中第一条满足条件的结果
- NSString *aa=[db stringForQuery:@"SELECT Name FROM User WHERE Age = ?",@"20"];
这样我们就查询返回了一条数据,那当我们想要查询放返回多条数据怎么办呢?不用愁,之前我就提到了FMDB中的另外一个主要的类,FMResultSet,这是一个结果集!返回多条数据时FMDB会将数据放在这个结果集中,然后我们在对这个结果集进行查询操作!很简单。
- FMResultSet *rs=[db executeQuery:@"SELECT * FROM User"];
- rs=[db executeQuery:@"SELECT * FROM User WHERE Age = ?",@"20"];
- while ([rs next]){
- NSLog(@"%@ %@",[rs stringForColumn:@"Name"],[rs stringForColumn:@"Age"]);
- }
- FMResultSet *rs=[db executeQuery:@"SELECT * FROM User"];
- rs=[db executeQuery:@"SELECT * FROM User WHERE Age = ?",@"20"];
- while ([rs next]){
- NSLog(@"%@ %@",[rs stringForColumn:@"Name"],[rs stringForColumn:@"Age"]);
- }
更多的 FMResultSet方法有:
- intForColumn:
- longForColumn:
- longLongIntForColumn:
- boolForColumn:
- doubleForColumn:
- stringForColumn:
- dateForColumn:
- dataForColumn:
- dataNoCopyForColumn:
- UTF8StringForColumnIndex:
- objectForColumn:
具体查看一下类就行了! 好了,对于FMDB的使用就这样,是不是很简单呢,其实这个些封装sqlite的框架都是万变不离其宗的,只要你掌握了sql就行了!
小结:iPhone数据存储中关于Sqlite 3使用第三方框架FMDB的内容介绍完了,希望本文对你有所帮助
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
在iOS开发中使用FMDB
前言
SQLite (http://www.sqlite.org/docs.html) 是一个轻量级的关系数据库。iOS SDK很早就支持了SQLite,在使用时,只需要加入 libsqlite3.dylib 依赖以及引入 sqlite3.h 头文件即可。但是,原生的SQLite API在使用上相当不友好,在使用时,非常不便。于是,开源社区中就出现了一系列将SQLite API进行封装的库,而FMDB (https://github.com/ccgus/fmdb) 则是开源社区中的优秀者。
FMDB在使用上相当方便。以下是一个简单的例子:
1 2 3 4 5 6 7 8 9 10 11 |
|
可以看到,使用FMDB后的数据库代码清晰明了,比原生的API优雅多了。另外,FMDB同时兼容ARC和非ARC工程,会自动根据工程配置来调整相关的内存管理代码。
使用说明
该使用说明主要翻译自fmdb的github项目说明文档: https://github.com/ccgus/fmdb
引入相关文件
首先将FMDB从github上clone下来,然后将以下文件copy到你的工程中:
1 2 3 4 5 6 7 8 9 10 |
|
建立数据库
建立数据库只需要如下一行即可,当该文件不存在时,fmdb会自己创建一个。如果你传入的参数是空串:@”” ,则fmdb会在临时文件目录下创建这个数据库,如果你传入的参数是 NULL,则它会建立一个在内存中的数据库。
1 |
|
打开数据库
使用如下语句,如果打开失败,可能是权限不足或者资源不足。通常打开完操作操作后,需要调用close方法来关闭数据库。
1 2 3 4 5 6 7 8 |
|
执行更新操作
除了Select操作之外,其它的都是更新操作。更新操作使用如下方法,如果有错误,可以用error参数中获得。
1 |
|
执行查询操作
查询操作示例如下。注意:即使操作结果只有一行,也需要先调用FMResultSet的next方法。
1 2 3 4 5 6 7 8 9 |
|
FMDB提供如下多个方法来获取不同类型的数据:
1 2 3 4 5 6 7 8 9 10 11 |
|
通常情况下,你并不需要关闭FMResultSet,因为相关的数据库关闭时,FMResultSet也会被自动关闭。
数据参数
通常情况下,你可以按照标准的SQL语句,用?表示执行语句的参数,如:
1 |
|
然后,可以我们可以调用executeUpdate方法来将?所指代的具体参数传入,通常是用变长参数来传递进去的,如下:
1 2 |
|
这里需要注意的是,参数必须是NSObject的子类,所以象int,double,bool这种基本类型,需要封装成对应的包装类才行,如下所示:
1 2 3 4 |
|
线程安全
如果我们的app需要多线程操作数据库,那么就需要使用FMDatabaseQueue来保证线程安全了。切记不能在多个线程中共同一个FMDatabase对象并且在多个线程中同时使用,这个类本身不是线程安全的,这样使用会造成数据混乱等问题。
使用FMDatabaseQueue很简单,首先用一个数据库文件地址来初使化FMDatabaseQueue,然后就可以将一个闭包(block)传入inDatabase方法中。在闭包中操作数据库,而不直接参与FMDatabase的管理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
|
工具
为了查看Sqlite中的数据,一个好的图形化界面的数据库管理程序是必不可少的。mysql有phpMyAdmin,那么sqlite呢?
我主要使用的是Firefox的一个名为SQLite Manager的插件,安装此插件后,可以直接打开后缀名为sqlite的数据库文件。SQLite Manager提供一个图形化的界面来执行数据查询或更改操作。如下图所示:
总结
FMDB将SQLite API进行了很友好的封装,使用上非常方便,对于那些使用纯Sqlite API来进行数据库操作的app,可以考虑将其迁移到基于FMDB上,这对于以后数据库相关功能的开发维护,可以提高不少效率。
我在学习fmdb的时候做了一个小工程用于练习,我把它放到github上了。感兴趣的可以自行下载:https://github.com/tangqiaoboy/FmdbSample
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Sqlite第三方类库FMDB的使用
使用资料库的第一件事,就是建立一个资料库。要注意的是,在iOS环境下,只有document directory 是可以进行读写的。在写程式时用的那个Resource资料夹底下的东西都是read-only。因此,建立的资料库要放在document 资料夹下。方法如下:
1
|
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
|
2
|
NSString *documentDirectory = [paths objectAtIndex:0];
|
3
|
NSString *dbPath = [documentDirectory stringByAppendingPathComponent:@ "MyDatabase.db" ];
|
4
|
FMDatabase *db = [FMDatabase databaseWithPath:dbPath] ;
|
5
|
if (![db open]) {
|
6
|
NSLog(@“Could not open db.”);
|
7
|
return ;
|
8
|
}
|
建立table
1
|
[db executeUpdate:@ "CREATE TABLE PersonList (Name text, Age integer, Sex integer, Phone text, Address text, Photo blob)" ];
|
1
|
[db executeUpdate:@ "INSERT INTO PersonList (Name, Age, Sex, Phone, Address, Photo) VALUES (?,?,?,?,?,?)" ,
|
2
|
3
|
@ "Jone" , [NSNumber numberWithInt:20], [NSNumber numberWithInt:0], @“091234567”, @“Taiwan, R.O.C”, [NSData dataWithContentsOfFile: filepath]];
|
1
|
[db executeUpdate:@ "UPDATE PersonList SET Age = ? WHERE Name = ?" ,[NSNumber numberWithInt:30],@“John”];
|
01
|
FMResultSet *rs = [db executeQuery:@ "SELECT Name, Age, FROM PersonList" ];
|
02
|
03
|
while ([rs next]) {
|
04
|
05
|
NSString *name = [rs stringForColumn:@ "Name" ];
|
06
|
07
|
int age = [rs intForColumn:@ "Age" ];
|
08
|
09
|
}
|
10
|
11
|
[rs close];
|
1
|
//找地址
|
2
|
3
|
NSString *address = [db stringForQuery:@ "SELECT Address FROM PersonList WHERE Name = ?" ,@"John”];
|
4
|
5
|
//找年齡
|
6
|
7
|
int age = [db intForQuery:@ "SELECT Age FROM PersonList WHERE Name = ?" ,@"John”];
|
FMDB的简单应用(4篇)相关推荐
- Redux其实很简单(原理篇)
在上一篇文章中,我们通过一个示例页面,了解到Redux的使用方法以及各个功能模块的作用.如果还不清楚Redux如何使用,可以先看看Redux其实很简单(示例篇),然后再来看本文,理解起来会更加轻松. ...
- HTML5边玩边学(9):俄罗斯方块就是这么简单 之 数据模型篇
特别提示: 本文中的运行效果需要 Chrome 浏览器或者 Firefox 浏览器. 一.从数据出发还是从界面出发 要写一个俄罗斯方块小游戏,我们先来一块考虑一下下面几个问题: 1.用什么表示方块 2 ...
- FMDB数据库简单使用
上一篇文章sqlite3原生数据库简单使用 介绍了sqlite3原生数据库的简单使用,由于执行语句都是C语言写的,导致看起来操作非常不方便,因此便根据数据库封装了一个很好用的第三方框架,以下是他的简单 ...
- (纯故事)我简单写几篇,就这一次
写在最前:我发几篇之前写过的小段子,主要是朋友要,我想起来了,请不要一个人看. ---------------------------------- 1. 禾禾躺在床上,翻来覆去的睡不着.他是个很认床 ...
- Midjourney绘制插画,绘画重来没有如此之简单 - 第12篇
历史文章(文章累计460+) <国内最全的Spring Boot系列之一> <国内最全的Spring Boot系列之二> <国内最全的Spring Boot系列之三> ...
- Vim的简单实用(存活篇)
为什么80%的码农都做不了架构师?>>> 由于最近接触了Liunx编程,教学需要用到Vim.听说Vim是人类史上最好的文本编辑器,希望它能成为我最后一个使用的文本编辑器吧! 接 ...
- 初识 java(简单易懂入门篇)
引言 java语言是Sun公司在1990年由James Gosling创建的(Sun公司现已被Oracle甲骨文公司收购),在1995年才公布,java创始人James Gosling通过C++创造了 ...
- HTML写一首简单的居中唐诗,韩愈写的诗最简单的10篇
韩愈是古文运动的倡导者,主张继承先秦两汉散文传统,反对专讲声律对仗而忽视内容的骈体文.韩愈文章气势雄伟,说理透彻,逻辑性强,被尊为"唐宋八大家"之首.时人有"韩文&quo ...
- FMDB 的简单说明
FMDB是对sqlite进行封装的第三方库,对于其基础的知识网络中已经有了数不胜数的说明,这里就不在重复的说明.本文的主要目的是了解FMDB的基本操作: 1)通过手动或cocopads添加FMDB的第 ...
最新文章
- 防止******ADSL的一些技巧
- calendar 获取季度的第一天_Java日期查询:日、周、旬、月、季度、年等时间操作...
- CentOS7 部署 galera cluster mariadb 10.1
- 可以比较两个指针是否相等_算法一招鲜——双指针问题
- 打印出如下图案(菱形)
- Python 自动化-pywinauto遍历展示程序的所有菜单项,菜单栏menu_select()操作方法的使用
- tableau可视化函数使用案例(四十六)-数字函数的使用方法
- MySQL 19个规则数据库设计总结
- java项目教训_[免费电子书]分析超过600,000个Java项目的经验教训
- python如何创建模块视频_Python | 如何创建模块(模块示例)?
- AI需要你帮忙 | 把两栖爬行动物框出来,提高AI识别准确率
- websocket.onmessage回调没反应_Java笔记:反应器模式的简单运用
- Atitit callback回调机制大总结 目录 1. 回调机制=Call back,	1 1.1. 1.为什么需要Call back	2 1.2. 模块之间的调用,调用的方式分为几种:1)同步调
- OpenSSL制作自签名V3证书
- Sftp中文件名乱码
- 删除亚马逊Kindle电子书的DRM,将AZW转为PDF格式文档
- 样本峰度(kurtosis)与随机变量的峰度及四阶统计量之间的关系和计算估计
- 中兴新支点操作系统_中兴发国产操作系统新支点,好不好用测了才知道
- 双系统之删除Linux
- 图片免费压缩——在线压缩JPG方法分享
热门文章
- C++ dpi,px,cm,mm换算心得,以及以a4纸计算为例,其它大家各自换算
- 小程序系统API调用
- ubantu16.04下安装omnet5.4.1,inet3.6.4,veins4.7.1 和 sumo0.32.0
- 云计算概论 -- 云使能技术
- Vue mounted方法中使用data变量
- Enow ICQ上的自白
- CISCO设备信息泄漏漏洞案例
- Service ‘MongoDB Server‘(MongoDB) failed to start.Verify that you have sufficient privileges to
- IP公有地址和私有地址划分
- java 时间戳 什么意思_java时间与时间戳