• 关于

    拼接符有什么用

    的搜索结果

问题

OpenSearch的数据源及插件是什么?

轩墨 2019-12-01 20:55:51 1089 浏览量 回答数 0

回答

是否可以用规则引擎?比如 Drools 。或者可以考虑行为树,看下行为树能否满足需求,行为树多用于游戏AI,但本质上也是各个条件的判断。######回复 @别忘了带红领巾 : 抱歉!python不熟悉。######谢谢,请问python方面有什么好办法吗?###### 你会拼接字符串吧,通过读取condition生成下面的SQL即可 select *, (age > 21 and mony >280.05 and accessTime > '2015-05-31') as cond from 资产表###### 针对你这种情况,需要先写个模板,然后再跟规则配合,比如说有一个字段,首先这个字段的数据类型有N种,你就得先根据数据类型设定N中模板,然后每个数据类型有M种校验方法,你就得再针对每个模板设定好M种方法的执行流程,你这样设定好了之后,每次就很容易调用了; eg:有个数字类型的字段  需要校验该字段的值是否大于某个值 那么你的调用顺序就是:  获取数字类型校验模板,选择校验值大于某个值的方法######谢谢,但是我的是要多个条件,多个逻辑符。目前我想到的是两两判断,但是语句我有些写不出来。###### 条件和结果是动态配置的,数量也不一定。想通过java来实现,还有更好的思路吗?谢谢###### 先  找到  判断的  优先级      哪个要先判断  哪个 最后判断 要明确。  一个判断条件大于3中情况 或者 以后还会添加 就建议所用switch       ######谢谢,但是多个条件之间会存再逻辑运算符呀。###### 是做参数校验还是啥?,看条件最终产生结果,以此类型结果为优先解?######下面有样例,麻烦帮忙看看,谢谢!###### 你需要举个(比较完整的)例子,不知道你具体在说啥######样例在下面,谢谢###### 现在有个数据表 年龄(age : int)资产 (money : number)入网日期 (accessTime : date)20100.002017-03-2420150.002016-05-0721300.002015-04-0321240.002015-07-1522300.002014-12-2121300.002014-12-21 另外,有一张条件表,condition: 字段名(fieldName : varchar)运算符(oper : varchar)阈值 (threshold : varchar )age=21money>280.05accessTime>2015-05-31 条件表condition用来配置过滤用户person的条件,表示要筛选出符合条件 年龄等于21岁 资产大于280.05 入网日期在 2015-06-01之后 的所有用户。符合条件的我有固定输出结果,不符合的也是有错误输出结果。谢谢

kun坤 2020-06-07 16:22:35 0 浏览量 回答数 0

回答

1 js 的基本数据类型? 2 JavaScript 有几种类型的值? 3 什么是堆?什么是栈?它们之间有什么区别和联系? 4 内部属性 [Class] 是什么? 5 介绍 js 有哪些内置对象? 6 undefined 与 undeclared 的区别? 7 null 和 undefined 的区别? 8 如何获取安全的 undefined 值? 9 说几条写 JavaScript 的基本规范? 10 JavaScript 原型,原型链? 有什么特点? 11 js 获取原型的方法? 12 在 js 中不同进制数字的表示方式? 13 js 中整数的安全范围是多少? 14 typeof NaN 的结果是什么? 15 isNaN 和 Number.isNaN 函数的区别? 16 Array 构造函数只有一个参数值时的表现? 17 其他值到字符串的转换规则? 18 其他值到数字值的转换规则? 19 其他值到布尔类型的值的转换规则? 20 {} 和 [] 的 valueOf 和 toString 的结果是什么? 21 什么是假值对象? 22 ~ 操作符的作用? 23 解析字符串中的数字和将字符串强制类型转换为数字的返回结果都是数字,它们之间的区别是什么? 24 + 操作符什么时候用于字符串的拼接? 25 什么情况下会发生布尔值的隐式强制类型转换? 26 || 和 && 操作符的返回值? 27 Symbol 值的强制类型转换? 28 == 操作符的强制类型转换规则? 29 如何将字符串转化为数字,例如 '12.3b'? 30 如何将浮点数点左边的数每三位添加一个逗号,如 12000000.11 转化为『12,000,000.11』? 31 常用正则表达式? 32 生成随机数的各种方法? 33 如何实现数组的随机排序? 34 javascript 创建对象的几种方式? 35 JavaScript 继承的几种实现方式? 36 寄生式组合继承的实现? 37 Javascript 的作用域链? 38 谈谈 This 对象的理解。 39 eval 是做什么的? 40 什么是 DOM 和 BOM? 41 写一个通用的事件侦听器函数。 42 事件是什么?IE 与火狐的事件机制有什么区别? 如何阻止冒泡? 43 三种事件模型是什么? 44 事件委托是什么? 45 ['1', '2', '3'].map(parseInt) 答案是多少? 46 什么是闭包,为什么要用它? 47 javascript 代码中的 'use strict'; 是什么意思 ? 使用它区别是什么? 48 如何判断一个对象是否属于某个类? 49 instanceof 的作用? 50 new 操作符具体干了什么呢?如何实现? 51 Javascript 中,有一个函数,执行时对象查找时,永远不会去查找原型,这个函数是? 52 对于 JSON 的了解? 53 [].forEach.call($$(''),function(a){a.style.outline='1px solid #'+(~~(Math.random()(1<<24))).toString(16)}) 能解释一下这段代码的意思吗? 54 js 延迟加载的方式有哪些? 55 Ajax 是什么? 如何创建一个 Ajax? 56 谈一谈浏览器的缓存机制? 57 Ajax 解决浏览器缓存问题? 58 同步和异步的区别? 59 什么是浏览器的同源政策? 60 如何解决跨域问题? 61 服务器代理转发时,该如何处理 cookie? 62 简单谈一下 cookie ? 63 模块化开发怎么做? 64 js 的几种模块规范? 65 AMD 和 CMD 规范的区别? 66 ES6 模块与 CommonJS 模块、AMD、CMD 的差异。 67 requireJS 的核心原理是什么?(如何动态加载的?如何避免多次加载的?如何 缓存的?) 68 JS 模块加载器的轮子怎么造,也就是如何实现一个模块加载器? 69 ECMAScript6 怎么写 class,为什么会出现 class 这种东西? 70 documen.write 和 innerHTML 的区别? 71 DOM 操作——怎样添加、移除、移动、复制、创建和查找节点? 72 innerHTML 与 outerHTML 的区别? 73 .call() 和 .apply() 的区别? 74 JavaScript 类数组对象的定义? 75 数组和对象有哪些原生方法,列举一下? 76 数组的 fill 方法? 77 [,,,] 的长度? 78 JavaScript 中的作用域与变量声明提升? 79 如何编写高性能的 Javascript ? 80 简单介绍一下 V8 引擎的垃圾回收机制 81 哪些操作会造成内存泄漏? 82 需求:实现一个页面操作不会整页刷新的网站,并且能在浏览器前进、后退时正确响应。给出你的技术实现方案? 83 如何判断当前脚本运行在浏览器还是 node 环境中?(阿里) 84 把 script 标签放在页面的最底部的 body 封闭之前和封闭之后有什么区别?浏览器会如何解析它们? 85 移动端的点击事件的有延迟,时间是多久,为什么会有? 怎么解决这个延时? 86 什么是“前端路由”?什么时候适合使用“前端路由”?“前端路由”有哪些优点和缺点? 87 如何测试前端代码么? 知道 BDD, TDD, Unit Test 么? 知道怎么测试你的前端工程么(mocha, sinon, jasmin, qUnit..)? 88 检测浏览器版本版本有哪些方式? 89 什么是 Polyfill ? 90 使用 JS 实现获取文件扩展名? 91 介绍一下 js 的节流与防抖? 92 Object.is() 与原来的比较操作符 '==='、'==' 的区别? 93 escape,encodeURI,encodeURIComponent 有什么区别? 94 Unicode 和 UTF-8 之间的关系? 95 js 的事件循环是什么? 96 js 中的深浅拷贝实现? 97 手写 call、apply 及 bind 函数 98 函数柯里化的实现 99 99. 为什么 0.1 + 0.2 != 0.3?如何解决这个问题? 100 原码、反码和补码的介绍 101 toPrecision 和 toFixed 和 Math.round 的区别? 102 什么是 XSS 攻击?如何防范 XSS 攻击? 103 什么是 CSP? 104 什么是 CSRF 攻击?如何防范 CSRF 攻击? 105 什么是 Samesite Cookie 属性? 106 什么是点击劫持?如何防范点击劫持? 107 SQL 注入攻击? 108 什么是 MVVM?比之 MVC 有什么区别?什么又是 MVP ? 109 vue 双向数据绑定原理? 110 Object.defineProperty 介绍? 111 使用 Object.defineProperty() 来进行数据劫持有什么缺点? 112 什么是 Virtual DOM?为什么 Virtual DOM 比原生 DOM 快? 113 如何比较两个 DOM 树的差异? 114 什么是 requestAnimationFrame ? 115 谈谈你对 webpack 的看法 116 offsetWidth/offsetHeight,clientWidth/clientHeight 与 scrollWidth/scrollHeight 的区别? 117 谈一谈你理解的函数式编程? 118 异步编程的实现方式? 119 Js 动画与 CSS 动画区别及相应实现 120 get 请求传参长度的误区 121 URL 和 URI 的区别? 122 get 和 post 请求在缓存方面的区别 123 图片的懒加载和预加载 124 mouseover 和 mouseenter 的区别? 125 js 拖拽功能的实现 126 为什么使用 setTimeout 实现 setInterval?怎么模拟? 127 let 和 const 的注意点? 128 什么是 rest 参数? 129 什么是尾调用,使用尾调用有什么好处? 130 Symbol 类型的注意点? 131 Set 和 WeakSet 结构? 132 Map 和 WeakMap 结构? 133 什么是 Proxy ? 134 Reflect 对象创建目的? 135 require 模块引入的查找方式? 136 什么是 Promise 对象,什么是 Promises/A+ 规范? 137 手写一个 Promise 138 如何检测浏览器所支持的最小字体大小? 139 怎么做 JS 代码 Error 统计? 140 单例模式模式是什么? 141 策略模式是什么? 142 代理模式是什么? 143 中介者模式是什么? 144 适配器模式是什么? 145 观察者模式和发布订阅模式有什么不同? 146 Vue 的生命周期是什么? 147 Vue 的各个生命阶段是什么? 148 Vue 组件间的参数传递方式? 149 computed 和 watch 的差异? 150 vue-router 中的导航钩子函数 151 两个router 的区别? 152 vue 常用的修饰符? 153 computed 和 watch 区别? 154 keep-alive 组件有什么作用? 155 vue 中 mixin 和 mixins 区别? 156 开发中常用的几种 Content-Type ? 157 如何封装一个 javascript 的类型判断函数? 158 如何判断一个对象是否为空对象? 159 使用闭包实现每隔一秒打印 1,2,3,4 160 手写一个 jsonp 161 手写一个观察者模式? 162 EventEmitter 实现 163 一道常被人轻视的前端 JS 面试题 164 如何确定页面的可用性时间,什么是 Performance API? 165 js 中的命名规则 166 js 语句末尾分号是否可以省略? 167 Object.assign() 168 Math.ceil 和 Math.floor 169 js for 循环注意点 170 一个列表,假设有 100000 个数据,这个该怎么办? 171 js 中倒计时的纠偏实现? 172 进程间通信的方式? 173 如何查找一篇英文文章中出现频率最高的单词? 174 174道 JavaScript 面试题,合集

剑曼红尘 2020-04-02 14:05:35 0 浏览量 回答数 0

阿里云试用中心,为您提供0门槛上云实践机会!

0元试用32+款产品,最高免费12个月!拨打95187-1,咨询专业上云建议!

回答

拜托,数据库自己有这个功能######这回复,怎一个拽字了得######是要插入数据库,看明白需求再讲######想快用python###### shell脚本就搞定了 cut -f1,2,3 -d" "  然后拼接SQL就了 ######例子我写在后面了######有例子吗###### 不明白你为什么头上要加一个空格,split可以跟表示空白符的正则 split("\\\W"); ###### f = open("t.txt", "r") lines = f.readlines() for line in lines: words = line.split() if len(words) < 2: continue key1 = words[0] key2 = words[1]######有问题就解决呗[20]######谢谢,思路是对的,按照你的思路,但新的问题来了,有空麻烦解决下######split()方法接收的是一个正则表达式,写成.split("\\W+")应该就ok了。######回复 @panfanglin : 大写的……######\\w根本就不可以######瓶颈的地方应该在插入数据库的地方,可以考虑用多线程分片插入数据库 ######回复 @cyb_beta : 额######回复 @panfanglin : 例子没有,可以考虑数据库连接池######兄台说的是,有例子吗######如果是Oracle可以尝试 sqlloader,Google一下吧!######是mysql###### 如果全是空格分隔,试试正则 split(" +"); 不行用\\W ###### 数据库连接来回开关你不觉得很蛋疼 初始化的时候开一次,最后一次关掉就可以了吧。 我也没看懂你那个计数。 你有没觉得你那每次都处理了一次  

kun坤 2020-06-06 16:23:58 0 浏览量 回答数 0

问题

【python学习全家桶】263道python热门问题,阿里百位技术专家答疑解惑

管理贝贝 2019-12-01 20:07:21 7217 浏览量 回答数 2

回答

  关于 SQLite 的优化,首先是能用SQL语句的,就不要单笔操作, Cursor 就更是能不用就不用。比如成批的 DELETE/UPDATE ,将条件组装到 SQL 语句,会比使用 CURSOR 一条条的查再删效率要高很多( 若干年前就曾使用存储过程代替单笔操作,将一次批量计算时间从一晚上缩到了一小时以内 )。其次是对操作的优化:对于 INSERT/UPDATE 操作较多时使用事务,如果SELECT操作较多时,使用索引。   结合现在的工作,发现针对操作的优化,下面 这篇文章 可以翻译出来归档。以下为正文:   SQLite 有一个简洁的SQL接口,且以低内存占用著称。现如今, SQLite 已经在 Android 及 iOS 开发中得到广泛的应用。本文主要讨论在 Android 应用如何优化 SQLite 的性能和资源占用。   1, 使用事务( Transaction )   在默认情况下每一个SQL语句都被包一个全新的事务内,比如执行一个如INSERT这样基本的数据库操作,就会放到一个新创建的事务中执行。一次只需要操作一次数据库操作时,让SQLite自己来进行事务管理当然是明智的。但如果一次有大量的操作要做时,比如循环调用INSERT添加时,这样就显得开销过大了,因为每一笔操作都要重新打开、写入,最后再关闭journal文件, 这个文件是临时用来保存数据操作的中间结果,详细内容看这里( 参考 )。   如果明确地在一系列SQL语句前后以 BEGIN TRANSACTION 及 END TRANSACTION 这样显示地使用事务就可以避免上面的情况。对于那些不会改变数据的操作,这样的方式也同样可以提速(好似数据库操作中单笔的操作效率将远低于批次操作,如果用SQL语句可以搞定的事,就不可使用Cursor进行操作)。   注明:除了发起事务外,你必须还要负责对事务的提交和回滚操作。   在Android应用开发中可以使用类似如下的方式使用 BEGIN TRANSACTION 及 END TRANSACTION :   db.beginTransaction(); try{ for(int i =0; i< LENGTH ; i++,sequenceNum++) { // execute SQL } db.setTransactionSuccessful();// marks a commit } finally{ db.endTransaction(); }   2. 使用索引   如果没有在数据库使用索引,当你在一个没有排序的数据表中使用映射查询(projection query)搜索时,无可避免的要执行一个全序列查找。这种情况通常并不是什么问题,每种数据库,包括SQLite都会为数据集执行索引来降低查找时间。   索引维护着一个表中某一列或某几列的顺序,这样就可以快速定位到一组值,而不用扫遍全表。所有的索引信息会被保存在一个独立的索引表中,所以会产生额外的空间占用,不过绝对物超所值,特别是当你会在数据库中进行大量的读及搜索操作时。   SQLite会自动为每一个UNIQUE栏位创建索引,包括主键(Primary Key)栏位,另外也可以通过CREATE INDEX进行显示地创建。   注:如果你的查询太复杂而无法使用所创建的索引,那你就要好好想想你数据库的结构了。   3. 在Where分支中使用限定符   如果以字串拼接出SQL语句的Where,莫不如使用SQLite的query操作带上'?'来编译查询。以下是它的好处:   a. 有利于SQLite缓存这些查询。   b. 可以避免达到SQLite缓存的上限。使用字串拼接Where的查询,每一个都被视为不同的查询,这就容易达到缓存的上限。   c. 可以避免非法的SQL注入。    “答案来源于网络,供您参考” 希望以上信息可以帮到您!

牧明 2019-12-02 02:17:55 0 浏览量 回答数 0

问题

【Java学习全家桶】1460道Java热门问题,阿里百位技术专家答疑解惑

管理贝贝 2019-12-01 20:07:15 27612 浏览量 回答数 19

问题

OpenSearch的搜索处理是什么?

轩墨 2019-12-01 20:57:06 1661 浏览量 回答数 0

问题

二叉树 7月21日 【今日算法】

游客ih62co2qqq5ww 2020-07-25 07:44:02 0 浏览量 回答数 0

回答

字符串的操作 字符串的连接操作 符号: +格式:str1 + str2例如:str1 = 'I Love' str2 = 'You!' print(str1 + str2) >>> 'I Love You!' 返回值:str字符串的复制操作 符号: *格式:str * num例如:str = 'abc' num = 3 print(str1 * num) >>> 'abcabcabc' 返回值:str字符串的索引操作 符号: []格式:str[index]例如:str = 'abcde' print(str[2]) >>> 'c' 返回值:str字符串的切片操作 符号: [::]格式:str[index:index:step]例如:str = 'abcdefg' print(str[:]) >>> 'abcdefg' #取字符串所有内容,开头的0可以忽略 print(str[:3]) >>> 'abc' #取出字符串索引0-3的内容(顾头不顾尾,不包含索引3的对象) print(str[:5:2]) >>> 'ace' #取出字符串索引0-5的内容,每2个索引取一次 print(str[3:]) >>> 'defg' #取出字符串索引3开始到结尾的内容 print(str[-2:]) >>> 'fg' #取出字符串倒数第2开始到结尾的内容 返回值:str 内置方法 连接 格式:x.__add__(y)等同于x+y返回值:str 包含 格式:x.__contains__(y)返回值:bool相等 格式:x.__eq__(y)等同于x==y返回值:bool大于等于 格式:x.__ge__(y)等同于x>=y返回值:bool访问属性方法(文件操作时用) 格式:x.__getattribute__(self,name)返回值:tuple获取键值对(字典操作时用) 格式:x.__getitem__(key)返回值:键的值 大于 格式:x.__gt__(y)等同于x>y返回值:bool哈希值 格式:x.__hash__()返回值:哈希值,int类型迭代器 格式:x.__iter__()返回值:迭代器小于等于 格式:x.__le__(y)等同于x<=y返回值:bool长度 格式:x.__len__()等同于len(x)返回值:int类型小于 格式:x.__lt__()返回值:布尔类型复制 格式:x.__mul__(y)等同于x*y返回值:str注::此处的y必须是int类型 不等于 格式:x.__ne__(y)等同于x!=y返回值:bool右->左 复制 格式:x.__rmul__(y)等同于y*x返回值:str注:此处的y必须是int类型 常用方法 首字母大写,后面的小写 格式:x.capitalize() #开头第一个单词首字母大写,后面的所有字符串全部小写 例如:x = = 'i am A 好 boy' print(x.capitalize()) >>> 'I am a 好 boy' 返回值:str全部字符小写 格式:x.casefold() #字符串中所有单词的所有字母全部小写 例如:x = = 'i am A 好 boy' print(x.casefold()) >>> 'i am a 好 boy' 返回值:str居中,两边默认以空格填充 格式:x.center() #定义字符串的长度,不足长度时,两边以指定字符串进行填充 例如:x = 'abc' print(x.center(20,'*')) >>> '********abc*********' 返回值:str计数(默认全文计数) 格式:x.count(str,index1,index2) #指定开始和结束范围来统计某字符串的个数 例如:x = 'sffefwsf' print(x.count('sf'),0,8) >>> 2 返回值:int类型编码 格式:x.encode() #指定字符串的编码格式 例如:x.encode(encoding='utf-8')#转换为utf-8格式返回值:bytes以什么为结尾 格式:x.endswith(str,index1,index2) #指定字符串的开始和结束范围,判断所选区域是否是以指定字符串结尾 例如:x = 'adfd' print(x.endswith('fd',2,3)) >>> True 返回值:bool把t转换为空格 格式:x.expandtabs() #默认开头到\t为8个字节,不足以空格填充 例如:x = 'i amt At 好 boy' print(x.expandtabs()) >>> 'i am A 好 boy' 返回值:str查找 格式:x.find(str,index1,index2) #指定开始和结束的范围,查找指定区域内是否由指定的字符串(只返回查找到第一个的索引值) 例如:x = 'asdfdsfsafsaf' print(x.find('df',1,8)) >>> 2 返回值:int类型注:如果find未查找到,将返回为-1 格式化 格式:x.format(*args) #字符串的格式化可以有参数,可以无参数,可以是索引值参数,也可以是关键字参数 无参数 例如:s1 = 'I {} {} {}' print(s1.format('love','you','!')) >>> 'I love you !' 索引参数 例如:s1 = 'I {0} {1} {0} {1}' print(s1.format('love','you')) >>> 'I love you love you' 注:使用索引参数时,只能按顺序,从索引0开始 关键字参数 例如:s1 = 'I {m} {n}' print(s1.format(m = 'love',n = 'you')) >>> 'I love you' 格式限定符 填充常和对齐一起使用: ^ < > 分别是居中,左对齐和右对齐,后面带宽度 : 后面带填充的字符,只能是一个字符,默认是空格 例如: 无(位置)参数:s1 = 'I love you {}' print(s1.format(', very much !')) 'I love you , very much !' 默认居中方法:s1 = 'I love you {:^18}' print(s1.format(', very much !')) 'I love you , very much ! ' 指定字符居中:s1 = 'I love you {:*^18}' print(s1.format(', very much !')) 'I love you , very much !*' 指定字符左对齐:s1 = 'I love you {:*<18}' print(s1.format(', very much !')) 'I love you , very much !*' 指定字符右对齐:s1 = 'I love you {:*>18}' print(s1.format(', very much !')) 'I love you *, very much !' 精度与类型f 例如:s1 = '圆周率大概是{}' print(s1.format(3.1415926)) >>> '圆周率大概是3.1415926' s1 = '圆周率大概是{:.2f}'print(s1.format(3.1415926)) >>> '圆周率大概是3.14' s1 = '圆周率大概是{:.2f}'print(s1.format(3.1415926)) >>> '圆周率大概是3.1416' 注:精度一般和浮点一起使用,取值时使用四舍五入法 进制操作 主要的进制为b、d、o、x,分别是二、十、八、十六进制 例如: 十进制:s1 = 'The pen values {} yuan!'s1 = 'The pen values {:d} yuan!'print(s1.format(17)) >>> 'The pen values 17 yuan!' 二进制:s1 = 'The pen values {:b} yuan!'print(s1.format(17)) >>> 'The pen values 10001 yuan!' 八进制:s1 = 'The pen values {:o} yuan!'print(s1.format(17)) >>> 'The pen values 21 yuan!' 十六进:s1 = 'The pen values {:x} yuan!'print(s1.format(17)) >>> 'The pen values 11 yuan!' 金融字符,千分位 即, 例如:s1 = 'The phone is {}$ !' print(s1.format(10000000)) >>> 'The phone is 10000000$ !' s1 = 'The phone is {:,}$ !'print(s1.format(10000000)) >>> 'The phone is 10,000,000$ !' 返回值:str 查找 格式:x.index(str,index1,index2) #用法和find一样 返回值:int注::当index未查找到,程序将报错 非符号字符串 格式:x.isalnum() #字符串中可以有大小写,可以有数字,但不可以有符号 返回值:bool纯字母的字符串 格式:x.isalpha() #字符串中可以有大小写,但不可以有数字和符号 返回值:bool纯数字的字符串 格式:x.isdecimal() #字符串中只可以数字 返回值:bool纯数字的字符串 格式:x.isdigit() #字符串中只可以数字 返回值:bool开头字母的字符串 格式:x.isidentifier() #字符串以字母开头,可以是大小写,后面可以有数字,但数字不能开头 返回值:bool全部小写 格式:x.islower() #字符串全部是小写,也可以有数字,数字可以开头,但不能全数字 返回值:bool包含中文数字 格式:x.isnumeric() #字符串中可以有数字,也可以有中文大小写数字 返回值:bool可打印 格式:x.isprintable() #打印为空,则为假 返回值:bool空格 格式:x.isspace() #字符串中只能是空格 返回值:bool标题 格式:x.istitle() #字符串中每个单词首字母大写 返回值:bool全部大写 格式:x.isupper() #字符串中可以有数字,数字可以开头,但必须有大写字母 返回值:bool拼接 格式:x.join(str) #把字符串以指定字符串进行相连 例如:x = 'abcde' print('_'.join(x)) >>> 'a_b_c_d_e' 返回值:str左对齐 格式:x.ljust(str) #字符串左对齐,需要指定长度,不足长度时可以用指定字符串进行填充(默认以空格填充),当指定长度小于字符串长度,将会左对齐 例如:x = 'abcde' print(x.ljust(12,'*')) >>> 'abcde*******' 返回值:str全部小写 格式:x.lower() #字符串中所有单词,所有字母全部小写 #与casefold()功能一样 返回值:str去除左边空格 格式:x.lstrip() #去除对字符串左边的指定字符串,字符串中间和结尾的指定字符串不做处理,默认去除的是空格 例如:x = 'aaafdfdfaaadfdsaaa' print(x.lstrip('a')) >>> 'fdfdfaaadfdsaaa' 返回值:str字符串进行分段 格式:x.partition(str) #把字符串以从左到右第一个指定字符串为元素进行分段,以元组形式展现 例如:x = 'acbadfsadfsdfsd' print(x.partition('sa')) >>> ('acbadf', 'sa', 'dfsdfsd') 返回值:tuple字符串替换 格式:x.replace(old,new,count) #把字符串中指定的字符串替换为新字符串,默认全部替换,也可以指定替换次数,如果次数超过存在的个数,将全部替换 例如:x = 'acbadfsadfsdfsd' print(x.replace('df','A',7)) >>> 'acbaAsaAsAsd' 返回值:str右→左 查找 格式:x.rfind(str,index1,index2) #功能同find()一样 返回值:int右→左 查找 格式:x.rindex(str,index1,index2) #功能同index()一样 返回值:int右对齐 格式:x.rjust(str) #字符串右对齐,需要指定长度,不足长度时可以用指定字符串进行填充(默认以空格填充),当指定长度小于字符串长度,将会右对齐 例如:x = 'adc' print(x.rjust(6,'%')) >>> '%%%adc' 返回值:str右→左 字符串分段 格式:x.rpartition(str) #把字符串以从右到左第一个指定字符串进行分段,以元组形式展示 例如:x = 'abccbacbd' print(x.rpartition('cb')) >>> ('abccba', 'cb', 'd') 返回值:tuple字符串切片 格式:x.rsplit(str) #把字符串以指定字符串进行切片,并以列表的形式展现 例如:x = 'abccbacbd' print(x.rsplit('cb')) >>> ['abc', 'a', 'd'] 返回值:list去除右边空格 格式:x.rstrip(str) #去除字符串最右边的指定字符串,左边和中间的指定字符串不做处理,默认去除的是空格 例如:x = 'aaafdfdfaaadfdsaaa' print(x.rstrip('a')) >>> 'aaafdfdfaaadfds' 返回值:str切片 格式:x.split() #把字符串以指定字符串进行切片,并以列表的形式展现 #功能同rsplit()一样 返回值:list换行符分段 格式:x.splitlines() #把字符串以换行符进行切片,并以列表的形式展现 返回值:list以什么为开头 格式:x.startswith(str,index1,index2) #指定字符串的开始和结束范围,判断指定区域是否是以指定字符串开头 例如:x = 'adafsdaf' print(x.startswith('da',1,8)) >>> True 返回值:bool去除两边空格 格式:x.strip(str) #去除字符串两边的指定字符串,中间的指定字符串不做处理,默认去除的是空格 例如:x = 'aaadfsaaafdsfaaa' print(x.strip()) >>> 'dfsaaafdsf' 返回值:str大小写互转 格式:x.swapcase() #字符串中所有的字母进行大小写相互转换 例如:x = 'aBcdE' print(x.swapcase()) >>> 'AbCDe' 返回值:str标题化 格式:x.title() #对字符串中所有单词首字母大写,单词中间的大写全部转换为小写 例如:x = 'asd faDSdsf sdf' print(x.title()) >>> 'Asd Fadsdsf Sdf' 返回值:str全部变大写 格式:x.upper() #字符串中所有字母全部转换为大写 例如:x = 'DFdgDdfdg' print(x.upper()) >>> 'DFDGDDFDG' 返回值:str左对齐,零填充 格式:x.zfill() #字符串左对齐,指定字符串长度,不足部分以0填充 例如:x = 'afd' print(x.zfill(5)) >>> '00afd' 返回值:str映射函数 x.maketrans(*args) #把两个字符串进行一一对应,两个字符串长度必须一致 格式:str.maketrans(str1,str2) bytearray.maketrans(str1,str2) bytes.maketrans(str1,str2) 返回值:dict映射函数 x.translate(*args) #把maketrans()得到的映射表应用出来 格式:x.translate(str.maketrans(str1,str2))返回值:str

xuning715 2019-12-02 01:10:18 0 浏览量 回答数 0

问题

备战大厂每日挑战算法,坚持打卡更有社区定制周边奖品等你赢!

被纵养的懒猫 2020-04-07 11:41:45 5309 浏览量 回答数 5

问题

【精品问答】Java实战200例(附源码)

珍宝珠 2020-02-14 11:55:46 16104 浏览量 回答数 10

问题

【javascript学习全家桶】934道javascript热门问题,阿里百位技术专家答疑解惑

管理贝贝 2019-12-01 20:07:22 6202 浏览量 回答数 1

问题

字符串函数是什么?

nicenelly 2019-12-01 21:26:22 1658 浏览量 回答数 0

回答

Android平台进行数据存储的五大方式,分别如下: 1 使用SharedPreferences存储数据 2 文件存储数据 3 SQLite数据库存储数据 4 使用ContentProvider存储数据 5 网络存储数据 下面详细讲解这五种方式的特点 第一种: 使用SharedPreferences存储数据 适用范围:保存少量的数据,且这些数据的格式非常简单:字符串型、基本类型的值。比如应用程序的各种配置信息(如是否打开音效、是否使用震动效果、小游戏的玩家积分等),解锁口 令密码等 核心原理:保存基于XML文件存储的key-value键值对数据,通常用来存储一些简单的配置信息。通过DDMS的File Explorer面板,展开文件浏览树,很明显SharedPreferences数据总是存储在/data/data/<package name>/shared_prefs目录下。SharedPreferences对象本身只能获取数据而不支持存储和修改,存储修改是通过SharedPreferences.edit()获取的内部接口Editor对象实现。 SharedPreferences本身是一 个接口,程序无法直接创建SharedPreferences实例,只能通过Context提供的getSharedPreferences(String name, int mode)方法来获取SharedPreferences实例,该方法中name表示要操作的xml文件名,第二个参数具体如下: Context.MODE_PRIVATE: 指定该SharedPreferences数据只能被本应用程序读、写。 Context.MODE_WORLD_READABLE: 指定该SharedPreferences数据能被其他应用程序读,但不能写。 Context.MODE_WORLD_WRITEABLE: 指定该SharedPreferences数据能被其他应用程序读,写 Editor有如下主要重要方法: SharedPreferences.Editor clear():清空SharedPreferences里所有数据 SharedPreferences.Editor putXxx(String key , xxx value): 向SharedPreferences存入指定key对应的数据,其中xxx 可以是boolean,float,int等各种基本类型据 SharedPreferences.Editor remove(): 删除SharedPreferences中指定key对应的数据项 boolean commit(): 当Editor编辑完成后,使用该方法提交修改 实际案例:运行界面如下 这里只提供了两个按钮和一个输入文本框,布局简单,故在此不给出界面布局文件了,程序核心代码如下: 、class ViewOcl implements View.OnClickListener{ @Override public void onClick(View v) { switch(v.getId()){ case R.id.btnSet: //步骤1:获取输入值 String code = txtCode.getText().toString().trim(); //步骤2-1:创建一个SharedPreferences.Editor接口对象,lock表示要写入的XML文件名,MODE_WORLD_WRITEABLE写操作 SharedPreferences.Editor editor = getSharedPreferences("lock", MODE_WORLD_WRITEABLE).edit(); //步骤2-2:将获取过来的值放入文件 editor.putString("code", code); //步骤3:提交 editor.commit(); Toast.makeText(getApplicationContext(), "口令设置成功", Toast.LENGTH_LONG).show(); break; case R.id.btnGet: //步骤1:创建一个SharedPreferences接口对象 SharedPreferences read = getSharedPreferences("lock", MODE_WORLD_READABLE); //步骤2:获取文件中的值 String value = read.getString("code", ""); Toast.makeText(getApplicationContext(), "口令为:"+value, Toast.LENGTH_LONG).show(); break; } } } 、读写其他应用的SharedPreferences: 步骤如下 1、在创建SharedPreferences时,指定MODE_WORLD_READABLE模式,表明该SharedPreferences数据可以被其他程序读取 2、创建其他应用程序对应的Context: Context pvCount = createPackageContext("com.tony.app", Context.CONTEXT_IGNORE_SECURITY);这里的com.tony.app就是其他程序的包名 3、使用其他程序的Context获取对应的SharedPreferences SharedPreferences read = pvCount.getSharedPreferences("lock", Context.MODE_WORLD_READABLE); 4、如果是写入数据,使用Editor接口即可,所有其他操作均和前面一致。 SharedPreferences对象与SQLite数据库相比,免去了创建数据库,创建表,写SQL语句等诸多操作,相对而言更加方便,简洁。但是SharedPreferences也有其自身缺陷,比如其职能存储boolean,int,float,long和String五种简单的数据类型,比如其无法进行条件查询等。所以不论SharedPreferences的数据存储操作是如何简单,它也只能是存储方式的一种补充,而无法完全替代如SQLite数据库这样的其他数据存储方式。 第二种: 文件存储数据 核心原理: Context提供了两个方法来打开数据文件里的文件IO流 FileInputStream openFileInput(String name); FileOutputStream(String name , int mode),这两个方法第一个参数 用于指定文件名,第二个参数指定打开文件的模式。具体有以下值可选: MODE_PRIVATE:为默认操作模式,代表该文件是私有数据,只能被应用本身访问,在该模式下,写入的内容会覆盖原文件的内容,如果想把新写入的内容追加到原文件中。可 以使用Context.MODE_APPEND MODE_APPEND:模式会检查文件是否存在,存在就往文件追加内容,否则就创建新文件。 MODE_WORLD_READABLE:表示当前文件可以被其他应用读取; MODE_WORLD_WRITEABLE:表示当前文件可以被其他应用写入。 除此之外,Context还提供了如下几个重要的方法: getDir(String name , int mode):在应用程序的数据文件夹下获取或者创建name对应的子目录 File getFilesDir():获取该应用程序的数据文件夹得绝对路径 String[] fileList():返回该应用数据文件夹的全部文件 public String read() { try { FileInputStream inStream = this.openFileInput("message.txt"); byte[] buffer = new byte[1024]; int hasRead = 0; StringBuilder sb = new StringBuilder(); while ((hasRead = inStream.read(buffer)) != -1) { sb.append(new String(buffer, 0, hasRead)); } inStream.close(); return sb.toString(); } catch (Exception e) { e.printStackTrace(); } return null; } public void write(String msg){ // 步骤1:获取输入值 if(msg == null) return; try { // 步骤2:创建一个FileOutputStream对象,MODE_APPEND追加模式 FileOutputStream fos = openFileOutput("message.txt", MODE_APPEND); // 步骤3:将获取过来的值放入文件 fos.write(msg.getBytes()); // 步骤4:关闭数据流 fos.close(); } catch (Exception e) { e.printStackTrace(); } } openFileOutput()方法的第一参数用于指定文件名称,不能包含路径分隔符“/” ,如果文件不存在,Android 会自动创建它。创建的文件保存在/data/data//files目录,如: /data/data/cn.tony.app/files/message.txt, 下面讲解某些特殊文件读写需要注意的地方: 读写sdcard上的文件 其中读写步骤按如下进行: 1、调用Environment的getExternalStorageState()方法判断手机上是否插了sd卡,且应用程序具有读写SD卡的权限,如下代码将返回true Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED) 2、调用Environment.getExternalStorageDirectory()方法来获取外部存储器,也就是SD卡的目录,或者使用"/mnt/sdcard/"目录 3、使用IO流操作SD卡上的文件 注意点:手机应该已插入SD卡,对于模拟器而言,可通过mksdcard命令来创建虚拟存储卡 必须在AndroidManifest.xml上配置读写SD卡的权限 // 文件写操作函数 private void write(String content) { if (Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)) { // 如果sdcard存在 File file = new File(Environment.getExternalStorageDirectory() .toString() + File.separator + DIR + File.separator + FILENAME); // 定义File类对象 if (!file.getParentFile().exists()) { // 父文件夹不存在 file.getParentFile().mkdirs(); // 创建文件夹 } PrintStream out = null; // 打印流对象用于输出 try { out = new PrintStream(new FileOutputStream(file, true)); // 追加文件 out.println(content); } catch (Exception e) { e.printStackTrace(); } finally { if (out != null) { out.close(); // 关闭打印流 } } } else { // SDCard不存在,使用Toast提示用户 Toast.makeText(this, "保存失败,SD卡不存在!", Toast.LENGTH_LONG).show(); } } // 文件读操作函数 private String read() { if (Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)) { // 如果sdcard存在 File file = new File(Environment.getExternalStorageDirectory() .toString() + File.separator + DIR + File.separator + FILENAME); // 定义File类对象 if (!file.getParentFile().exists()) { // 父文件夹不存在 file.getParentFile().mkdirs(); // 创建文件夹 } Scanner scan = null; // 扫描输入 StringBuilder sb = new StringBuilder(); try { scan = new Scanner(new FileInputStream(file)); // 实例化Scanner while (scan.hasNext()) { // 循环读取 sb.append(scan.next() + "\n"); // 设置文本 } return sb.toString(); } catch (Exception e) { e.printStackTrace(); } finally { if (scan != null) { scan.close(); // 关闭打印流 } } } else { // SDCard不存在,使用Toast提示用户 Toast.makeText(this, "读取失败,SD卡不存在!", Toast.LENGTH_LONG).show(); } return null; } 复制代码 第三种:SQLite存储数据 SQLite是轻量级嵌入式数据库引擎,它支持 SQL 语言,并且只利用很少的内存就有很好的性能。现在的主流移动设备像Android、iPhone等都使用SQLite作为复杂数据的存储引擎,在我们为移动设备开发应用程序时,也许就要使用到SQLite来存储我们大量的数据,所以我们就需要掌握移动设备上的SQLite开发技巧 SQLiteDatabase类为我们提供了很多种方法,上面的代码中基本上囊括了大部分的数据库操作;对于添加、更新和删除来说,我们都可以使用 1 db.executeSQL(String sql); 2 db.executeSQL(String sql, Object[] bindArgs);//sql语句中使用占位符,然后第二个参数是实际的参数集 除了统一的形式之外,他们还有各自的操作方法: 1 db.insert(String table, String nullColumnHack, ContentValues values); 2 db.update(String table, Contentvalues values, String whereClause, String whereArgs); 3 db.delete(String table, String whereClause, String whereArgs);以上三个方法的第一个参数都是表示要操作的表名;insert中的第二个参数表示如果插入的数据每一列都为空的话,需要指定此行中某一列的名称,系统将此列设置为NULL,不至于出现错误;insert中的第三个参数是ContentValues类型的变量,是键值对组成的Map,key代表列名,value代表该列要插入的值;update的第二个参数也很类似,只不过它是更新该字段key为最新的value值,第三个参数whereClause表示WHERE表达式,比如“age > ? and age < ?”等,最后的whereArgs参数是占位符的实际参数值;delete方法的参数也是一样 下面给出demo 数据的添加 1.使用insert方法 复制代码1 ContentValues cv = new ContentValues();//实例化一个ContentValues用来装载待插入的数据2 cv.put("title","you are beautiful");//添加title3 cv.put("weather","sun"); //添加weather4 cv.put("context","xxxx"); //添加context5 String publish = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")6 .format(new Date());7 cv.put("publish ",publish); //添加publish8 db.insert("diary",null,cv);//执行插入操作复制代码2.使用execSQL方式来实现 String sql = "insert into user(username,password) values ('Jack Johnson','iLovePopMuisc');//插入操作的SQL语句db.execSQL(sql);//执行SQL语句数据的删除 同样有2种方式可以实现 String whereClause = "username=?";//删除的条件String[] whereArgs = {"Jack Johnson"};//删除的条件参数db.delete("user",whereClause,whereArgs);//执行删除使用execSQL方式的实现 String sql = "delete from user where username='Jack Johnson'";//删除操作的SQL语句db.execSQL(sql);//执行删除操作数据修改 同上,仍是2种方式 ContentValues cv = new ContentValues();//实例化ContentValuescv.put("password","iHatePopMusic");//添加要更改的字段及内容String whereClause = "username=?";//修改条件String[] whereArgs = {"Jack Johnson"};//修改条件的参数db.update("user",cv,whereClause,whereArgs);//执行修改使用execSQL方式的实现 String sql = "update user set password = 'iHatePopMusic' where username='Jack Johnson'";//修改的SQL语句db.execSQL(sql);//执行修改数据查询 下面来说说查询操作。查询操作相对于上面的几种操作要复杂些,因为我们经常要面对着各种各样的查询条件,所以系统也考虑到这种复杂性,为我们提供了较为丰富的查询形式: 1 db.rawQuery(String sql, String[] selectionArgs); 2 db.query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy); 3 db.query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit); 4 db.query(String distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit); 上面几种都是常用的查询方法,第一种最为简单,将所有的SQL语句都组织到一个字符串中,使用占位符代替实际参数,selectionArgs就是占位符实际参数集; 各参数说明: table:表名称colums:表示要查询的列所有名称集selection:表示WHERE之后的条件语句,可以使用占位符selectionArgs:条件语句的参数数组groupBy:指定分组的列名having:指定分组条件,配合groupBy使用orderBy:y指定排序的列名limit:指定分页参数distinct:指定“true”或“false”表示要不要过滤重复值Cursor:返回值,相当于结果集ResultSet最后,他们同时返回一个Cursor对象,代表数据集的游标,有点类似于JavaSE中的ResultSet。下面是Cursor对象的常用方法: 复制代码 1 c.move(int offset); //以当前位置为参考,移动到指定行 2 c.moveToFirst(); //移动到第一行 3 c.moveToLast(); //移动到最后一行 4 c.moveToPosition(int position); //移动到指定行 5 c.moveToPrevious(); //移动到前一行 6 c.moveToNext(); //移动到下一行 7 c.isFirst(); //是否指向第一条 8 c.isLast(); //是否指向最后一条 9 c.isBeforeFirst(); //是否指向第一条之前 10 c.isAfterLast(); //是否指向最后一条之后 11 c.isNull(int columnIndex); //指定列是否为空(列基数为0) 12 c.isClosed(); //游标是否已关闭 13 c.getCount(); //总数据项数 14 c.getPosition(); //返回当前游标所指向的行数 15 c.getColumnIndex(String columnName);//返回某列名对应的列索引值 16 c.getString(int columnIndex); //返回当前行指定列的值 复制代码实现代码 复制代码String[] params = {12345,123456};Cursor cursor = db.query("user",columns,"ID=?",params,null,null,null);//查询并获得游标if(cursor.moveToFirst()){//判断游标是否为空 for(int i=0;i<cursor.getCount();i++){ cursor.move(i);//移动到指定记录 String username = cursor.getString(cursor.getColumnIndex("username"); String password = cursor.getString(cursor.getColumnIndex("password")); } }复制代码通过rawQuery实现的带参数查询 复制代码Cursor result=db.rawQuery("SELECT ID, name, inventory FROM mytable");//Cursor c = db.rawQuery("s name, inventory FROM mytable where ID=?",new Stirng[]{"123456"}); result.moveToFirst(); while (!result.isAfterLast()) { int id=result.getInt(0); String name=result.getString(1); int inventory=result.getInt(2); // do something useful with these result.moveToNext(); } result.close();复制代码 在上面的代码示例中,已经用到了这几个常用方法中的一些,关于更多的信息,大家可以参考官方文档中的说明。 最后当我们完成了对数据库的操作后,记得调用SQLiteDatabase的close()方法释放数据库连接,否则容易出现SQLiteException。 上面就是SQLite的基本应用,但在实际开发中,为了能够更好的管理和维护数据库,我们会封装一个继承自SQLiteOpenHelper类的数据库操作类,然后以这个类为基础,再封装我们的业务逻辑方法。 这里直接使用案例讲解:下面是案例demo的界面 SQLiteOpenHelper类介绍 SQLiteOpenHelper是SQLiteDatabase的一个帮助类,用来管理数据库的创建和版本的更新。一般是建立一个类继承它,并实现它的onCreate和onUpgrade方法。 方法名 方法描述SQLiteOpenHelper(Context context,String name,SQLiteDatabase.CursorFactory factory,int version) 构造方法,其中 context 程序上下文环境 即:XXXActivity.this; name :数据库名字; factory:游标工厂,默认为null,即为使用默认工厂; version 数据库版本号 onCreate(SQLiteDatabase db) 创建数据库时调用onUpgrade(SQLiteDatabase db,int oldVersion , int newVersion) 版本更新时调用getReadableDatabase() 创建或打开一个只读数据库getWritableDatabase() 创建或打开一个读写数据库首先创建数据库类 复制代码 1 import android.content.Context; 2 import android.database.sqlite.SQLiteDatabase; 3 import android.database.sqlite.SQLiteDatabase.CursorFactory; 4 import android.database.sqlite.SQLiteOpenHelper; 5 6 public class SqliteDBHelper extends SQLiteOpenHelper { 7 8 // 步骤1:设置常数参量 9 private static final String DATABASE_NAME = "diary_db";10 private static final int VERSION = 1;11 private static final String TABLE_NAME = "diary";12 13 // 步骤2:重载构造方法14 public SqliteDBHelper(Context context) {15 super(context, DATABASE_NAME, null, VERSION);16 }17 18 /*19 * 参数介绍:context 程序上下文环境 即:XXXActivity.this 20 * name 数据库名字 21 * factory 接收数据,一般情况为null22 * version 数据库版本号23 */24 public SqliteDBHelper(Context context, String name, CursorFactory factory,25 int version) {26 super(context, name, factory, version);27 }28 //数据库第一次被创建时,onCreate()会被调用29 @Override30 public void onCreate(SQLiteDatabase db) {31 // 步骤3:数据库表的创建32 String strSQL = "create table "33 + TABLE_NAME34 + "(tid integer primary key autoincrement,title varchar(20),weather varchar(10),context text,publish date)";35 //步骤4:使用参数db,创建对象36 db.execSQL(strSQL);37 }38 //数据库版本变化时,会调用onUpgrade()39 @Override40 public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) {41 42 }43 }复制代码正如上面所述,数据库第一次创建时onCreate方法会被调用,我们可以执行创建表的语句,当系统发现版本变化之后,会调用onUpgrade方法,我们可以执行修改表结构等语句。 我们需要一个Dao,来封装我们所有的业务方法,代码如下: 复制代码 1 import android.content.Context; 2 import android.database.Cursor; 3 import android.database.sqlite.SQLiteDatabase; 4 5 import com.chinasoft.dbhelper.SqliteDBHelper; 6 7 public class DiaryDao { 8 9 private SqliteDBHelper sqliteDBHelper;10 private SQLiteDatabase db;11 12 // 重写构造方法13 public DiaryDao(Context context) {14 this.sqliteDBHelper = new SqliteDBHelper(context);15 db = sqliteDBHelper.getWritableDatabase();16 }17 18 // 读操作19 public String execQuery(final String strSQL) {20 try {21 System.out.println("strSQL>" + strSQL);22 // Cursor相当于JDBC中的ResultSet23 Cursor cursor = db.rawQuery(strSQL, null);24 // 始终让cursor指向数据库表的第1行记录25 cursor.moveToFirst();26 // 定义一个StringBuffer的对象,用于动态拼接字符串27 StringBuffer sb = new StringBuffer();28 // 循环游标,如果不是最后一项记录29 while (!cursor.isAfterLast()) {30 sb.append(cursor.getInt(0) + "/" + cursor.getString(1) + "/"31 + cursor.getString(2) + "/" + cursor.getString(3) + "/"32 + cursor.getString(4)+"#");33 //cursor游标移动34 cursor.moveToNext();35 }36 db.close();37 return sb.deleteCharAt(sb.length()-1).toString();38 } catch (RuntimeException e) {39 e.printStackTrace();40 return null;41 }42 43 }44 45 // 写操作46 public boolean execOther(final String strSQL) {47 db.beginTransaction(); //开始事务48 try {49 System.out.println("strSQL" + strSQL);50 db.execSQL(strSQL);51 db.setTransactionSuccessful(); //设置事务成功完成 52 db.close();53 return true;54 } catch (RuntimeException e) {55 e.printStackTrace();56 return false;57 }finally { 58 db.endTransaction(); //结束事务 59 } 60 61 }62 }复制代码我们在Dao构造方法中实例化sqliteDBHelper并获取一个SQLiteDatabase对象,作为整个应用的数据库实例;在增删改信息时,我们采用了事务处理,确保数据完整性;最后要注意释放数据库资源db.close(),这一个步骤在我们整个应用关闭时执行,这个环节容易被忘记,所以朋友们要注意。 我们获取数据库实例时使用了getWritableDatabase()方法,也许朋友们会有疑问,在getWritableDatabase()和getReadableDatabase()中,你为什么选择前者作为整个应用的数据库实例呢?在这里我想和大家着重分析一下这一点。 我们来看一下SQLiteOpenHelper中的getReadableDatabase()方法: 复制代码 1 public synchronized SQLiteDatabase getReadableDatabase() { 2 if (mDatabase != null && mDatabase.isOpen()) { 3 // 如果发现mDatabase不为空并且已经打开则直接返回 4 return mDatabase; 5 } 6 7 if (mIsInitializing) { 8 // 如果正在初始化则抛出异常 9 throw new IllegalStateException("getReadableDatabase called recursively"); 10 } 11 12 // 开始实例化数据库mDatabase 13 14 try { 15 // 注意这里是调用了getWritableDatabase()方法 16 return getWritableDatabase(); 17 } catch (SQLiteException e) { 18 if (mName == null) 19 throw e; // Can't open a temp database read-only! 20 Log.e(TAG, "Couldn't open " + mName + " for writing (will try read-only):", e); 21 } 22 23 // 如果无法以可读写模式打开数据库 则以只读方式打开 24 25 SQLiteDatabase db = null; 26 try { 27 mIsInitializing = true; 28 String path = mContext.getDatabasePath(mName).getPath();// 获取数据库路径 29 // 以只读方式打开数据库 30 db = SQLiteDatabase.openDatabase(path, mFactory, SQLiteDatabase.OPEN_READONLY); 31 if (db.getVersion() != mNewVersion) { 32 throw new SQLiteException("Can't upgrade read-only database from version " + db.getVersion() + " to " 33 + mNewVersion + ": " + path); 34 } 35 36 onOpen(db); 37 Log.w(TAG, "Opened " + mName + " in read-only mode"); 38 mDatabase = db;// 为mDatabase指定新打开的数据库 39 return mDatabase;// 返回打开的数据库 40 } finally { 41 mIsInitializing = false; 42 if (db != null && db != mDatabase) 43 db.close(); 44 } 45 }复制代码在getReadableDatabase()方法中,首先判断是否已存在数据库实例并且是打开状态,如果是,则直接返回该实例,否则试图获取一个可读写模式的数据库实例,如果遇到磁盘空间已满等情况获取失败的话,再以只读模式打开数据库,获取数据库实例并返回,然后为mDatabase赋值为最新打开的数据库实例。既然有可能调用到getWritableDatabase()方法,我们就要看一下了: 复制代码public synchronized SQLiteDatabase getWritableDatabase() { if (mDatabase != null && mDatabase.isOpen() && !mDatabase.isReadOnly()) { // 如果mDatabase不为空已打开并且不是只读模式 则返回该实例 return mDatabase; } if (mIsInitializing) { throw new IllegalStateException("getWritableDatabase called recursively"); } // If we have a read-only database open, someone could be using it // (though they shouldn't), which would cause a lock to be held on // the file, and our attempts to open the database read-write would // fail waiting for the file lock. To prevent that, we acquire the // lock on the read-only database, which shuts out other users. boolean success = false; SQLiteDatabase db = null; // 如果mDatabase不为空则加锁 阻止其他的操作 if (mDatabase != null) mDatabase.lock(); try { mIsInitializing = true; if (mName == null) { db = SQLiteDatabase.create(null); } else { // 打开或创建数据库 db = mContext.openOrCreateDatabase(mName, 0, mFactory); } // 获取数据库版本(如果刚创建的数据库,版本为0) int version = db.getVersion(); // 比较版本(我们代码中的版本mNewVersion为1) if (version != mNewVersion) { db.beginTransaction();// 开始事务 try { if (version == 0) { // 执行我们的onCreate方法 onCreate(db); } else { // 如果我们应用升级了mNewVersion为2,而原版本为1则执行onUpgrade方法 onUpgrade(db, version, mNewVersion); } db.setVersion(mNewVersion);// 设置最新版本 db.setTransactionSuccessful();// 设置事务成功 } finally { db.endTransaction();// 结束事务 } } onOpen(db); success = true; return db;// 返回可读写模式的数据库实例 } finally { mIsInitializing = false; if (success) { // 打开成功 if (mDatabase != null) { // 如果mDatabase有值则先关闭 try { mDatabase.close(); } catch (Exception e) { } mDatabase.unlock();// 解锁 } mDatabase = db;// 赋值给mDatabase } else { // 打开失败的情况:解锁、关闭 if (mDatabase != null) mDatabase.unlock(); if (db != null) db.close(); } } }复制代码大家可以看到,几个关键步骤是,首先判断mDatabase如果不为空已打开并不是只读模式则直接返回,否则如果mDatabase不为空则加锁,然后开始打开或创建数据库,比较版本,根据版本号来调用相应的方法,为数据库设置新版本号,最后释放旧的不为空的mDatabase并解锁,把新打开的数据库实例赋予mDatabase,并返回最新实例。 看完上面的过程之后,大家或许就清楚了许多,如果不是在遇到磁盘空间已满等情况,getReadableDatabase()一般都会返回和getWritableDatabase()一样的数据库实例,所以我们在DBManager构造方法中使用getWritableDatabase()获取整个应用所使用的数据库实例是可行的。当然如果你真的担心这种情况会发生,那么你可以先用getWritableDatabase()获取数据实例,如果遇到异常,再试图用getReadableDatabase()获取实例,当然这个时候你获取的实例只能读不能写了 最后,让我们看一下如何使用这些数据操作方法来显示数据,界面核心逻辑代码: 复制代码public class SQLiteActivity extends Activity { public DiaryDao diaryDao; //因为getWritableDatabase内部调用了mContext.openOrCreateDatabase(mName, 0, mFactory); //所以要确保context已初始化,我们可以把实例化Dao的步骤放在Activity的onCreate里 @Override protected void onCreate(Bundle savedInstanceState) { diaryDao = new DiaryDao(SQLiteActivity.this); initDatabase(); } class ViewOcl implements View.OnClickListener { @Override public void onClick(View v) { String strSQL; boolean flag; String message; switch (v.getId()) { case R.id.btnAdd: String title = txtTitle.getText().toString().trim(); String weather = txtWeather.getText().toString().trim();; String context = txtContext.getText().toString().trim();; String publish = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") .format(new Date()); // 动态组件SQL语句 strSQL = "insert into diary values(null,'" + title + "','" + weather + "','" + context + "','" + publish + "')"; flag = diaryDao.execOther(strSQL); //返回信息 message = flag?"添加成功":"添加失败"; Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show(); break; case R.id.btnDelete: strSQL = "delete from diary where tid = 1"; flag = diaryDao.execOther(strSQL); //返回信息 message = flag?"删除成功":"删除失败"; Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show(); break; case R.id.btnQuery: strSQL = "select * from diary order by publish desc"; String data = diaryDao.execQuery(strSQL); Toast.makeText(getApplicationContext(), data, Toast.LENGTH_LONG).show(); break; case R.id.btnUpdate: strSQL = "update diary set title = '测试标题1-1' where tid = 1"; flag = diaryDao.execOther(strSQL); //返回信息 message = flag?"更新成功":"更新失败"; Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show(); break; } } } private void initDatabase() { // 创建数据库对象 SqliteDBHelper sqliteDBHelper = new SqliteDBHelper(SQLiteActivity.this); sqliteDBHelper.getWritableDatabase(); System.out.println("数据库创建成功"); } }复制代码 Android sqlite3数据库管理工具 Android SDK的tools目录下提供了一个sqlite3.exe工具,这是一个简单的sqlite数据库管理工具。开发者可以方便的使用其对sqlite数据库进行命令行的操作。 程序运行生成的.db文件一般位于"/data/data/项目名(包括所处包名)/databases/.db",因此要对数据库文件进行操作需要先找到数据库文件: 1、进入shell 命令 adb shell2、找到数据库文件 cd data/data ls --列出所有项目 cd project_name --进入所需项目名 cd databases ls --列出现寸的数据库文件 3、进入数据库 sqlite3 test_db --进入所需数据库 会出现类似如下字样: SQLite version 3.6.22Enter ".help" for instructionsEnter SQL statements terminated with a ";"sqlite>至此,可对数据库进行sql操作。 4、sqlite常用命令 .databases --产看当前数据库.tables --查看当前数据库中的表.help --sqlite3帮助.schema --各个表的生成语句 原文地址https://www.cnblogs.com/ITtangtang/p/3920916.html

auto_answer 2019-12-02 01:50:21 0 浏览量 回答数 0
阿里云大学 云服务器ECS com域名 网站域名whois查询 开发者平台 小程序定制 小程序开发 国内短信套餐包 开发者技术与产品 云数据库 图像识别 开发者问答 阿里云建站 阿里云备案 云市场 万网 阿里云帮助文档 免费套餐 开发者工具 企业信息查询 小程序开发制作 视频内容分析 企业网站制作 视频集锦 代理记账服务 2020阿里巴巴研发效能峰会 企业建站模板 云效成长地图 高端建站