对于SQLite结合PHP的开发感兴趣的读者,本文将会是一篇不错的选择,我们将详细介绍sqlphp,并为您提供关于BOA+PHP+SQLite之SQLite、Codeigniter(CI)结合PHPE
对于SQLite结合PHP的开发感兴趣的读者,本文将会是一篇不错的选择,我们将详细介绍sql php,并为您提供关于BOA+PHP+SQLite之SQLite、Codeigniter(CI)结合PHPExcel类完成数据导入、Content Provider与SQLite结合使用、hadoop的安装,主从设置及结合php的应用的有用信息。
本文目录一览:- SQLite结合PHP的开发(sql php)
- BOA+PHP+SQLite之SQLite
- Codeigniter(CI)结合PHPExcel类完成数据导入
- Content Provider与SQLite结合使用
- hadoop的安装,主从设置及结合php的应用
SQLite结合PHP的开发(sql php)
sqlite是一款轻型的数据库,它的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了。它能够支持Windows/linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如Tcl、php、java等,还有ODBC接口,同样比起MySQL、Postgresql这两款开源世界著名的数据库管理系统来讲,它的处理速度比他们都快。
sqlite虽然很小巧,但是支持的sql语句不会逊色于其他开源数据库,它支持的sql包括:
ATTACH DATABASE
BEGIN TRANSACTION
comment
COMMIT TRANSACTION
copY
CREATE INDEX
CREATE TABLE
CREATE TRIGGER
CREATE VIEW
DELETE
DETACH DATABASE
DROP INDEX
DROP TABLE
DROP TRIGGER
DROP VIEW
END TRANSACTION
EXPLAIN
exPRession
INSERT
ON CONFLICT clause
PRAGMA
REPLACE
ROLLBACK TRANSACTION
SELECT
UPDATE
同时它还支持事务处理功能等等。也有人说它象Microsoft的access,有时候真的觉得有点象,但是事实上它们区别很大。比如sqlite支持跨平台,操作简单,能够使用很多语言直接创建数据库,而不象Access一样需要Office的支持。如果你是个很小型的应用,或者你想做嵌入式开发,没有合适的数据库系统,那么现在你可以考虑使用sqlite。目前它的最新版本是 3.2.2,它的官方网站是:http://www.sqlite.org,能在上面获得源代码和文档。同时因为数据库结构简单,系统源代码也不是很多,也适合想研究数据库系统开发的专业人士。
现在我们开始简单的介绍,主要我是想讲清楚几个问题,一是如何安装使用,二是如何跟PHP结合开发。
一、安装
1. Windows平台
下载windows下的文件,其实就是一个命令行程序,(下载地址:http://www.sqlite.org/sqlite-3_2_2.zip),这个命令行程序用来包括生成数据库文件、执行SQL查询、备份数据库等等功能。
下载后比如我们解压缩到 D:\Downloads\sqlite\sqlite-3_2_2 这个目录下,那么我们进入cmd,并且进入该目录:
cd D:\Downloads\sqlite\sqlite-3_2_2 D:\Downloads\sqlite\sqlite-3_2_2>sqlite3 test.db
# 如果test.db不存在,那么就产生一个数据库文件,如果存在就直接使用该数据库文件,相当于MysqL中的use
sqlite version 3.2.2
Enter ".help" for instructions
sqlite>
# sqlite的提示符,如果想查看命令帮助输入 .help,在sqlite中所有系统命令都是 . 开头的:
# 查看帮助
sqlite> .help
# 我们创建一个数据库catlog
sqlite> create table catalog( ...> id integer primarykey,...> pid integer,...> name varchar(10) UNIQUE ...> ); sqlite>
# 如果表存在就会提示:
sql error: table catalog already exists
# 我们创建索引信息
create index catalog_idx on catalog (id asc);# 我们查看表的信息,看有多少个表
sqlite> .table aa catalog# 查看表的结构:
sqlite> .schema catalog CREATE TABLE catalog( id integer primary key,pid integer,name varchar(10) UNIQUE ); CREATE INDEX catalog_idx on catalog(id asc);# 给数据表插入一条记录
sqlite> insert into catalog (ppid,name) values ('001','heiyeluren');# 成功无任何提示,如果表达式错误提示错误信息:
sql error: near "set": Syntax error
# 检索有多少条记录
sqlite> select count(*) from catalog; 1# 检索搜索记录
sqlite> select * from catalog; 1|1|heiyeluren
反正使用标准的sql来操作就没有问题,不清楚可以去官方网站上查看帮助信息。另外还要说明的是sqlite不支持修改表结构,如果要修改表结构,只有删除表重新再建立,所以建立表的时候一定要考虑扩展性。估计以后这方面的功能会加强。
2. Linux/Unix 平台
error: 目前还没装过,呵呵,不过估计跟Windows差不多,改天把这部分内容补上。
二、PHP对sqlite的开发
PHP 5开始不再默认支持MysqL,而是默认支持sqlite,可见它的影响力多么大,所以如果你想做sqlite的PHP开发,建议你使用PHP 5.0.0以上版本,我目前使用的是 PHP 5.0.4版本,直接支持sqlite扩展,这里我就不仔细讲如何安装PHP扩展,如果不清楚可以查看PHP相关文档。
这里我主要是讲针对sqlite的开发。目前PHP的主流DB类都支持sqlite的驱动,包括PEAR::DB类、ADOdb类都支持,所以使用DB来来做开发也是个好的选择。
(以下操作为了简便,都是再Windows平台进行的)
1. 使用PHP操作已经建立好的sqlite数据库
如果你有一个已经通过sqlite.exe建立好了的数据库和表结构,那么你就能够直接对它进行操作。PHP中针对sqlite的处理函数比较多,你可以查看PHP手册获得详细信息。
我们使用sqlite_open()函数来打开一个sqlite数据库,它成功返回一个操作资源,失败返回false,那么以后的所有操作都是在这个资源上进行的,执行一个SQL查询使用sqlite_query函数。
下面我假设你在当前PHP程序目录下有一个abc.db的sqlite数据库文件,我们对该文件进行操作:
<?PHP //打开sqlite数据库 $db = @sqlite_open("abc.db"); //异常处理 if (!$db) die("Connection sqlite Failed.\n"); //添加一个叫做foo的数据库 @sqlite_query($db,"CREATE TABLE foo (bar varchar(10))"); //插入一条记录 @sqlite_query($db,"INSERT INTO foo VALUES ('fnord')"); //检索所有记录 $result = @sqlite_query($db,'select bar from foo'); //打印获取的结果 print_r(sqlite_fetch_array($result)); ?>
我们看到的输出结果是:
Array
(
[0] => fnord
[bar] => fnord
)
证明我们代码执行成功,没有输入请检查程序,或者你的数据库文件是否存在。
那么有了这个基本操作,你就能够考虑使用更复杂的操作和sql来操作它,让它帮你管理信息,你可以做一个留言本,或者做一个CMS系统,我想都是没有问题的。
2. 使用PHP建立数据库并且操作
如果你没有任何sqlite.exe之类的工具,那么你也能够通过PHP来创建一个sqlite数据库,并且对它进行管理。
其实通过sqlite.exe程序建立的数据库,内容是空的,其实只有后来等创建表,添加数据以后,数据库文件才有,那么我们是不是能够手工添加一个文件,比如一个空的 test.db 文件,并且对它进行操作。这是完全可以,下面我们就使用PHP程序来完成创建一个数据库,并且执行简单的建立数据表,插入数据和检索数据的功能。
首先我们来看代码:(代码比较长,但比较容易理解)
<?PHP define("LN",__LINE__);//行号 define("FL",__FILE__);//当前文件 define("DEBUG",0);//调试开关 $db_name = "heiyeluren.db"; //创建数据库文件,文件内容为空 if (!file_exists($db_name)) { if (!($fp = fopen($db_name,"w+"))) { exit(error_code(-1,LN)); } fclose($fp); } //打开数据库文件 if (!($db = sqlite_open($db_name))) { exit(error_code(-2,LN)); } //产生数据表结构 if (!sqlite_query($db,"DROP TABLE test")) { exit(error_code(-3,LN)); } if (!sqlite_query($db,"CREATE TABLE test (id integer primary key,name varchar(10) UNIQUE)")) { exit(error_code(-3,LN)); } //插入一条数据 if (!sqlite_query($db," INSERT INTO test (name) VALUES ('heiyeluren') ")) { exit(error_code(-4,LN)); } //把数据检索出来 if (!($result = sqlite_query($db,"SELECT * FROM test"))) { exit(error_code(-5,LN)); } //获取检索数据并显示 while ($array = sqlite_fetch_array($result)) { echo "ID: ". $array[id] ."<br>Name: ". $array[name] ; } /* 错误信息代码函数 */ function error_code($code,$line_num,$debug=DEBUG) { if ($code<-6 || $code>-1) { return false; } switch($code) { case -1: $errmsg = "Create database file error."; break; case -2: $errmsg = "Open sqlite database file Failed."; break; case -3: $errmsg = "Create table Failed,table already exist."; break; case -4: $errmsg = "Insert data Failed."; break; case -5: $errmsg = "Query database data Failed."; break; case -6: $errmsg = "Fetch data Failed."; break; case -7: $errmsg = ""; break; default: $errmsg = "UnkNown error."; } $m = "<b>[ Error ]</b><br>File: ". basename(FL) ." <br>Line: ". LN ."<br>Mesg: ". $errmsg .""; if (!$debug) { ($m = $errmsg); } return $m; } ?>
如果你操作无误的话,那么程序最后输出:
ID: 1
Name: heiyeluren
我们以上的程序包括了比较完整的功能,有调试、异常处理、存取数据库等功能,算是一个简单应用。如果你有兴趣也可以进行扩展。
* sqlite资源
官方网站:http://www.sqlite.org
sql语法:http://www.sqlite.org/lang.html
开发文档:http://www.sqlite.org/docs.html
常见问题:http://www.sqlite.org/faq.html
下载地址:http://www.sqlite.org/download.html
BOA+PHP+SQLite之SQLite
欢迎进入Linux社区论坛,与200万技术人员互动交流 >>进入 SQLite 1第一种办法pc机上要安装交叉编译环境(我安装的是arm-linux-gcc 3.4.1) 把sqlite-3.5.6.tar.gz解压#tar -vzxf sqlite-3.5.6.tar.gz进入sqlite-3.5.6目录#cd sqlite-3.5.6创建sqlite-arm目
欢迎进入linux社区论坛,与200万技术人员互动交流 >>进入
SQLite 第一种办法pc机上要安装交叉编译环境(我安装的是arm-linux-gcc 3.4.1)
把sqlite-3.5.6.tar.gz解压#tar -vzxf sqlite-3.5.6.tar.gz进入sqlite-3.5.6目录#cd sqlite-3.5.6创建sqlite-arm目录,并进入该目录#mkdir sqlite-3.5.6 #cd sqlite-arm
接着输入以下命令:#……/configure ――prefix=/home/tong/sqlite-3.5.6/sqlite-arm ――disable-tcl ――host=arm-linux configure:是软件的组态设置文件,产生对应平台的Makefile文件,――prefix:表示产生的文件的存放目录
接着进行编译并进行安装#make \\根据Makefile的内容 编译出符合平台的可执行文件#make install \\安装编译成功的软件
执行完以上命令就会在/home/tong/sqlite-3.5.6/sqlite-arm/目录下产生:bin,include,lib等
可以分别使用如下命令把动态库文件的调试信息给剥离,减少文件所占有的空间#arm-linux-strip libsqlite3.so.0.8.6 #arm-linux-strip sqlite3
把bin目录下的sqlite3文件和lib目录下所有的文件都复制到新创建的目录sqlite,然后把sqlite整个文件夹烧到板上(我的存放的位置是/mnt/yaffs/,由于lib目录的libsqlite3.so和libsqlte3.so.0是libsqlite3.so.0.8.6的软连接文件,所以复制不了,可以先去不管它)
设置环境变量[/mnt/yaffs/sqlite]export LD_LIBRARY_PATH=/mnt/yaffs/sqlite/:$LD_LIBRARY_PATH [/mnt/yaffs/sqlite]export PATH=/mnt/yaffs/sqlite/:$PATH
接下来建立软连接[/mnt/yaffs/sqlite]ln -s libsqlite3.so.0.8.6 libsqlite3.so.0 [/mnt/yaffs/sqlite]ln -s libsqlite3.so.0.8.6 libsqlite3.so
这样,移植就算完成了[/mnt/yaffs/sqlite]sqlite3 test.db出现如下内容,表示成功SQLite version 3.5.6 Enter ".help" for instructions sqlite>在>后输入一个; test.db方可创建成功接着,编写一个连接sqlite数据库的程序,在2410上运行
view plainprint?
#include
int main( void )
{ sqlite3 *db=NULL;int rc;rc = sqlite3_open("test.db", &db); //打开指定的数据库文件,如果不存在将创建一个同名的数据库文件if( rc ){ fprintf(stderr, "Can''t open database: %s\n", sqlite3_errmsg(db));sqlite3_close(db);exit(1);} else printf("open test.db successfully!\n");
sqlite3_close(db); //关闭数据库return 0;}
#include
编译程序:tong@tong-desktop:~/exp$arm-linux-gcc -L /sqlite-3.3.8 -I /sqlite-3.3.8 -o test1 test1.c -lsqlite3
-lsqlite3 -L/home/tong/sqlite-3.5.6/sqlite-arm/lib:表示在/home/tong/sqlite-3.5.6/sqlite-arm/lib目录中寻找sqlite3的库文件
-I/home/tong/sqlite-3.5.6/sqlite-arm/include:表示在/home/tong/sqlite-3.5.6/sqlite-arm/include目录中寻找头文件
查看产生的文件的属性:tong@tong-desktop:~/exp$ file sqlite_connect sqlite_connect: ELF 32-bit LSB executable, arm, version 1, dynamically linked (uses shared libs), for GNU/Linux 2.4.3, not stripped
把sqlite_connect文件烧到板上,运行:[/mnt/yaffs/test]./sqlite_connect open test.db successfully!
成功!!!
第二种办法在arm-Linux平台上移植SQLite
(陈云川 200620603001 ybc2084@163.com 四川成都)
摘要:本文首先对嵌入式数据库SQLite做了简单的介绍,对移植所采用的软硬件平台作了简单的说明。然后以SQLite3为蓝本对移植过程中的细节作了详细的说明,并对移植后的SQLite3数据库进行了测试。测试结果表明,本文所采取的移植方式是有效的。
关键字:arm-Linux、嵌入式、SQLite
Port SQLite to arm-Linux Platform(Yun Chuan Chen, 200620603001, ybc2084@163.com, Chengdu Sichuan)
Abstract: This paper first give a brief introduction to SQLite database and the hardware and software platform to port. Then demonstrate SQLite3‘s porting process to ARM-Linux in detail and test the ported SQLite3. The testing result states that the porting method this paper proposed is effective. Keywords: arm-Linux、embedded、SQLite
1、引言本文将简要介绍如何在arm-Linux平台上移植SQLite嵌入式数据库。SQLite是一个采用C语言开发的嵌入式数据库引擎。SQLite的最新版本是3.3.8,在不至于引起混淆的情况下,本文也将其简称为SQLite3.数 据库的目标是 实现对数据的存储、检索等功能。传统的数据库产品除提供了基本的查询、添加、删除等功能外,也提供了很多高级特性,如触发器、存储过程、数据备份恢复等。 但实际上用到这些高级功能的时候并不多,应用中频繁用到的还是数据库的基本功能。于是,在一些特殊的应用场合,传统的数据库就显得过于臃肿了。在这种情况 下,嵌入式数据库开始崭露头角。嵌入式数据库是一种具备了基本数据库特性的数据文件,它与传统数据库的区别是:嵌入式数据库采用程序方式直接驱动,而传统 数据库则采用引擎响应方式驱动。嵌入式数据库的体积通常都很小,这使得嵌入式数据库常常应用在移动设备上。由于性能卓越,所以在高性能的应用上也经常见到 嵌入式数据库的身影。
SQLite是一种嵌入式数据库。SQLite的目标是尽量简单,因此它抛弃了传统企业级数据库的种种复杂特性,只实现那 些对于数据库而言非常必要的功能。尽管简单性是SQLite追求的首要目标,但是其功能和性能都非常出色。它具有这样一些特点[1]: 支持ACID事务(ACID是Atomic、Consistent、Isolated、Durable的缩写);零配置,不需要任何管理性的配置过程;实 现了大部分SQL92标准;所有数据存放在一个单独的文件之中,支持的文件大小最高可达2TB;数据库可以在不同字节序的机器之间共享;体积小,在去掉可 选功能的情况下,代码体积小于150KB,即使加入所有可选功能,代码大小也不超过250KB;系统开销小,检索效率高,执行常规数据库操作时速度比客户 /服务器类型的数据库快;简单易用的API接口;可以和Tcl、Python、C/C++、Java、Ruby、Lua、Perl、PHP等多种语言绑 定;自包含,不依赖于外部支持;良好注释的代码;代码测试覆盖率达95%以上;开放源码,可以用于任何合法用途。由于这样一些杰出的优点,SQLite获 得了由Google与O‘Reilly举办的2005 Open Source Award!
由于SQLite具有功能强大、接口简单、速度快、占用空间小这样一些特殊的优点,因此特别适合于应用在嵌入式环境中。SQLite在手机、PDA、机顶盒等设备上已获得了广泛应用。本文将说明如何在arm-Linux内核的基础上移植SQLite3. 2、软硬件平台本 文中采用的硬件平台为Sitsang嵌入式评估板。Sitsang评估板的核心是PXA255嵌入式处理器,PXA255是一款基于Intel XScale微架构的高性能、低功耗嵌入式处理器。Sitsang评估板上配备了Flash存储器、LCD、触摸屏、USB接口、以太网接口、全功能串口 (FFUART)、蓝牙串口(BTUART)、音频接口等诸多硬件资源。
底层软件系统是以ARM-Linux内核为基础的。Sitsang评估板使用的arm-Linux是在linux-2.4.19内核上打了patch-2.4.19-sitsang2补丁后编译而成。
[1] [2]
Codeigniter(CI)结合PHPExcel类完成数据导入
1. 安装PHPExcel到Codeigniter
1) 解压压缩包里的Classes文件夹中的内容到application\libraries\目录下,目录结构如下:
– application\libraries\PHPExcel.php
– application\libraries\PHPExcel (文件夹)
2)修改application\libraries\PHPExcel\IOFactory.php 文件
立即学习“PHP免费学习笔记(深入)”;
– 将其类名从PHPExcel_IOFactory改为IOFactory,遵从CI类命名规则。
– 将其构造函数改为public(__construct)
2. 安装完毕,写一个导出excel的控制器(Controller)
public function index(){
//判断上传文件存在值
if(!empty($_FILES)){
$filename = $_FILES[''file''][''name''];//被上传文件的名称
$filetype = $_FILES["file"]["type"];//被上传文件的类型
$filesize = $_FILES["file"]["size"];// 被上传文件的大小,以字节计
$filetmp = $_FILES["file"]["tmp_name"];//存储在服务器的文件的临时副本的名称
$fileerror = $_FILES["file"]["error"];//由文件上传导致的错误代码
//判断是否上传成功
if($fileerror==0){
//判断是否是excel表格
if($filetype=="application/vnd.ms-excel" || $filetype=="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"){
/*设置保存路径*/
$filePath = ''uploads/excel/'';
$str = "";
/*加载PHPExcel*/
$this->load->library(''PHPExcel.php'');
$this->load->library(''PHPExcel/IOFactory.php'');
//$this->load->library(''PHPExcel/Reader/Excel5.php'');
//注意设置时区
$time=date("YmdHis");//去当前上传的时间
//获取上传文件的扩展名
$extend=strrchr ($filename,''.'');
//上传后的文件名
$name=$time.$extend;
//上传后的文件名地址
$uploadfile=$filePath.$name;//上传后的文件名地址
//move_uploaded_file() 函数将上传的文件移动到新位置。若成功,则返回 true,否则返回 false。
$result=move_uploaded_file($filetmp,$uploadfile);//假如上传到当前目录下
//echo $result;
//如果上传文件成功,就执行导入excel操作
if($result){
$inputFileType = IOFactory::identify($uploadfile);//确定输入文件的格式
$objReader = IOFactory::createReader($inputFileType);//穿件相对应的阅读器
$objPHPExcel = $objReader->load($uploadfile); //加载要读取的文件
$sheet = $objPHPExcel->getSheet(); //得到当前活动sheet
$highestRow = $sheet->getHighestRow(); //取得总行数
$highestColumn = $sheet->getHighestColumn(); //取得总列数
// print_r($highestRow);
//print_r($highestColumn);
/* 第一种方法
//循环读取excel文件,读取一条,插入一条
for($j=1;$j {
for($k=''A'';$k {
//
//这种方法简单,但有不妥,以''\\''合并为数组,再分割\\为字段值插入到数据库
//实测在excel中,如果某单元格的值包含了\\导入的数据会为空
//
$str .=$objPHPExcel->getActiveSheet()->getCell("$k$j")->getValue().''\\'';//读取单元格
}
//echo $str; die();
//explode:函数把字符串分割为数组。
$strs = explode("\\",$str);
print_r($strs);
$sql = "INSERT INTO te(`id`, `name`) VALUES (
''{$strs[0]}'',
''{$strs[1]}'')";
//die($sql);
if(!mysql_query($sql))
{
return false;
echo ''sql语句有误'';
}
mysql_query($sql);
$str = "";
}
unlink($uploadfile); //删除上传的excel文件
$msg = "导入成功!";
*/
/* 第二种方法*/
$objWorksheet = $objPHPExcel->getActiveSheet();
$highestRow = $objWorksheet->getHighestRow();
$highestColumn = $objWorksheet->getHighestColumn();
$highestColumnIndex = PHPExcel_Cell::columnIndexFromString($highestColumn);//总列数
$headtitle=array();
for ($row = 2;$row
$arr=array();
//注意highestColumnIndex的列数索引从0开始
for ($col = 0;$col
$arr[$col] =$objWorksheet->getCellByColumnAndRow($col, $row)->getValue();
}
// $sql = "INSERT INTO admins(`account`, `pwd`, `username`, `power`, `tel`,`sex`,`work_numjob`,`job`,`sector`) VALUES (
// ''{$strs[0]}'',
// ''{$strs[1]}'',
// ''{$strs[2]}'',
// ''{$strs[3]}'',
// ''{$strs[4]}'',
// ''{$strs[5]}'',
// ''{$strs[6]}'',
// ''{$strs[7]}'',
// ''{$strs[8]}'',)";
$data=array(
''account''=>$arr[''0''],
''pwd''=>$arr[''1''],
''username''=>$arr[''2''],
''power''=>$arr[''3''],
''tel''=>$arr[''4''],
''sex''=>$arr[''5''],
''work_num''=>$arr[''6''],
''job''=>$arr[''7''],
''sector''=>$arr[''8''],
);
$this->db->insert("admins",$data);
}
unlink($uploadfile);
show_msg("导入成功",site_url("链接地址"));//跳转地址
//删除上传的excel文件
}
}else{
show_msg("上传文件非cvs格式,请重新上传");
}
}else{
switch ($fileerror){
case 1:
show_msg("上传的文件超过了 php.ini 中 upload_max_filesize 选项限制的值.");
break;
case 2:
show_msg("上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值");
break;
case 3:
show_msg("文件只有部分被上传");
break;
case 4:
show_msg("没有文件被上传");
break;
}
}
}
}
注意事项:阅读方式excel方式不能指定死,让他自动识别文件来自动读取。
3. 读取excel详细资料
1. 导入一个Excel最简单的方法是使用PHPExel的IO Factory,调用PHPExcel_IOFactory类的静态法load,它可以自动识别文档格式,包括Excel2007、 Excel2003XML、OOCalcSYLK、Gnumeric、CSV。返回一个PHPExcel的实例。
//加载工厂类
include''PHPExcel/IOFactory.php'';
//要读取的xls文件路径
$inputFileName = ''./sampleData/example1.xls'';
/** 用PHPExcel_IOFactory的load方法得到excel操作对象 **/
$objPHPExcel = PHPExcel_IOFactory::load($inputFileName);
//得到当前活动表格,调用toArray方法,得到表格的二维数组
$sheetData =$objPHPExcel->getActiveSheet()->toArray(null,true,true,true);
var_dump($sheetData);
1. 创建一个ExcelReader去加载一个Excel文档
如果你知道这个Excel文档的格式,可以建立一个相应的Reader去加载要读取的Excel文档。但是如果你加载了错误的文档类型,可会产生不可预知的错误。
$inputFileName = ''./sampleData/example1.xls'';
/** Create a new Excel5 Reader **/
$objReader = new PHPExcel_Reader_Excel5();
// $objReader = new PHPExcel_Reader_Excel2007();
// $objReader = new PHPExcel_Reader_Excel2003XML();
// $objReader = new PHPExcel_Reader_OOCalc();
// $objReader = new PHPExcel_Reader_SYLK();
// $objReader = new PHPExcel_Reader_Gnumeric();
// $objReader = new PHPExcel_Reader_CSV();
/** Load $inputFileName to a PHPExcel Object **/
$objPHPExcel = $objReader->load($inputFileName);
//得到当前活动sheet
$curSheet =$objPHPExcel->getActiveSheet();
//以二维数组形式返回该表格的数据
$sheetData = $curSheet->toArray(null,true,true,true);
var_dump($sheetData);
也可以用PHPExcel_IOFactory的createReader方法去得到一个Reader对象,无需知道要读取文件的格式。
$inputFileType = ''Excel5'';
// $inputFileType = ''Excel2007'';
// $inputFileType = ''Excel2003XML'';
// $inputFileType = ''OOCalc'';
// $inputFileType = ''SYLK'';
// $inputFileType = ''Gnumeric'';
// $inputFileType = ''CSV'';
$inputFileName = ''./sampleData/example1.xls'';
/** Create a new Reader of the type defined in $inputFileType **/
$objReader = PHPExcel_IOFactory::createReader($inputFileType);
/** Load $inputFileName to a PHPExcel Object **/
$objPHPExcel = $objReader->load($inputFileName);
//得到当前活动sheet
$curSheet = $objPHPExcel->getActiveSheet();
//以二维数组形式返回该表格的数据
$sheetData = $curSheet->toArray(null,true,true,true);
var_dump($sheetData);
如果在读取文件之前,文件格式未知,你可以通过IOFactory 的 identify()方法得到文件类型,然后通过createReader()方法去穿件阅读器。
$inputFileName = ''./sampleData/example1.xls'';
/** 确定输入文件的格式 **/
$inputFileType = PHPExcel_IOFactory::identify($inputFileName);
/** 穿件相对应的阅读器 **/
$objReader = PHPExcel_IOFactory::createReader($inputFileType);
/** 加载要读取的文件 **/
$objPHPExcel = $objReader->load($inputFileName);
在使用load()方法加载文件之前,可以设置读取选项来控制load的行为.
2.1.ReadingOnly Data from a Spreadsheet File
setReadDataOnly()方法,配置阅读器不关注表格数据的数据类型,都以string格式返回
$inputFileType = ''Excel5'';
$inputFileName = ''./sampleData/example1.xls'';
/** Create a new Reader of the type defined in $inputFileType **/
$objReader = PHPExcel_IOFactory::createReader($inputFileType);
/** 配置单元格数据都以字符串返回 **/
$objReader->setReadDataOnly(true);
/** Load $inputFileName to a PHPExcel Object **/
$objPHPExcel = $objReader->load($inputFileName);
$sheetData =$objPHPExcel->getActiveSheet()->toArray(null,true,true,true);
var_dump($sheetData);
详细资料:http://blog.csdn.net/andy1219111/article/details/7673796;
Content Provider与SQLite结合使用
前言
虽然推荐使用数据库保存结构化的复杂数据,但是数据共享是一个挑战,因为数据库只允许创建它的应用访问。
在Android中共享数据
在Android中,推荐使用content provider方法在不同包之间共享数据。content provider可以被视为一个数据仓库。它如何存储数据与应用如何使用它无关。然而,应用如何使用一致的编程接口在它的里面的数据非常重要。content provider的行为与数据库非常相似——你可以查询它、编辑它的内容、添加或者删除内容。然而,与数据库不同的是,一个content provider可以使用不同的方式存储它的数据。数据可以被存储在数据库中、在文件中、甚至在网络上。
Android提供了许多非常有用的content provider,包括以下几种:
类型 | 说明 |
---|---|
browser | 存储浏览器数据,比如浏览器的书签、浏览器访问历史等。 |
CallLog | 存储通话数据,比如未接电话、通话详情等。 |
Contacts | 存储通讯录详情。 |
MediaStore | 存储多媒体文件,比如音频、视频和图片。 |
Settings | 存储设备的设置和偏好设置。 |
除了许多内置的content provider以外,可以创建自定义的content provider。
要查询一个content provider,需要以统一的资源标识符(Uniform Resource Identifier,URI)的形式制定查询字符串,以及一个可选的特定行说明符。以下是查询URI的形式:
<standard_prefix>://<authority>/<data_path>/<id>
URI的各种组成部分如下:
组成 | 说明 |
---|---|
content provider | content provider的标准前缀是content:// 。 |
authority | 指定content provider的名称。例如内置Contacts的content provider的名称为contacts。对于第三方content provider来说,它可以是完整的合法名称,例如com.wrox.provider。 |
data_path | 指定请求的数据种类。例如,如果你要从Contacts的content provider中获取所有的通讯录,那么data_path应该是people,URI将类似与:content://contacts/people 。 |
id | 指定请求特定的记录。例如,如果你要获取Contacts的content provider中第2条通讯录,URI将类似类似于:content://contact/people/2 。 |
查询字符串 | 描述 |
---|---|
content://media/internal/images | 返回设备上保存在内部存储中的图片列表。 |
content://media/external/images | 返回设备上保存在外部存储(例如SD卡)中的图片列表。 |
content://call_log/calls | 返回登记在通话记录中的通话记录。 |
content://browser/bookmarks | 返回存储在浏览器中的书签列表。 |
使用content provider
理解content provider的最佳方法是在实践中使用它。
Main2Activity
public class Main2Activity extends ListActivity { final private int REQUEST_READ_CONTACTS = 123; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); if (ContextCompat.checkSelfPermission(this,Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.READ_CONTACTS},REQUEST_READ_CONTACTS); } else { listContacts(); } } @Override public void onRequestPermissionsResult(int requestCode,@NonNull String[] permissions,@NonNull int[] grantResults) { switch (requestCode) { case REQUEST_READ_CONTACTS: if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { listContacts(); } else { Toast.makeText(Main2Activity.this,"Permission Denied",Toast.LENGTH_SHORT).show(); } break; default: super.onRequestPermissionsResult(requestCode,permissions,grantResults); } } protected void listContacts() { Uri allContacts = Uri.parse("content://contacts/people"); CursorLoader cursorLoader = new CursorLoader( this,allContacts,null,null); Cursor cursor = cursorLoader.loadInBackground(); String[] columns = new String[]{ ContactsContract.Contacts.disPLAY_NAME,ContactsContract.Contacts._ID}; int[] views = new int[]{R.id.contactName,R.id.contactID}; SimpleCursorAdapter adapter; adapter = new SimpleCursorAdapter( this,R.layout.activity_main2,cursor,columns,views,CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER); this.setlistadapter(adapter); } }
本示例获取了存储在Contacts应用中的通讯录并且将其显示在ListView中。
首先指定访问Contacts应用的URI:
Uri allContacts = Uri.parse("content://contacts/people");
其次,检查应用是否由访问Contacts的权限:
if (ContextCompat.checkSelfPermission(this,Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this,REQUEST_READ_CONTACTS); } else { listContacts(); }
如果没有访问权限,就会发出一条权限请求(使Android弹出一个权限请求对话框)。如果应用由相应的访问权限,ListContacts()方法会被调用。
getContentResolver()方法返回一个ContentResolver对象,它会使用适当content provider解析内容URI。
CursorLoader类(Android API level 11及以上版本可用)在后再线程中执行cursor查询操作,因此不会阻塞应用UI。
CursorLoader cursorLoader = new CursorLoader( this,null); Cursor cursor = cursorLoader.loadInBackground();
SimpleCursorAdapter对象将一个Cursor数据映射到XML文件(activity_main2.xml)中定义的TextView(或者ImageView)。它将数据(对应于代码中的columns变量)映射到视图(对应于代码中的view变量)中:
String[] columns = new String[]{ ContactsContract.Contacts.disPLAY_NAME,ContactsContract.Contacts._ID }; int[] views = new int[]{ R.id.contactName,R.id.contactID }; SimpleCursorAdapter adapter = new SimpleCursorAdapter( this,CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER); this.setlistadapter(adapter);
类似于managedQuery()方法,SimpleCursorAdapter类的一个构造函数已经被弃用。对于运行Honeycomb及后续版本的设备,需要使用新的SimpleCursorAdapter类的构造函数,与旧版本相比,该构造函数多一个参数:
SimpleCursorAdapter adapter = new SimpleCursorAdapter( this,CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
新的标志参数将该适配器注册为观察者,当Content Provider发生变化时,该适配器会被通知。
注意,如果你的应用要访问Contacts应用,需要在AndroidManifest.xml文件中添加READ_CONTACTS权限。
CursorLoader说明
CursorLoader (Context context,Uri uri,String[] projection,String selection,String[] selectionArgs,String sortOrder)
参数 | 类型 | 说明 |
---|---|---|
context | Context | |
uri | Uri | Uri: The URI,using the content:// scheme,for the content to retrieve. This value must never be null. |
projection | String | String: A list of which columns to return. Passing null will return all columns,which is inefficient. |
selection | String | String: A filter declaring which rows to return,formatted as an sql WHERE clause (excluding the WHERE itself). Passing null will return all rows for the given URI. |
selectionArgs | String | String: You may include ?s in selection,which will be replaced by the values from selectionArgs,in the order that they appear in the selection. The values will be bound as Strings.This value may be null. |
sortOrder | String | String: How to order the rows,formatted as an sql ORDER BY clause (excluding the ORDER BY itself). Passing null will use the default sort order,which may be unordered. |
预定义查询字符串常量
Uri allContacts = Uri.parse("content://contacts/people");
等同于:
Uri allContacts = ContactsContract.Contacts.CONTENT_URI;
在下面的示例中,通过访问ContactsContract.Contacts._ID
字段获取一条通讯录的ID,通过访问ContactsContract.Contacts.disPLAY_NAME
字段获取一条通讯录的姓名。如果想要显示通讯录电话号码,可以再次查询content provider,因为这个信息存储在另外一个表中:
private void printContacts(Cursor c) { if (c.movetoFirst()) { do { String contactID = c.getString(c.getColumnIndex(ContactsContract.Contacts._ID)); String contactdisplayName = c.getString(c.getColumnIndex( ContactsContract.Contacts.disPLAY_NAME)); Log.v("ContentProviders",contactID + "," + contactdisplayName); // 获取电话号码 Cursor phoneCursor = getContentResolver().query( ContactsContract.CommonDataKinds.Phone.CONTENT_URI,ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + contactID,null); assert phoneCursor != null; while (phoneCursor.movetoNext()) { Log.v("ContentProviders",phoneCursor.getString(phoneCursor.getColumnIndex( ContactsContract.CommonDataKinds.Phone.NUMBER))); } phoneCursor.close(); } while (c.movetoNext()); } }
注意,要访问通讯录中的电话号码,需要使用保存在
ContactsContract.CommonDataKinds.Phone.CONTENT_URI
常量中的URI查询。
显示结果:
V/ContentProviders: 1,I think is okay V/ContentProviders: 100 V/ContentProviders: 2,Java V/ContentProviders: 1 234-567-9 V/ContentProviders: 3,Kotlin V/ContentProviders: 1 23 V/ContentProviders: 4,Scala V/ContentProviders: 45 V/ContentProviders: 5,Python V/ContentProviders: 78 V/ContentProviders: 6,Ruby V/ContentProviders: 36 V/ContentProviders: 7,Gradle V/ContentProviders: 258- V/ContentProviders: 8,JavaScript V/ContentProviders: 1 4 V/ContentProviders: 9,Haskell V/ContentProviders: 1 5 V/ContentProviders: 10,C/C+ V/ContentProviders: 35 V/ContentProviders: 11,Html+CSS V/ContentProviders: 248-6
指定查询字段
CursorLoader类的第三个参数控制查询返回多少列。这个参数称为Projections(映射)。
String[] projection = new String[]{ ContactsContract.Contacts._ID,ContactsContract.Contacts.disPLAY_NAME }; CursorLoader cursorLoader = new CursorLoader( this,projection,null); Cursor cursor = cursorLoader.loadInBackground();
筛选
CursorLoader类的第四和第五个参数指定一个sql WHERE语句用来筛选查询的结果。例如,以下示例代码仅仅获取姓名以Lee
结尾的通讯录:
String[] projection = new String[]{ ContactsContract.Contacts._ID,ContactsContract.Contacts.disPLAY_NAME }; CursorLoader cursorLoader = new CursorLoader( this,ContactsContract.Contacts.disPLAY_NAME + " LIKE ?",new String[]{"%Lee"},null; Cursor cursor = cursorLoader.loadInBackground();
排序
CursorLoader类的最后一个参数指定sql ORDER BY语句用来排序查询结果。例如,以下示例代码将通讯录姓名以升序排序:
String[] projection = new String[]{ ContactsContract.Contacts._ID,ContactsContract.Contacts.disPLAY_NAME + " ASC"); Cursor cursor = cursorLoader.loadInBackground();
自定义Content Provider
AndroidManifest.xml
先在AndroidManifest.xml
中添加如下语句:
<provider android:name=".BooksProvider" android:authorities="link_work.myapplication.provider.Books" android:exported="false" />
说明:android:authorities="<包名>.provider.Books"
BooksProvider
方法 | 说明 |
---|---|
getType() | 返回给定URI的数据的MIME类型。 |
onCreate() | 当provider启动时调用。 |
query() | 收到一条客户的请求。结果将以Cursor对象返回。 |
insert() | 向content provider插入一条新的记录。 |
delete() | 从content provider中删除一条已存在的记录。 |
update() | 从content provider中更新一条已存在的记录。 |
在自定义的content provider中,可以自由地选择如何存储数据——使用传统文件系统、XML文件、数据库,或者通过Web服务。在本示例中,使用的是sqlite数据库方案。
@SuppressLint("Registered") public class BooksProvider extends ContentProvider { /** * 常量 */ static final String PROVIDER_NAME = "link_work.myapplication.provider.Books"; static final Uri CONTENT_URI = Uri.parse("content://" + PROVIDER_NAME + "/books"); static final String ID = "_id"; static final String TITLE = "title"; static final String ISBN = "isbn"; static final int BOOKS = 1; static final int BOOK_ID = 2; private static final UriMatcher URI_MATCHER; /* * * 使用URI_MATCHER对象解析内容URI,将内容URI通过ContentResolver传递给 * content provider。例如,以下内容URI表示请求content provider中的所 * 有图书。 * */ static { URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH); URI_MATCHER.addURI(PROVIDER_NAME,"books",BOOKS); URI_MATCHER.addURI(PROVIDER_NAME,"books/#",BOOK_ID); } /** * ---数据库实例--- */ sqliteDatabase booksDB; static final String DATABASE_NAME = "Books"; static final String DATABASE_TABLE = "titles"; static final int DATABASE_VERSION = 1; static final String DATABASE_CREATE = "create table " + DATABASE_TABLE + " (_id integer primary key autoincrement," + "title text not null,isbn text not null);"; /** * 要删除一本书,需要重写delete方法。 * 同样,在删除成功后调用ContentResolver的notifyChange方法。 * 它会通知已注册的观察者有一条记录要删除。 * */ @Override public int delete(@NonNull Uri arg0,String arg1,String[] arg2) { // arg0 = uri // arg1 = selection // arg2 = selectionArgs int count; switch (URI_MATCHER.match(arg0)) { case BOOKS: count = booksDB.delete(DATABASE_TABLE,arg1,arg2); break; case BOOK_ID: String id = arg0.getPathSegments().get(1); count = booksDB.delete(DATABASE_TABLE,ID + " = " + id + (!TextUtils.isEmpty(arg1) ? " AND (" + arg1 + ')' : ""),arg2); break; default: throw new IllegalArgumentException("UnkNown URI " + arg0); } getContext().getContentResolver().notifyChange(arg0,null); return count; } /** * 重写getType方法,为自定义Content Provider描述数据类型。使用UriMatcher对象解析 * URI,vnd.android.cursor.item/vnd.<包名>.books表示返回一条图书记录, * vnd.android.cursor.dir/vnd.<包名>.books表示返回多条图书记录。 * */ @Override public String getType(@NonNull Uri uri) { switch (URI_MATCHER.match(uri)) { //---获取所有的书籍--- case BOOKS: return "vnd.android.cursor.dir/vnd.link_work.myapplication.books "; //---获取指定的书籍--- case BOOK_ID: return "vnd.android.cursor.item/vnd.link_work.myapplication.books "; default: throw new IllegalArgumentException("Unsupported URI: " + uri); } } /** * 默认情况下,查询的结果按照title字段排序。查询结果以Cursor对象返回。 * 为了能够向content Provider中插入新的图书记录,需要重写insert方法。 * 当数据插入成功后,调用ContentResolver的notifyChange方法。它会通 * 知已注册的观察者由一条记录更新。 * */ @Override public Uri insert(@NonNull Uri uri,ContentValues values) { //---添加一本书--- long rowID = booksDB.insert(DATABASE_TABLE,"",values); //---如果添加成功的话--- if (rowID > 0) { Uri tempuri = ContentUris.withAppendedId(CONTENT_URI,rowID); getContext().getContentResolver().notifyChange(tempuri,null); return tempuri; } //---添加不成功--- throw new sqlException("Failed to insert row into " + uri); } /** * 重写onCreate方法,当content Provider启动的时候,打开数据库连接。 * */ @Override public boolean onCreate() { Context context = getContext(); DatabaseHelper dbHelper = new DatabaseHelper(context); booksDB = dbHelper.getWritableDatabase(); return booksDB != null; } /** * 重写query方法,使得用户可以查询图书。 * */ @Override public Cursor query(@NonNull Uri uri,String[] projection,String selection,String[] selectionArgs,String sortOrder) { sqliteQueryBuilder sqlBuilder = new sqliteQueryBuilder(); sqlBuilder.setTables(DATABASE_TABLE); //---如果要获取制定的图书信息-- if (URI_MATCHER.match(uri) == BOOK_ID) { sqlBuilder.appendWhere(ID + " = " + uri.getPathSegments().get(1)); } if (sortOrder == null || Objects.equals(sortOrder,"")) { sortOrder = TITLE; } Cursor c = sqlBuilder.query( booksDB,selection,selectionArgs,sortOrder); //---注册一个观察者来监视Uri的变化--- c.setNotificationUri(getContext().getContentResolver(),uri); return c; } /** * 要更新一本书,需要重写update方法。 * 如同insert方法和delete方法,更新成功后你需要调用ContentResolver * 的notifyChange方法。它会通知已注册的观察者有一条记录被更新。 * */ @Override public int update(@NonNull Uri uri,ContentValues values,String[] selectionArgs) { int count; switch (URI_MATCHER.match(uri)) { case BOOKS: count = booksDB.update( DATABASE_TABLE,values,selectionArgs); break; case BOOK_ID: count = booksDB.update( DATABASE_TABLE,ID + " = " + uri.getPathSegments().get(1) + (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : ""),selectionArgs); break; default: throw new IllegalArgumentException("UnkNown URI " + uri); } getContext().getContentResolver().notifyChange(uri,null); return count; } /** * 本示例中Content Provider使用sqlite数据库存储图书数据。 * */ private static class DatabaseHelper extends sqliteOpenHelper { DatabaseHelper(Context context) { super(context,DATABASE_NAME,DATABASE_VERSION); } @Override public void onCreate(sqliteDatabase db) { db.execsql(DATABASE_CREATE); } @Override public void onUpgrade(sqliteDatabase db,int oldVersion,int newVersion) { Log.w("Provider database","Upgrading database from version " + oldVersion + " to " + newVersion + ",which will destroy all old data"); db.execsql("DROP TABLE IF EXISTS titles"); onCreate(db); } } }
使用自定义的Content Provider
Main3Activity
public class Main3Activity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main3); } public void onClickAddTitle(View view) { //---添加一本书--- ContentValues values = new ContentValues(); values.put(BooksProvider.TITLE,((EditText) findViewById(R.id.txtTitle)).getText().toString()); values.put(BooksProvider.ISBN,((EditText) findViewById(R.id.txtISBN)).getText().toString()); Uri uri = getContentResolver().insert(BooksProvider.CONTENT_URI,values); assert uri != null; Toast.makeText(getBaseContext(),uri.toString(),Toast.LENGTH_LONG).show(); } public void onClickRetrieveTitles(View view) { //---检索书名--- Uri allTitles = Uri.parse("content://link_work.myapplication.provider.Books/books"); CursorLoader cursorLoader = new CursorLoader( this,allTitles,// 默认以title列从大到小排序 "title desc" ); Cursor c = cursorLoader.loadInBackground(); if (c.movetoFirst()) { do { String string = c.getString(c.getColumnIndex(BooksProvider.ID)) + "," + c.getString(c.getColumnIndex(BooksProvider.TITLE)) + "," + c.getString(c.getColumnIndex(BooksProvider.ISBN)); Toast.makeText(this,string,Toast.LENGTH_SHORT).show(); } while (c.movetoNext()); } } }
activity_main3.xml
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".Main3Activity"> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="16dp" android:text="ISBN" app:layout_constraintLeft_toLeftOf="@+id/activity_main" app:layout_constraintRight_toRightOf="@+id/activity_main" app:layout_constraintTop_toTopOf="@+id/activity_main" tools:layout_constraintLeft_creator="1" tools:layout_constraintRight_creator="1" /> <EditText android:id="@+id/txtISBN" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="8dp" android:layout_marginTop="8dp" android:ems="10" android:inputType="text" app:layout_constraintBottom_toTopOf="@+id/textView2" app:layout_constraintHorizontal_bias="0.46" app:layout_constraintLeft_toLeftOf="@+id/activity_main" app:layout_constraintRight_toRightOf="@+id/activity_main" app:layout_constraintTop_toBottomOf="@+id/textView" app:layout_constraintVertical_bias="0.100000024" tools:layout_constraintLeft_creator="1" tools:layout_constraintRight_creator="1" /> <TextView android:id="@+id/textView2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="142dp" android:text="Title" app:layout_constraintLeft_toLeftOf="@+id/activity_main" app:layout_constraintRight_toRightOf="@+id/activity_main" app:layout_constraintTop_toTopOf="@+id/activity_main" tools:layout_constraintLeft_creator="1" tools:layout_constraintRight_creator="1" tools:layout_constraintTop_creator="1" /> <EditText android:id="@+id/txtTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:ems="10" android:inputType="text" app:layout_constraintLeft_toLeftOf="@+id/activity_main" app:layout_constraintRight_toRightOf="@+id/activity_main" app:layout_constraintTop_toBottomOf="@+id/textView2" tools:layout_constraintLeft_creator="1" tools:layout_constraintRight_creator="1" /> <Button android:id="@+id/btnAdd" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="112dp" android:onClick="onClickAddTitle" android:text="添加标题" app:layout_constraintLeft_toLeftOf="@+id/activity_main" app:layout_constraintRight_toRightOf="@+id/activity_main" app:layout_constraintTop_toBottomOf="@+id/txtTitle" tools:layout_constraintLeft_creator="1" tools:layout_constraintRight_creator="1" /> <Button android:id="@+id/btnRetrieve" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="32dp" android:onClick="onClickRetrieveTitles" android:text="检索标题" app:layout_constraintLeft_toLeftOf="@+id/activity_main" app:layout_constraintRight_toRightOf="@+id/activity_main" app:layout_constraintTop_toBottomOf="@+id/btnAdd" tools:layout_constraintLeft_creator="1" tools:layout_constraintRight_creator="1" /> </android.support.constraint.ConstraintLayout>
附录
- 《Beginning Android Programming with Android Studio,4th Edition》
hadoop的安装,主从设置及结合php的应用
- <?
- //php连接hive thrift依赖包路径
- $GLOBALS[''THRIFT_ROOT''] = ''/home/hadoop/Thrift/'';
- //load the required files for connecting to Hive
- require_once $GLOBALS[''THRIFT_ROOT''] . ''packages/hive_service/ThriftHive.php'';
- require_once $GLOBALS[''THRIFT_ROOT''] . ''transport/TSocket.php'';
- require_once $GLOBALS[''THRIFT_ROOT''] . ''protocol/TBinaryProtocol.php'';
- //Set up the transport/protocol/client
- $transport = new TSocket(''192.168.1.247'', 10000);
- $protocol = new TBinaryProtocol($transport);
- $client = new ThriftHiveClient($protocol);
- $transport->open();
- //run queries, metadata calls etc
- $client->execute(''show tables'');
- var_dump($client->fetchAll());
- $transport->close();
- ?>
今天关于SQLite结合PHP的开发和sql php的讲解已经结束,谢谢您的阅读,如果想了解更多关于BOA+PHP+SQLite之SQLite、Codeigniter(CI)结合PHPExcel类完成数据导入、Content Provider与SQLite结合使用、hadoop的安装,主从设置及结合php的应用的相关知识,请在本站搜索。
本文标签: