• 关于

    html txt读取

    的搜索结果

回答

提供个想法,通过 ajax 读取 xml 文件内容(其实更建议用 txt,一行一个文件),读取每个 html 内容。然后 一个一个追加到文件末尾。
杨冬芳 2019-12-02 02:46:31 0 浏览量 回答数 0

问题

php读取文件内容的三种方式

分享下php读取文件内容的三种方法。 php读取文件内容: //**************第一种读取方式*****************************   header("content-type:text/ht...
你的风向标 2019-12-01 21:40:00 5414 浏览量 回答数 3

问题

在Django项目中获取一个javascript本地文件

我的文件夹里有一个. txt文件。我正在使用JS中的fetch()函数来读取该文件。我需要在Django项目中这样做。但是当我在fetch中调用文件时,Django错误发生了。 (索引):456 GEThttp://127 ...
┭┮﹏┭┮ 2020-03-31 11:07:36 38 浏览量 回答数 1

回答

<script type="text/javascript"> $(function(){ $.post('./flowchartjson.txt',function(data){ render_flow_chart($("<div/>").html(data).text()); },'text').error(function() {alert('读取txt出错!')}); }); </script>
a123456678 2019-12-02 03:05:12 0 浏览量 回答数 0

回答

StreamReader读取txt文件,然后看你是winform还是webform,winform就在后台反序列化,然后显示;webform就将json字符串返回前端,前端组织显示http://www.cnblogs.com/txw1958/archive/2012/08/01/csharp-json.html
杨冬芳 2019-12-02 03:03:29 0 浏览量 回答数 0

问题

收藏 写了一个目录扫描脚本,大家看看吧?:报错

目的: 1、读取出url.txt文件里的网站地址 2、读取出dict.txt 文件里的目录,如(manager/login.html) 3、最后判断某网站是否存在dict.txt...
kun坤 2020-06-06 16:54:23 0 浏览量 回答数 1

问题

php 如何实现批量监测网页中的某一内容是否发生变化?:报错

如题:php 如何实现批量监控页面中的某一内容A是否发生改变? 考虑的问题点: 1.批量读取txt内容,(已经解决) 2.正则匹配内容A&...
kun坤 2020-06-07 16:33:57 0 浏览量 回答数 1

回答

Re:将文件复制到FTP文件夹时发生错误,检查是否有权限将文件放到该服务 .. 你在什么场景下提示的错误呢? 虚拟主机还是云服务器还是免费虚拟主机。 如果是虚拟主机的话通过ftp进入目录先把 说明文档看一下。 ------------------------- 回 4楼(acease) 的帖子 一般情况下你登陆ftp会有一个 请先都我.txt 内容如下: 欢迎使用万网主机服务 本路径下各文件夹功能和权限说明:      / :             您的FTP的根目录,为避免您错误删除该路径下的内容,所以禁止写入,只可读取 htdocs/:            您的网站的根目录,请将您的网站文件(php, htm, html, css, js等)上传至此文件夹 htdocs/logreport/:   访问统计报告存放目录,不占用空间,只可读取。   myfolder/:         此文件夹中的内容不会被web用户看到,您可以临时存放一些不愿公开的内容,比如站点备份、数据库备份等   ftplogs/:          您的ftp访问日志存放位置,只读   wwwlogs/:          您的www访问日志存放位置,只读   backup/:           系统自动为您生成的数据库备份的存放位置,只读 ------------------------- Re:将文件复制到FTP文件夹时发生错误,检查是否有权限将文件放到该服务 .. 你的网站程序需要放到htdocs 文件夹下。
51干警网 2019-12-02 00:09:22 0 浏览量 回答数 0

问题

我从txt文本中读取中文文本然后存到mysql数据库中,中文变成了乱码!

public static void JD() throws IOException{ File input =new File("/Users/huboqin/Downloads/网页1/京东/jd450.html"); ...
爵霸 2019-12-01 19:54:27 1013 浏览量 回答数 1

回答

第一步:安装multer模块 1 cnpm install multer --save 第二步:引入multer模块,构造multer对象: multer(opt) opt是个key-value对象,包含属性dest/storage,fileFilter,limits.分表表示文件的存储位置/方式,文件过滤,文件大小限制.如下: 复制代码 1 var moment = require("moment"); 2 var express = require("express"); 3 var multer = require('multer'); 4 var storage = multer.diskStorage({ 5 //文件存储路径 6 destination: function (req, file, cb) { 7 cb(null, path.join(__dirname, "/../uploads/temps")); 8 }, 9 //修改上传文件的名字 10 //file 是个文件对象 ,fieldname对应在客户端的name属性 11 //存储的文件需要自己加上文件的后缀,multer并不会自动添加 12 //这里直接忽略文件的后缀. 13 filename: function (req, file, cb) { 14 var date = new Date(); 15 cb(null, moment().format("YYYYMMDDhhmmss") + file.originalname); 16 } 17 }); 18 let objMulter = multer({storage : storage }); 复制代码 如果初始化multer时候没有指定dest或者storage,上传的文件将保存在内存中,永远不会写入到磁盘中,在storage中如果没有指定destination值,那么上传的文件将存储在系统默认的临时文件夹. 复制代码 1 multer关联的文件信息: 2 3 filedname : 在form表单中指定的name属性值 4 orginalname : 原始文件名 5 encoding : 文件编码方式 6 mimetype : 多媒体类型 7 size : 文件大小,单位b 8 destination : 文件上传后存储在服务端的路径 9 filename : 文件在服务端的命名 10 path : 文件在服务端的完整路径 11 buffer : 文件二进制数据 12 13 ps:其中destination,filename和path只有在指定storage属性时候有效.而buffer只有文件在内存中存储时候有效. 复制代码 multer同时提供了single/array/fields/any方法用于对接受文件数的控制. single(fieldname) 接收单个文件,通过req.file访问该文件 array(fieldnaem,[maxcount]) 接收多个文件,通过req.files数组方法文件.maxcount指定接收文件最大数. fields(fields) 接受指定fieldname的文件,fieldname由客户端决定,通过req.files数组方法 any 接收所有文件上传,通过req.files访问文件 2.2,fs模块 第一步:安装fs模块,也可直接引用,node默认集成 1 cnpm install fs --save//项目目录安装 2 var fs = require("fs");//直接引入文件系统模块 第二步:介绍fs模块的方法 1 var fs = require('fs'); // 载入fs模块 1,删除指定文件:fs.unlink(path,callback) path参数为该文件的绝对物理路径,callback回调参数当中只有一个错误信息参数err,一般在该文件不存在或者删除文件失败时触发调用。 复制代码 1 fs.unlink('/tmp/234.txt', function(err) { 2 if (err) { 3 throw err; 4 } 5 console.log('成功删除了 /tmp/234.txt'); 6 }); 复制代码 2,读取文件:fs.readFile(filename,[option],callback) 参数说明: filename String 文件名 option Object encoding String |null default=null flag String default='r' callback Function path参数为该文件的绝对物理路径,其中options参数可选,可以传入编码格式,如读取文本文件时,可传入'utf8',若不指定编码格式,则默认输出读取的文件内容为Buffer形式,故一般都会传入该参数。callback回调参数当中有两个参数err和data,其中err为错误信息参数,一般在在文件不存在或者读取文件失败时触发调用,data为文件内容。 复制代码 1 fs.readFile('./tmp/test.txt','utf-8'function(err, data) { 2 // 读取文件失败/错误 3 if (err) { 4 throw err; 5 } 6 // 读取文件成功 7 console.log(data); 8 }); 复制代码 3,写入文件:fs.writeFile(filename,data,[options],callback),追加写入:fs.appendFile(filename,data[,options],callback) filename参数为该文件的绝对物理路径,data为需要写入该文件当中的数据内容,其中options参数可选,可以传入编码格式,若不传则默认为utf8。callback回调参数当中只有一个错误信息参数err,一般在写入失败时触发调用。 复制代码 1 // 写入文件内容(如果文件不存在会创建一个文件) 2 // 传递了追加参数 { 'flag': 'a' } 3 fs.writeFile('./test2.txt', 'test test', { 'flag': 'a' }, function(err) { 4 if (err) { 5 throw err; 6 } 7 8 console.log('Saved.'); 9 10 // 写入成功后读取测试 11 fs.readFile('./test2.txt', 'utf-8', function(err, data) { 12 if (err) { 13 throw err; 14 } 15 console.log(data); 16 }); 17 }); 复制代码 flag传值,r代表读取文件,w代表写文件,a代表追加。 复制代码 1 // 追加写入 2 fs.appendFile("2.txt","我是追加的字符",function (err) { 3 if(err){ 4 return console.log(err); 5 }else { 6 console.log("追加成功"); 7 } 8 }) 复制代码 4,检测文件是否存在:fs.exists(path,callback) path参数传入该文件的绝对物理路径,该callback回调函数有个参数exists。exists为一个文件状态对象,是否存在。 复制代码 1 var dest_Dir = path.join(__dirname.replace("routes", ""), "uploads", destDir); 2 fs.exists(dest_Dir, function (exists) { 3 if (exists) { 4 //存在 5 } 6 else { 7 8 } 9 }); 复制代码 5,移动或重命名指定文件:fs.rename(oldPath,newPath,callback) oldPath参数为该文件原来的路径,newPath参数为该文件移动或重命名之后的路径,这两个参数都必须能传入文件完整的绝对物理路径。callback回调参数当中只有一个错误信息参数,一般在oldPath当中指定的文件不存在或者该操作失败时触发调用。 复制代码 1 fs.rename(sourceFile, destPath, function (err) { 2 res.status(200).json({ 3 httpCode: 200, 4 message: '上传成功', 5 data: { 6 "fileurl": fileurl 7 }, 8 }); 9 }); 复制代码 6,创建一个目录文件夹:fs.mkdir(path[,model],callback) path为该目录的绝对物理路径,callback回调函数当中也只有一个错误信息参数,一般在目录创建失败时触发调用。 复制代码 1 fs.mkdir(dest_Dir, 0777, function (err) { 2 if (err) { 3 res.status(500).json({ 4 5 } else { 6 //创建目录成功,上传文件 7 fs.rename(sourceFile, destPath, function (err) { 8 res.status(200).json({ 9 httpCode: 200, 10 message: '上传成功', 11 data: { 12 "fileurl": fileurl 13 }, 14 }); 15 }); 16 } 17 }) 复制代码 7,读取目录文件夹:fs.readdir(path,callback) path为该目录的绝对物理路径,callback回调函数当中有两个参数err和files,err为错误信息参数,一般在该目录不存在或读取失败时触发调用,files为一个数组对象,包含该目录下的所有文件夹与文件的名字。(仅为文件夹的名字和文件名,不是路径形式)。 复制代码 1 fs.readdir('./newdir', function(err, files) { 2 if (err) { 3 throw err; 4 } 5 // files是一个数组 6 // 每个元素是此目录下的文件或文件夹的名称 7 console.log(files); 8 }); 复制代码 8,删除一个空文件夹:fs.rmdir(path,callback) path为该目录的绝对物理路径,callback回调函数当中也只有一个错误信息参数,一般在该目录不存在或者删除操作失败时触发调用。 复制代码 1 fs.rmdir('/tmp', function(err) { 2 if (err) { 3 throw err; 4 } 5 console.log('成功删除了 空文件夹 tmp'); 6 }); 复制代码 以上的实例均是异步操作,如果需同步操作在函数后面加Sync既可 1 //同步 所有同步的函数都是函数后面加Sync; 2 var res = fs.writeFileSync("1.txt","我是写入内容"); 2.3,文件上传 1,单文件上传 复制代码 1 router.post('/upload', upload.single('file'), function (req, res, next) { 2 var fileName = req.file.filename; 3 var destDir = req.body.dir == undefined ? "default" : req.body.dir; 4 var sourceFile = req.file.path; 5 var destPath = path.join(__dirname.replace("routes", ""), "uploads", destDir, fileName); 6 var dest_Dir = path.join(__dirname.replace("routes", ""), "uploads", destDir); 7 var fileurl = uploadFileDomin + destPath.substr(destPath.indexOf("uploads")); 8 fileurl = fileurl.replace(/\/g, "/"); 9 fs.exists(dest_Dir, function (exists) { 10 if (exists) { 11 fs.rename(sourceFile, destPath, function (err) { 12 res.status(200).json({ 13 httpCode: 200, 14 message: '上传成功', 15 data: { 16 "fileurl": fileurl 17 }, 18 }); 19 }); 20 } 21 else { 22 fs.mkdir(dest_Dir, 0777, function (err) { 23 if (err) { 24 res.status(500).json({ 25 httpCode: 500, 26 message: err, 27 data: [], 28 }); 29 } else { 30 fs.rename(sourceFile, destPath, function (err) { 31 res.status(200).json({ 32 httpCode: 200, 33 message: '上传成功', 34 data: { 35 "fileurl": fileurl 36 }, 37 }); 38 }); 39 } 40 }) 41 } 42 }); 43 44 }); 复制代码 2,多文件上传 复制代码 1 router.post('/uploads', upload.array('file', 8), function (req, res, next) { 2 var paths = []; 3 for (var i = 0; i < req.files.length; i++) { 4 var path = req.files[i].path.replace(/\/g, "/"); 5 var fileurl = uploadFileDomin + path.substr(path.indexOf("uploads")).replace('\', '/'); 6 paths.push(fileurl); 7 } 8 res.status(200).json({ 9 httpCode: 200, 10 message: '上传成功', 11 "fileurls": paths, 12 }); 13 }); 复制代码 最后抛出发送上传接口: 1 app.use("/api", require("./fileUploadApi.js")); 三,前端调用 3.1,单文件上传调用 1,简单html 复制代码 1 ajax upload 2 3 file 4 5 6 复制代码 2,js调用 复制代码 1 $("#btn_upload").click(function () { 2 //创建一个FormDate 3 var formData = new FormData(); 4 //将文件信息追加到其中 5 formData.append('file', file.files[0]); 6 formData.append('dir', 'attachment'); 7 //formData.append('name', file.files[0].name); 8 $.ajax({ 9 url: "http://localhost:3000/api/" + 'upload', 10 type: 'POST', 11 data: formData, 12 cache: false, 13 contentType: false, 14 processData: false, 15 xhrFields: { 16 withCredentials: true 17 }, 18 crossDomain: true, 19 success: function (data) { 20 callBack(data); 21 }, 22 error: function (response) { 23 console.log("error is :" + response); 24 } 25 }); 复制代码 3,实现效果 3.2,多文件上传调用 1,简单html 复制代码 1 ajax multi files upload 2 3 file 4 5 6 7 8 复制代码 2,js调用 复制代码 1 var files1 = $("#files1")[0]; 2 var files2 = $("#files2")[0]; 3 var files3 = $("#files3")[0]; 4 $("#btn_uploads").click(function () { 5 //创建一个FormDate 6 var formData = new FormData(); 7 //将文件信息追加到其中 8 formData.append('file', files1.files[0]); 9 formData.append('file', files2.files[0]); 10 formData.append('file', files3.files[0]); 11 $.ajax({ 12 url: 'http://localhost:3000/api/' + 'uploads', 13 type: 'POST', 14 data: formData, 15 contentType: false, 16 processData: false, 17 async: false, 18 xhrFields: { 19 withCredentials: true 20 }, 21 crossDomain: true, 22 success: function (data) { 23 callBack(data.fileurls); 24 }, 25 error: function (response) { 26 console.log("error is :" + response); 27 } 28 }) 29 }) 复制代码 3,实现效果
游客2q7uranxketok 2021-02-21 00:53:13 0 浏览量 回答数 0

问题

javascript图表绘制问题:报错

下面是html文件代码: <html> <head> <title>JSChart</title> <script type="text/jav...
kun坤 2020-06-07 20:24:13 0 浏览量 回答数 1

回答

如果还用.htaccess。。。 还不如不用Nginx###### .htaccess 的优点在于支持 "不重启服务程序" 时, 修改即时生效. 如果 nginx 不支持这个特性的话, 与其说支持 .htaccess ,还不如说支持  "rewrite" 来得实际. ---- 我并没有去求证 nginx 支不支持这个特性.###### 拜托, 不要一下子发了这么多关于 nginx 实现 .htaccess 的帖子... .htaccess 是一个"实在没办法"的办法. 他的实现, 是因为每次接受请求时, 都去读取 .htaccess 文件, 重新解析配置, 如果这个请求是一个深层的目录, 那么, 服务程序会查找每一级目录下的 htaccess 文件, 子目录的 htaccess 还会覆盖上一层目录的 htaccess 规则. 这是一个相当卖力不讨好的事情. 他唯一的生存环境, 就是那么运行于"虚拟空间" 的网站. 还有,这类提供商大多数都采用apache 而非 nginx. 再说, 就算提供商采用nginx, 我想,也不太可能提供 nginx + .htaccess 这个功能吧.###### 红薯鸡动了... 但这种实现方式跟apache是完全两回事情吧....###### .htaccess 这东西好慢,一般写在里面,官方有兼容版 ######在网站目录下建议一个.htaccess的文件,里面是nginx的urlrewrite规则,再在nginx.conf里include进去,这就叫做nginx支持.htaccess了? 我打个比方吧,在php环境里建议一个aa.asp,然后配置服务器用php去解析aa.asp,我是不是可以说php支持asp了? http://www.hdj.me/disdain-wurenzaidi-guy###### @ZhiWei en######www.hdj.me 这个是兄弟你的博客吧?###### 无语了,还自以为是的 说 支持.htaccess, 它只是一个文件名。。 nginx从早期版本开始,就支持rewrite, rewrite和apache的rewrite有区别 将文件名换成其他文件,一样使用。比如 include html/guize.txt###### 呵呵! 待会测试下 谢谢红薯大哥。######不评论。标记一下。###### 这样修改但.htaccess规则和APACHE不一样 而且要重启nginx 或者reload才生效 而APACHE是修改.htaccess规则就生效了
kun坤 2020-06-15 11:10:24 0 浏览量 回答数 0

回答

如果还用.htaccess。。。 还不如不用Nginx######.htaccess 的优点在于支持 "不重启服务程序" 时, 修改即时生效. 如果 nginx 不支持这个特性的话, 与其说支持 .htaccess ,还不如说支持  "rewrite" 来得实际. 我并没有去求证 nginx 支不支持这个特性.######拜托, 不要一下子发了这么多关于 nginx 实现 .htaccess 的帖子... .htaccess 是一个"实在没办法"的办法. 他的实现, 是因为每次接受请求时, 都去读取 .htaccess 文件, 重新解析配置, 如果这个请求是一个深层的目录, 那么, 服务程序会查找每一级目录下的 htaccess 文件, 子目录的 htaccess 还会覆盖上一层目录的 htaccess 规则. 这是一个相当卖力不讨好的事情. 他唯一的生存环境, 就是那么运行于"虚拟空间" 的网站. 还有,这类提供商大多数都采用apache 而非 nginx. 再说, 就算提供商采用nginx, 我想,也不太可能提供 nginx + .htaccess 这个功能吧.######红薯鸡动了... 但这种实现方式跟apache是完全两回事情吧....###### .htaccess 这东西好慢,一般写在里面,官方有兼容版 </td> ######在网站目录下建议一个.htaccess的文件,里面是nginx的urlrewrite规则,再在nginx.conf里include进去,这就叫做nginx支持.htaccess了? 我打个比方吧,在php环境里建议一个aa.asp,然后配置服务器用php去解析aa.asp,我是不是可以说php支持asp了? http://www.hdj.me/disdain-wurenzaidi-guy######@ZhiWei en######www.hdj.me 这个是兄弟你的博客吧?######无语了,还自以为是的 说 支持.htaccess, 它只是一个文件名。。 nginx从早期版本开始,就支持rewrite, rewrite和apache的rewrite有区别 将文件名换成其他文件,一样使用。比如 include html/guize.txt######呵呵! 待会测试下 谢谢红薯大哥。######不评论。标记一下。###### 这样修改但.htaccess规则和APACHE不一样 而且要重启nginx 或者reload才生效 而APACHE是修改.htaccess规则就生效了
kun坤 2020-06-01 09:46:44 0 浏览量 回答数 0

回答

" 如果还用.htaccess。。。 还不如不用Nginx###### .htaccess 的优点在于支持 "不重启服务程序" 时, 修改即时生效. 如果 nginx 不支持这个特性的话, 与其说支持 .htaccess ,还不如说支持  "rewrite" 来得实际. ---- 我并没有去求证 nginx 支不支持这个特性.###### 拜托, 不要一下子发了这么多关于 nginx 实现 .htaccess 的帖子... .htaccess 是一个"实在没办法"的办法. 他的实现, 是因为每次接受请求时, 都去读取 .htaccess 文件, 重新解析配置, 如果这个请求是一个深层的目录, 那么, 服务程序会查找每一级目录下的 htaccess 文件, 子目录的 htaccess 还会覆盖上一层目录的 htaccess 规则. 这是一个相当卖力不讨好的事情. 他唯一的生存环境, 就是那么运行于"虚拟空间" 的网站. 还有,这类提供商大多数都采用apache 而非 nginx. 再说, 就算提供商采用nginx, 我想,也不太可能提供 nginx + .htaccess 这个功能吧.###### 红薯鸡动了... 但这种实现方式跟apache是完全两回事情吧....###### .htaccess 这东西好慢,一般写在里面,官方有兼容版 ######在网站目录下建议一个.htaccess的文件,里面是nginx的urlrewrite规则,再在nginx.conf里include进去,这就叫做nginx支持.htaccess了? 我打个比方吧,在php环境里建议一个aa.asp,然后配置服务器用php去解析aa.asp,我是不是可以说php支持asp了? http://www.hdj.me/disdain-wurenzaidi-guy###### @ZhiWei en######www.hdj.me 这个是兄弟你的博客吧?###### 无语了,还自以为是的 说 支持.htaccess, 它只是一个文件名。。 nginx从早期版本开始,就支持rewrite, rewrite和apache的rewrite有区别 将文件名换成其他文件,一样使用。比如 include html/guize.txt###### 呵呵! 待会测试下 谢谢红薯大哥。######不评论。标记一下。###### 这样修改但.htaccess规则和APACHE不一样 而且要重启nginx 或者reload才生效 而APACHE是修改.htaccess规则就生效了 "
montos 2020-06-02 12:46:13 0 浏览量 回答数 0

问题

使用JFinal 读取 MySql BLOB 字段数据时 出现异常:报错

后台代码: String id = this.getPara("id"); Tpl tpl = Tpl.dao.findById(id); Tpl_Txt tpl_Txt = T...
kun坤 2020-06-06 16:15:55 0 浏览量 回答数 1

问题

Linux系统常用命令大全

系统信息 arch 显示机器的处理器架构(1) uname -m 显示机器的处理器架构(2) uname -r 显示正在使用的内核版本 dmidecode -q 显示硬件系统部件 - (SMBIOS / DMI) hdparm -...
北京小顽童 2019-12-01 21:15:48 36201 浏览量 回答数 16

问题

windows2003环境下Iis6tomcat6配置

工作的原理与iis7+tomcat7 是一样的,当一个request服务器时首先过滤器会检查是否 是jsp 请求,如果是直接通过连接器将请求转给tomcat的worker,实现jsp程序由t...
小易1246 2019-12-01 21:33:24 9409 浏览量 回答数 0

回答

系统信息 arch 显示机器的处理器架构 uname -m 显示机器的处理器架构 uname -r 显示正在使用的内核版本 dmidecode -q 显示硬件系统部件 - (SMBIOS / DMI) hdparm -i /dev/hda 罗列一个磁盘的架构特性 hdparm -tT /dev/sda 在磁盘上执行测试性读取操作 cat /proc/cpuinfo 显示CPU info的信息 cat /proc/interrupts 显示中断 cat /proc/meminfo 校验内存使用 cat /proc/swaps 显示哪些swap被使用 cat /proc/version 显示内核的版本 cat /proc/net/dev 显示网络适配器及统计 cat /proc/mounts 显示已加载的文件系统 lspci -tv 罗列 PCI 设备 lsusb -tv 显示 USB 设备 date 显示系统日期 cal 2007 显示2007年的日历表 date 041217002007.00 设置日期和时间 - 月日时分年.秒 clock -w 将时间修改保存到 BIOS 关机 (系统的关机、重启以及登出 ) shutdown -h now 关闭系统 init 0 关闭系统 telinit 0 关闭系统 shutdown -h hours:minutes & 按预定时间关闭系统 shutdown -c 取消按预定时间关闭系统 shutdown -r now 重启 reboot 重启 logout 注销 文件和目录 cd /home 进入 '/ home' 目录' cd .. 返回上一级目录 cd ../.. 返回上两级目录 cd 进入个人的主目录 cd ~user1 进入个人的主目录 cd - 返回上次所在的目录 pwd 显示工作路径 ls 查看目录中的文件 ls -F 查看目录中的文件 ls -l 显示文件和目录的详细资料 ls -a 显示隐藏文件 ls [0-9] 显示包含数字的文件名和目录名 tree 显示文件和目录由根目录开始的树形结构 lstree 显示文件和目录由根目录开始的树形结构 mkdir dir1 创建一个叫做 'dir1' 的目录' mkdir dir1 dir2 同时创建两个目录 mkdir -p /tmp/dir1/dir2 创建一个目录树 rm -f file1 删除一个叫做 'file1' 的文件' rmdir dir1 删除一个叫做 'dir1' 的目录' rm -rf dir1 删除一个叫做 'dir1' 的目录并同时删除其内容 rm -rf dir1 dir2 同时删除两个目录及它们的内容 mv dir1 new_dir 重命名/移动 一个目录 cp file1 file2 复制一个文件 cp dir/* . 复制一个目录下的所有文件到当前工作目录 cp -a /tmp/dir1 . 复制一个目录到当前工作目录 cp -a dir1 dir2 复制一个目录 ln -s file1 lnk1 创建一个指向文件或目录的软链接 ln file1 lnk1 创建一个指向文件或目录的物理链接 touch -t 0712250000 file1 修改一个文件或目录的时间戳 - (YYMMDDhhmm) file file1 outputs the mime type of the file as text iconv -l 列出已知的编码 iconv -f fromEncoding -t toEncoding inputFile > outputFile creates a new from the given input file by assuming it is encoded in fromEncoding and converting it to toEncoding. find . -maxdepth 1 -name *.jpg -print -exec convert "{}" -resize 80x60 "thumbs/{}" ; batch resize files in the current directory and send them to a thumbnails directory (requires convert from Imagemagick) 文件搜索 find / -name file1 从 '/' 开始进入根文件系统搜索文件和目录 find / -user user1 搜索属于用户 'user1' 的文件和目录 find /home/user1 -name *.bin 在目录 '/ home/user1' 中搜索带有'.bin' 结尾的文件 find /usr/bin -type f -atime +100 搜索在过去100天内未被使用过的执行文件 find /usr/bin -type f -mtime -10 搜索在10天内被创建或者修改过的文件 find / -name *.rpm -exec chmod 755 '{}' ; 搜索以 '.rpm' 结尾的文件并定义其权限 find / -xdev -name *.rpm 搜索以 '.rpm' 结尾的文件,忽略光驱、捷盘等可移动设备 locate *.ps 寻找以 '.ps' 结尾的文件 - 先运行 'updatedb' 命令 whereis halt 显示一个二进制文件、源码或man的位置 which halt 显示一个二进制文件或可执行文件的完整路径 挂载一个文件系统 mount /dev/hda2 /mnt/hda2 挂载一个叫做hda2的盘 - 确定目录 '/ mnt/hda2' 已经存在 umount /dev/hda2 卸载一个叫做hda2的盘 - 先从挂载点 '/ mnt/hda2' 退出 fuser -km /mnt/hda2 当设备繁忙时强制卸载 umount -n /mnt/hda2 运行卸载操作而不写入 /etc/mtab 文件- 当文件为只读或当磁盘写满时非常有用 mount /dev/fd0 /mnt/floppy 挂载一个软盘 mount /dev/cdrom /mnt/cdrom 挂载一个cdrom或dvdrom mount /dev/hdc /mnt/cdrecorder 挂载一个cdrw或dvdrom mount /dev/hdb /mnt/cdrecorder 挂载一个cdrw或dvdrom mount -o loop file.iso /mnt/cdrom 挂载一个文件或ISO镜像文件 mount -t vfat /dev/hda5 /mnt/hda5 挂载一个Windows FAT32文件系统 mount /dev/sda1 /mnt/usbdisk 挂载一个usb 捷盘或闪存设备 mount -t smbfs -o username=user,password=pass //WinClient/share /mnt/share 挂载一个windows网络共享 磁盘空间 df -h 显示已经挂载的分区列表 ls -lSr |more 以尺寸大小排列文件和目录 du -sh dir1 估算目录 'dir1' 已经使用的磁盘空间' du -sk * | sort -rn 以容量大小为依据依次显示文件和目录的大小 rpm -q -a --qf '%10{SIZE}t%{NAME}n' | sort -k1,1n 以大小为依据依次显示已安装的rpm包所使用的空间 (fedora, redhat类系统) dpkg-query -W -f='${Installed-Size;10}t${Package}n' | sort -k1,1n 以大小为依据显示已安装的deb包所使用的空间 (ubuntu, debian类系统) 用户和群组 groupadd group_name 创建一个新用户组 groupdel group_name 删除一个用户组 groupmod -n new_group_name old_group_name 重命名一个用户组 useradd -c "Name Surname " -g admin -d /home/user1 -s /bin/bash user1 创建一个属于 "admin" 用户组的用户 useradd user1 创建一个新用户 userdel -r user1 删除一个用户 ( '-r' 排除主目录) usermod -c "User FTP" -g system -d /ftp/user1 -s /bin/nologin user1 修改用户属性 passwd 修改口令 passwd user1 修改一个用户的口令 (只允许root执行) chage -E 2005-12-31 user1 设置用户口令的失效期限 pwck 检查 '/etc/passwd' 的文件格式和语法修正以及存在的用户 grpck 检查 '/etc/passwd' 的文件格式和语法修正以及存在的群组 newgrp group_name 登陆进一个新的群组以改变新创建文件的预设群组 文件的权限 - 使用 "+" 设置权限,使用 "-" 用于取消 ls -lh 显示权限 ls /tmp | pr -T5 -W$COLUMNS 将终端划分成5栏显示 chmod ugo+rwx directory1 设置目录的所有人(u)、群组(g)以及其他人(o)以读(r )、写(w)和执行(x)的权限 chmod go-rwx directory1 删除群组(g)与其他人(o)对目录的读写执行权限 chown user1 file1 改变一个文件的所有人属性 chown -R user1 directory1 改变一个目录的所有人属性并同时改变改目录下所有文件的属性 chgrp group1 file1 改变文件的群组 chown user1:group1 file1 改变一个文件的所有人和群组属性 find / -perm -u+s 罗列一个系统中所有使用了SUID控制的文件 chmod u+s /bin/file1 设置一个二进制文件的 SUID 位 - 运行该文件的用户也被赋予和所有者同样的权限 chmod u-s /bin/file1 禁用一个二进制文件的 SUID位 chmod g+s /home/public 设置一个目录的SGID 位 - 类似SUID ,不过这是针对目录的 chmod g-s /home/public 禁用一个目录的 SGID 位 chmod o+t /home/public 设置一个文件的 STIKY 位 - 只允许合法所有人删除文件 chmod o-t /home/public 禁用一个目录的 STIKY 位 文件的特殊属性 - 使用 "+" 设置权限,使用 "-" 用于取消 chattr +a file1 只允许以追加方式读写文件 chattr +c file1 允许这个文件能被内核自动压缩/解压 chattr +d file1 在进行文件系统备份时,dump程序将忽略这个文件 chattr +i file1 设置成不可变的文件,不能被删除、修改、重命名或者链接 chattr +s file1 允许一个文件被安全地删除 chattr +S file1 一旦应用程序对这个文件执行了写操作,使系统立刻把修改的结果写到磁盘 chattr +u file1 若文件被删除,系统会允许你在以后恢复这个被删除的文件 lsattr 显示特殊的属性 打包和压缩文件 bunzip2 file1.bz2 解压一个叫做 'file1.bz2'的文件 bzip2 file1 压缩一个叫做 'file1' 的文件 gunzip file1.gz 解压一个叫做 'file1.gz'的文件 gzip file1 压缩一个叫做 'file1'的文件 gzip -9 file1 最大程度压缩 rar a file1.rar test_file 创建一个叫做 'file1.rar' 的包 rar a file1.rar file1 file2 dir1 同时压缩 'file1', 'file2' 以及目录 'dir1' unrar x file1.rar 解压rar包 tar -cvf archive.tar file1 创建一个非压缩的 tarball tar -cvf archive.tar file1 file2 dir1 创建一个包含了 'file1', 'file2' 以及 'dir1'的档案文件 tar -tf archive.tar 显示一个包中的内容 tar -xvf archive.tar 释放一个包 tar -xvf archive.tar -C /tmp 将压缩包释放到 /tmp目录下 tar -cvfj archive.tar.bz2 dir1 创建一个bzip2格式的压缩包 tar -jxvf archive.tar.bz2 解压一个bzip2格式的压缩包 tar -cvfz archive.tar.gz dir1 创建一个gzip格式的压缩包 tar -zxvf archive.tar.gz 解压一个gzip格式的压缩包 zip file1.zip file1 创建一个zip格式的压缩包 zip -r file1.zip file1 file2 dir1 将几个文件和目录同时压缩成一个zip格式的压缩包 unzip file1.zip 解压一个zip格式压缩包 RPM 包 - (Fedora, Redhat及类似系统) rpm -ivh package.rpm 安装一个rpm包 rpm -ivh --nodeeps package.rpm 安装一个rpm包而忽略依赖关系警告 rpm -U package.rpm 更新一个rpm包但不改变其配置文件 rpm -F package.rpm 更新一个确定已经安装的rpm包 rpm -e package_name.rpm 删除一个rpm包 rpm -qa 显示系统中所有已经安装的rpm包 rpm -qa | grep httpd 显示所有名称中包含 "httpd" 字样的rpm包 rpm -qi package_name 获取一个已安装包的特殊信息 rpm -qg "System Environment/Daemons" 显示一个组件的rpm包 rpm -ql package_name 显示一个已经安装的rpm包提供的文件列表 rpm -qc package_name 显示一个已经安装的rpm包提供的配置文件列表 rpm -q package_name --whatrequires 显示与一个rpm包存在依赖关系的列表 rpm -q package_name --whatprovides 显示一个rpm包所占的体积 rpm -q package_name --scripts 显示在安装/删除期间所执行的脚本l rpm -q package_name --changelog 显示一个rpm包的修改历史 rpm -qf /etc/httpd/conf/httpd.conf 确认所给的文件由哪个rpm包所提供 rpm -qp package.rpm -l 显示由一个尚未安装的rpm包提供的文件列表 rpm --import /media/cdrom/RPM-GPG-KEY 导入公钥数字证书 rpm --checksig package.rpm 确认一个rpm包的完整性 rpm -qa gpg-pubkey 确认已安装的所有rpm包的完整性 rpm -V package_name 检查文件尺寸、 许可、类型、所有者、群组、MD5检查以及最后修改时间 rpm -Va 检查系统中所有已安装的rpm包- 小心使用 rpm -Vp package.rpm 确认一个rpm包还未安装 rpm2cpio package.rpm | cpio --extract --make-directories bin 从一个rpm包运行可执行文件 rpm -ivh /usr/src/redhat/RPMS/arch/package.rpm 从一个rpm源码安装一个构建好的包 rpmbuild --rebuild package_name.src.rpm 从一个rpm源码构建一个 rpm 包 YUM 软件包升级器 - (Fedora, RedHat及类似系统) yum install package_name 下载并安装一个rpm包 yum localinstall package_name.rpm 将安装一个rpm包,使用你自己的软件仓库为你解决所有依赖关系 yum update package_name.rpm 更新当前系统中所有安装的rpm包 yum update package_name 更新一个rpm包 yum remove package_name 删除一个rpm包 yum list 列出当前系统中安装的所有包 yum search package_name 在rpm仓库中搜寻软件包 yum clean packages 清理rpm缓存删除下载的包 yum clean headers 删除所有头文件 yum clean all 删除所有缓存的包和头文件 DEB 包 (Debian, Ubuntu 以及类似系统) dpkg -i package.deb 安装/更新一个 deb 包 dpkg -r package_name 从系统删除一个 deb 包 dpkg -l 显示系统中所有已经安装的 deb 包 dpkg -l | grep httpd 显示所有名称中包含 "httpd" 字样的deb包 dpkg -s package_name 获得已经安装在系统中一个特殊包的信息 dpkg -L package_name 显示系统中已经安装的一个deb包所提供的文件列表 dpkg --contents package.deb 显示尚未安装的一个包所提供的文件列表 dpkg -S /bin/ping 确认所给的文件由哪个deb包提供 APT 软件工具 (Debian, Ubuntu 以及类似系统) apt-get install package_name 安装/更新一个 deb 包 apt-cdrom install package_name 从光盘安装/更新一个 deb 包 apt-get update 升级列表中的软件包 apt-get upgrade 升级所有已安装的软件 apt-get remove package_name 从系统删除一个deb包 apt-get check 确认依赖的软件仓库正确 apt-get clean 从下载的软件包中清理缓存 apt-cache search searched-package 返回包含所要搜索字符串的软件包名称 查看文件内容 cat file1 从第一个字节开始正向查看文件的内容 tac file1 从最后一行开始反向查看一个文件的内容 more file1 查看一个长文件的内容 less file1 类似于 'more' 命令,但是它允许在文件中和正向操作一样的反向操作 head -2 file1 查看一个文件的前两行 tail -2 file1 查看一个文件的最后两行 tail -f /var/log/messages 实时查看被添加到一个文件中的内容 文本处理 cat file1 file2 ... | command <> file1_in.txt_or_file1_out.txt general syntax for text manipulation using PIPE, STDIN and STDOUT cat file1 | command( sed, grep, awk, grep, etc...) > result.txt 合并一个文件的详细说明文本,并将简介写入一个新文件中 cat file1 | command( sed, grep, awk, grep, etc...) >> result.txt 合并一个文件的详细说明文本,并将简介写入一个已有的文件中 grep Aug /var/log/messages 在文件 '/var/log/messages'中查找关键词"Aug" grep ^Aug /var/log/messages 在文件 '/var/log/messages'中查找以"Aug"开始的词汇 grep [0-9] /var/log/messages 选择 '/var/log/messages' 文件中所有包含数字的行 grep Aug -R /var/log/* 在目录 '/var/log' 及随后的目录中搜索字符串"Aug" sed 's/stringa1/stringa2/g' example.txt 将example.txt文件中的 "string1" 替换成 "string2" sed '/^$/d' example.txt 从example.txt文件中删除所有空白行 sed '/ *#/d; /^$/d' example.txt 从example.txt文件中删除所有注释和空白行 echo 'esempio' | tr '[:lower:]' '[:upper:]' 合并上下单元格内容 sed -e '1d' result.txt 从文件example.txt 中排除第一行 sed -n '/stringa1/p' 查看只包含词汇 "string1"的行 sed -e 's/ $//' example.txt 删除每一行最后的空白字符 sed -e 's/stringa1//g' example.txt 从文档中只删除词汇 "string1" 并保留剩余全部 sed -n '1,5p;5q' example.txt 查看从第一行到第5行内容 sed -n '5p;5q' example.txt 查看第5行 sed -e 's/00/0/g' example.txt 用单个零替换多个零 cat -n file1 标示文件的行数 cat example.txt | awk 'NR%2==1' 删除example.txt文件中的所有偶数行 echo a b c | awk '{print $1}' 查看一行第一栏 echo a b c | awk '{print $1,$3}' 查看一行的第一和第三栏 paste file1 file2 合并两个文件或两栏的内容 paste -d '+' file1 file2 合并两个文件或两栏的内容,中间用"+"区分 sort file1 file2 排序两个文件的内容 sort file1 file2 | uniq 取出两个文件的并集(重复的行只保留一份) sort file1 file2 | uniq -u 删除交集,留下其他的行 sort file1 file2 | uniq -d 取出两个文件的交集(只留下同时存在于两个文件中的文件) comm -1 file1 file2 比较两个文件的内容只删除 'file1' 所包含的内容 comm -2 file1 file2 比较两个文件的内容只删除 'file2' 所包含的内容 comm -3 file1 file2 比较两个文件的内容只删除两个文件共有的部分 字符设置和文件格式转换 dos2unix filedos.txt fileunix.txt 将一个文本文件的格式从MSDOS转换成UNIX unix2dos fileunix.txt filedos.txt 将一个文本文件的格式从UNIX转换成MSDOS recode ..HTML < page.txt > page.html 将一个文本文件转换成html recode -l | more 显示所有允许的转换格式 文件系统分析 badblocks -v /dev/hda1 检查磁盘hda1上的坏磁块 fsck /dev/hda1 修复/检查hda1磁盘上linux文件系统的完整性 fsck.ext2 /dev/hda1 修复/检查hda1磁盘上ext2文件系统的完整性 e2fsck /dev/hda1 修复/检查hda1磁盘上ext2文件系统的完整性 e2fsck -j /dev/hda1 修复/检查hda1磁盘上ext3文件系统的完整性 fsck.ext3 /dev/hda1 修复/检查hda1磁盘上ext3文件系统的完整性 fsck.vfat /dev/hda1 修复/检查hda1磁盘上fat文件系统的完整性 fsck.msdos /dev/hda1 修复/检查hda1磁盘上dos文件系统的完整性 dosfsck /dev/hda1 修复/检查hda1磁盘上dos文件系统的完整性 初始化一个文件系统 mkfs /dev/hda1 在hda1分区创建一个文件系统 mke2fs /dev/hda1 在hda1分区创建一个linux ext2的文件系统 mke2fs -j /dev/hda1 在hda1分区创建一个linux ext3(日志型)的文件系统 mkfs -t vfat 32 -F /dev/hda1 创建一个 FAT32 文件系统 fdformat -n /dev/fd0 格式化一个软盘 mkswap /dev/hda3 创建一个swap文件系统 SWAP文件系统 mkswap /dev/hda3 创建一个swap文件系统 swapon /dev/hda3 启用一个新的swap文件系统 swapon /dev/hda2 /dev/hdb3 启用两个swap分区 备份 dump -0aj -f /tmp/home0.bak /home 制作一个 '/home' 目录的完整备份 dump -1aj -f /tmp/home0.bak /home 制作一个 '/home' 目录的交互式备份 restore -if /tmp/home0.bak 还原一个交互式备份 rsync -rogpav --delete /home /tmp 同步两边的目录 rsync -rogpav -e ssh --delete /home ip_address:/tmp 通过SSH通道rsync rsync -az -e ssh --delete ip_addr:/home/public /home/local 通过ssh和压缩将一个远程目录同步到本地目录 rsync -az -e ssh --delete /home/local ip_addr:/home/public 通过ssh和压缩将本地目录同步到远程目录 dd bs=1M if=/dev/hda | gzip | ssh user@ip_addr 'dd of=hda.gz' 通过ssh在远程主机上执行一次备份本地磁盘的操作 dd if=/dev/sda of=/tmp/file1 备份磁盘内容到一个文件 tar -Puf backup.tar /home/user 执行一次对 '/home/user' 目录的交互式备份操作 ( cd /tmp/local/ && tar c . ) | ssh -C user@ip_addr 'cd /home/share/ && tar x -p' 通过ssh在远程目录中复制一个目录内容 ( tar c /home ) | ssh -C user@ip_addr 'cd /home/backup-home && tar x -p' 通过ssh在远程目录中复制一个本地目录 tar cf - . | (cd /tmp/backup ; tar xf - ) 本地将一个目录复制到另一个地方,保留原有权限及链接 find /home/user1 -name '.txt' | xargs cp -av --target-directory=/home/backup/ --parents 从一个目录查找并复制所有以 '.txt' 结尾的文件到另一个目录 find /var/log -name '.log' | tar cv --files-from=- | bzip2 > log.tar.bz2 查找所有以 '.log' 结尾的文件并做成一个bzip包 dd if=/dev/hda of=/dev/fd0 bs=512 count=1 做一个将 MBR (Master Boot Record)内容复制到软盘的动作 dd if=/dev/fd0 of=/dev/hda bs=512 count=1 从已经保存到软盘的备份中恢复MBR内容 光盘 cdrecord -v gracetime=2 dev=/dev/cdrom -eject blank=fast -force 清空一个可复写的光盘内容 mkisofs /dev/cdrom > cd.iso 在磁盘上创建一个光盘的iso镜像文件 mkisofs /dev/cdrom | gzip > cd_iso.gz 在磁盘上创建一个压缩了的光盘iso镜像文件 mkisofs -J -allow-leading-dots -R -V "Label CD" -iso-level 4 -o ./cd.iso data_cd 创建一个目录的iso镜像文件 cdrecord -v dev=/dev/cdrom cd.iso 刻录一个ISO镜像文件 gzip -dc cd_iso.gz | cdrecord dev=/dev/cdrom - 刻录一个压缩了的ISO镜像文件 mount -o loop cd.iso /mnt/iso 挂载一个ISO镜像文件 cd-paranoia -B 从一个CD光盘转录音轨到 wav 文件中 cd-paranoia -- "-3" 从一个CD光盘转录音轨到 wav 文件中(参数-3) cdrecord --scanbus 扫描总线以识别scsi通道 dd if=/dev/hdc | md5sum 校验一个设备的md5sum编码,例如一张 CD 网络 - (以太网和WIFI无线) ifconfig eth0 显示一个以太网卡的配置 ifup eth0 启用一个 'eth0' 网络设备 ifdown eth0 禁用一个 'eth0' 网络设备 ifconfig eth0 192.168.1.1 netmask 255.255.255.0 控制IP地址 ifconfig eth0 promisc 设置 'eth0' 成混杂模式以嗅探数据包 (sniffing) dhclient eth0 以dhcp模式启用 'eth0' route -n show routing table route add -net 0/0 gw IP_Gateway configura default gateway route add -net 192.168.0.0 netmask 255.255.0.0 gw 192.168.1.1 configure static route to reach network '192.168.0.0/16' route del 0/0 gw IP_gateway remove static route echo "1" > /proc/sys/net/ipv4/ip_forward activate ip routing hostname show hostname of system host www.example.com lookup hostname to resolve name to ip address and viceversa nslookup www.example.com lookup hostname to resolve name to ip address and viceversa ip link show show link status of all interfaces mii-tool eth0 show link status of 'eth0' ethtool eth0 show statistics of network card 'eth0' netstat -tup show all active network connections and their PID netstat -tupl show all network services listening on the system and their PID tcpdump tcp port 80 show all HTTP traffic iwlist scan show wireless networks iwconfig eth1 show configuration of a wireless network card hostname show hostname host www.example.com lookup hostname to resolve name to ip address and viceversa nslookup www.example.com lookup hostname to resolve name to ip address and viceversa whois www.example.com lookup on Whois database JPS工具 jps(Java Virtual Machine Process Status Tool)是JDK 1.5提供的一个显示当前所有java进程pid的命令,简单实用,非常适合在linux/unix平台上简单察看当前java进程的一些简单情况。 我想很多人都是用过unix系统里的ps命令,这个命令主要是用来显示当前系统的进程情况,有哪些进程,及其 id。 jps 也是一样,它的作用是显示当前系统的java进程情况,及其id号。我们可以通过它来查看我们到底启动了几个java进程(因为每一个java程序都会独占一个java虚拟机实例),和他们的进程号(为下面几个程序做准备),并可通过opt来查看这些进程的详细启动参数。 使用方法:在当前命令行下打 jps(需要JAVA_HOME,没有的话,到改程序的目录下打) 。 jps存放在JAVA_HOME/bin/jps,使用时为了方便请将JAVA_HOME/bin/加入到Path. $> jps 23991 Jps 23789 BossMain 23651 Resin 比较常用的参数: -q 只显示pid,不显示class名称,jar文件名和传递给main 方法的参数 $> jps -q 28680 23789 23651 -m 输出传递给main 方法的参数,在嵌入式jvm上可能是null $> jps -m 28715 Jps -m 23789 BossMain 23651 Resin -socketwait 32768 -stdout /data/aoxj/resin/log/stdout.log -stderr /data/aoxj/resin/log/stderr.log -l 输出应用程序main class的完整package名 或者 应用程序的jar文件完整路径名 $> jps -l 28729 sun.tools.jps.Jps 23789 com.asiainfo.aimc.bossbi.BossMain 23651 com.caucho.server.resin.Resin -v 输出传递给JVM的参数 $> jps -v 23789 BossMain 28802 Jps -Denv.class.path=/data/aoxj/bossbi/twsecurity/java/trustwork140.jar:/data/aoxj/bossbi/twsecurity/java/:/data/aoxj/bossbi/twsecurity/java/twcmcc.jar:/data/aoxj/jdk15/lib/rt.jar:/data/aoxj/jd k15/lib/tools.jar -Dapplication.home=/data/aoxj/jdk15 -Xms8m 23651 Resin -Xss1m -Dresin.home=/data/aoxj/resin -Dserver.root=/data/aoxj/resin -Djava.util.logging.manager=com.caucho.log.LogManagerImpl - Djavax.management.builder.initial=com.caucho.jmx.MBeanServerBuilderImpl
问问小秘 2020-07-23 13:20:37 0 浏览量 回答数 0

回答

OSS是Hadoop/Spark批处理作业可选的数据存储之一。本文将演示在OSS中创建一个文件,并在Spark中进行访问。 OSS数据准备 创建bucket 上传文件 上传文件可以通过OSS SDK,也可以通过HDFS,我们直接以控制台为例: 记住这个bucket的地址:oss://liumi-hust/A-Game-of-Thrones.txtendpoint:oss-cn-hangzhou-internal.aliyuncs.com至此OSS数据准备部分就已经ready。 在spark应用中读取OSS的数据 1、开发应用 应用开发上跟传统的部署方式没有区别。 SparkConf conf = new SparkConf().setAppName(WordCount.class.getSimpleName()); JavaRDD lines = sc.textFile("oss://liumi-hust/A-Game-of-Thrones.txt", 250); ... wordsCountResult.saveAsTextFile("oss://liumi-hust/A-Game-of-Thrones-result"); sc.close(); 2、将前面的core-site.xml放入应用项目的resources目录 fs.oss.impl org.apache.hadoop.fs.aliyun.oss.AliyunOSSFileSystem fs.oss.endpoint oss-cn-hangzhou-internal.aliyuncs.com fs.oss.accessKeyId {临时AK_ID} fs.oss.accessKeySecret {临时AK_SECRET} fs.oss.buffer.dir /tmp/oss fs.oss.connection.secure.enabled false fs.oss.connection.maximum 2048 3、打包的jar文件需要包含所有依赖 mvn assembly:assembly 附应用的pom.xml: 1 2<project xmlns="http://maven.apache.org/POM/4.0.0" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 5 4.0.0 6 7 com.aliyun.liumi.spark 8 SparkExampleJava 9 1.0-SNAPSHOT 10 11 12 13 org.apache.spark 14 spark-core_2.12 15 2.4.3 16 17 18 19 com.aliyun.dfs 20 aliyun-sdk-dfs 21 1.0.3 22 23 24 25 26 27 28 29 org.apache.maven.plugins 30 maven-assembly-plugin 31 2.6 32 33 false 34 35 jar-with-dependencies 36 37 38 39 com.aliyun.liumi.spark.example.WordCount 40 41 42 43 44 45 make-assembly 46 package 47 48 assembly 49 50 51 52 53 54 55 4、编写Dockerfile OSS: spark base image FROM registry.cn-beijing.aliyuncs.com/eci_open/spark:2.4.4 RUN rm $SPARK_HOME/jars/kubernetes-client-*.jar ADD https://repo1.maven.org/maven2/io/fabric8/kubernetes-client/4.4.2/kubernetes-client-4.4.2.jar $SPARK_HOME/jars RUN mkdir -p /opt/spark/jars COPY SparkExampleJava-1.0-SNAPSHOT.jar /opt/spark/jars oss 依赖jar COPY aliyun-sdk-oss-3.4.1.jar /opt/spark/jars COPY hadoop-aliyun-2.7.3.2.6.1.0-129.jar /opt/spark/jars COPY jdom-1.1.jar /opt/spark/jars oss 依赖jar下载地址见:https://help.aliyun.com/document_detail/97854.html 5、构建应用镜像 docker build -t registry.cn-beijing.aliyuncs.com/liumi/spark:2.4.4-example -f Dockerfile . 6、推到阿里云ACR docker push registry.cn-beijing.aliyuncs.com/liumi/spark:2.4.4-example 至此,spark应用镜像都已经准备完毕。接下来就是在kubernetes集群中部署Spark应用了。
1934890530796658 2020-03-20 18:42:57 0 浏览量 回答数 0

回答

环境准备 OSS对外提供的RESTful风格的API接口遵循HTTP协议,因此任何语言和工具只要按照OSS API文档定义的规则发送合法的HTTP请求,就可以使用OSS服务。如果你不想自己做深入的开发,可以直接使用OSS官方提供的SDK(下载页面:http://oss.aliyun.com)。目前,有三种语言的SDK可供选择:Python、PHP和Java。本文将以Python SDK为例【注:其他语言的SDK可能在函数名称上与本文中的例子有些出入,具体请参考相应的SDK文档。】,为大家深入讲解OSS的使用技巧。 如果你的系统支持Python 2.7,那么Python的OSS开发环境部署非常简单:只要把SDK中的几个*.py文件放在开发目录下,并在代码中加入如下两行,以填入在阿里云主页 My lashes. Star pharmacy rx one deployed hair have than cialis pas cher a ! for cheap viagra australia and plastic come this hairs http://www.plastofine.com/poq/buy-cialis-online.php continued find to ES-S141 or favorite pedicure rates surprised Free Sample Pack of Viagra did coat it visit site fine instead basic and. Week online prescriptions Stickiness also fast generic cialis pricey. Lotion produce 4 corners pharmacy to natural grams pulled http://lytemaster.com/yare/buy-viagra.html there for wonderful $1 you. pill identifier with pictures 8oz a show for http://www.cypresshomecareinc.com/fet/generic-cialis.php recommend effectiveness Almay have blisters pull clear missed. 上注册时获得的“Access ID”和“Access Key”,就可以通过my_store这个对象来使用SDK中声明的各个函数了。 在云存储上读写文件 从你的代码中,把fopen( )、fclose( )这类的函数删掉吧!取而代之的是RESTful风格的HTTP请求:写文件是PUT,读文件是GET,获取文件属性是HEAD,删除文件是 DELETE。在搭建好的OSS Python开发环境下,直接用上步声明的my_store对象创建并写入一个新文件(OSS称之为object)的代码如下: 上例中,content_type可以根据需求,填入HTTP协议中规定的某一种文件类型。如JPG图片使用“image/jpeg”,MP3文件使用 “audio/mpeg”,具体定义请参考RFC 2616。选择正确的content-type,可以让其他互联网应用直接正确地使用OSS上的文件。 读取一个已存在文件的代码如下: 获取文件属性的代码如下: 删除一个文件的代码如下: 通过上面列举的这四个简单的函数,你就可以轻松地将建立在传统文件系统上的应用移植到OSS这个云存储平台上来了。 通过签名URL防盗链 由于OSS有着非常优秀的网络带宽质量,很多朋友希望基于OSS开发图片、音乐、视频等网站和应用。但如何有效地防盗链是个让人头疼的问题。这里介绍一个简单且安全的方法:通过签名URL防盗链。 首先,确认自己的bucket权限是private,即这个bucket的所有请求必须在签名认证通过后才被认为是合法的。然后根据操作类型、要访 问的bucket、要访问的object以及超时时间,动态地生成一个经过签名的URL。通过这个签名URL,你授权的用户就可以在该签名URL过期时间 前执行相应的操作。 签名的Python代码如下: 其中method可以是PUT、GET、HEAD、DELETE中的任意一种;最后一个参数“timeout”是超时的时间,单位是秒。一个通过上面Python方法,计算得到的签名URL为: 通过这种动态计算签名URL的方法,可以有效地保护放在OSS上的数据,防止被其他人盗链。 满足特定条件时才传输数据 IMS(If-Modified-Since)参数是HTTP协议中,经常被用到的一个参数。它的含义是:通过这个时间戳参数,服务器端可以判断客 户端的数据是否是最新的;如果不是最新的,则返回服务器端的数据;如果是最新的,则返回304告诉客户端其本地 Cache的页面是最新的,于是客户端就可以直接从本地加载数据了。这样在网络上传输的数据量就会大大减少,同时也减轻了服务器的负担。 包括IMS在内,OSS共支持四种条件传输参数。只有object的属性满足客户端给出的条件时,OSS才传输object的数据。这四个参数是: If-Modified-Since If-Unmodified-Since If-Match If-None-Match If-Unmodified-Since的含义和If-Modified-Since正好相反:如果内容没更新,则返回数据;否则返回HTTP状态 码304。If-Unmodified-Since和If-Modified-Since这两个参数可以一起使用,以指定一个时间窗口。例如: If-Match、If-None-Match这对参数与If-Unmodified-Since、If-Modified-Since参数的含义类似,只是参数不是时间戳,而是内容的MD5值。利用好这四个参数,可以节省大量的流量,也就是可以节省很多money。 实现文件夹操作 许多终端用户习惯了文件夹这个概念,而较难适应只有bucket和object的云存储逻辑。但我们可以基于OSS从逻辑上实现文件夹功能。首先, 我们可以按照惯例,认为所有以斜杠(“/”)【注:可以用任意字符作为文件夹的分隔符,但按照*nix系统的文件系统的命名习惯,我们常常使用斜杠(“ /”)】结尾的object都是一个文件夹。例如,用户认为:“folder”是一个文件;“folder/”是一个文件夹;而“folder /file.txt”是一个放在folder文件夹内名为file.txt的文件。在云存储OSS上,“folder/”、“folder”和 “folder/file.txt”其实都是object。 当用户需要查询一个文件夹下的文件时,我们就需要巧妙地通过list object(Get Bucket)接口的四个参数:prefix、marker、delimiter和max-keys来实现。 例如,我们在OSS上名为“mydata”的bucket内有如下几个文件: 如果认为这个bucket是一个传统文件系统的话,当用户进入该bucket,应该只看到一个名为“lingyun.doc”的文件和一个名为 “folder/”的文件夹。为了获得这样的效果,我们将list object请求的delimiter参数设为“/”即可,代码如下: OSS收到这个请求后,会返回一个XML格式的消息,中间记录了这个bucket内有一个key为“lingyun.doc”的文件,以及一个名为 “folder”的common prefix,分别对应于文件和文件夹。当继续想查看文件夹“folder”内的文件列表时,可以将prefix参数设为“folder/”,代码如下: 执行后,我们就可以知道文件夹“folder”内,有三个文件:“file1.txt”、“file2.txt”,“file3.txt”和一个子文件夹:“image/”。 list objects命令的另一个参数是max-keys,它定义了在一次请求内OSS返回文件和文件夹最大的数目,默认值是100,最大可以设成1000。但 如果一个文件夹内有超过1000个文件怎么办?这时,可以利用list objects的最后一个参数——marker。这个参数告诉OSS从指定的文件开始,按照字典序查其后面的文件。示例代码为: 这时,OSS只会返回一个查询结果:“folder/file2.txt”。利用好这四个参数,你会发现做个类似于Dropbox【注:Dropbox是一个提供同步本地文件的网络存储在线应用,其官方主页:https://www.dropbox.com/】的应用是如此简单。 实现object断点下载和并发下载 从互联网上下载数据时,支持断点下载是一项非常基本的功能。其原理很简单,就是记住上次接受数据的位置,然后要求服务器从上次断点的地方开始将余下 的部分传输过来。下载OSS上的object时,可以采用HTTP请求中通用的Range这一header,来完成这个功能。例如: 获取一个文件的头5个字节的请求代码如下: 获取一个文件中间3KB字节数据的请求代码如下: 知道了如何使用Range来随机读一个object后,实现并发下载就轻而易举了。只要将要下载的object分成若干份,然后开多个线程,每个线程下载其中的一块。在所有块都下载完成后,整个文件就下载完成了。 注意:按照HTTP协议,如果用户的请求中含有Range字段,则服务器返回的HTTP状态码为206(Partial Content客户发送了一个带有Range头的GET请求,服务器完成了它)。 实现大文件并发上传 由于OSS是一个互联网服务,用户终端很难长时间保证和OSS之间的TCP连接。所以在上传一个大文件时会经常发生请求链接被断开的情况。这时就可 以采用OSS的Multipart Upload模式。Multipart Upload模式的原理是将一个较大的文件,在客户端拆成多个适合上传的小片(Part),然后分别上传至OSS服务器端,最后在服务器端组合成一个大文 件。由于每个小片是独立上传的,它们之间没有任何的关联,所以利用这种模式就可以做到并发上传。虽然原理看起来很麻烦,但如果使用OSS提供的SDK的 话,只要一行命令就搞定了并发上传: 具体实现细节请参考OSS API开发文档和SDK内部的实现逻辑,有兴趣的同学可以按照自己特定的需求自己实现一下。 快速删除一个有大量object的bucket 有一天,也许你只是看着自己的一个bucket不爽,想删除它。但OSS服务出于保护数据的考虑会温柔地通知你:这个bucket里面还有数据,不 能删除它。打开这个bucket一看,成千上万的文件在那里等着你去删。一个一个删,肯定太stupid了。这里教你一个小方法:先获取object列 表,再使用批量删除接口。在Python的SDK中已经封装好了与之对应的接口: 这样,删除几万个文件,也就是几十个请求的事情,不但节省了请求次数,更节省了大量的宝贵时间。 为object添加自定义的header 很多情况下,我们希望对文件的META属性中放入一些自定义的信息数据。例如,一张照片的拍摄时间;一篇文章的作者;一首歌曲的专辑名;甚至是一个专利的专利号。这样,我们在查看文件的META属性时,就可以获取这些自定义的信息数据,而不必将整个文件下载下来。 在使用OSS时,可以通过在PutObject的时候把自定义的信息数据放在以x-oss-meta-为前缀的参数中。OSS将把这些参数视为用户自定义的meta数据。添加x-oss-meta-author的实现代码为: 在获取这个object时,将收到如下的HTTP返回值: 在OSS上调试自己的代码 大家在用OSS开发时,如果发送了非法或者不符合规则的HTTP请求,OSS会返回错误码和相应的信息来帮助开发者发现和定位问题。OSS对于所有 HTTP返回码不是2xx的请求,都会返回一个XML结构的消息体,里面详细记录了无法执行用户请求的原因。例如,如果你尝试访问一个你没有访问权限的 object,那么OSS会返回给你403 Forbidden的HTTP错误码,以及一个如下的XML格式的消息体:
游客2q7uranxketok 2021-02-03 10:09:23 0 浏览量 回答数 0

问题

如何实时爬取股股市行情?

如何实时爬取股股市行情? 一. 数据来源准备 想爬取收集目前A股所有股票的每日行情做分析,首先要找到很全的上市公司股票代码信息,然后通过市面上已有的免费的股票数据api接口获取,接着...
珍宝珠 2020-01-06 14:40:36 385 浏览量 回答数 2

问题

采集一个简单的页面,我配置的分页一直不对,只能采集第一页?报错

以下是我配置的XML文件: <?xml version="1.0" encoding="UTF-8"?> <task> <!--  t...
爱吃鱼的程序员 2020-06-09 13:20:39 0 浏览量 回答数 1

问题

Apache服务器中如何启用gzip压缩

一、gzip介绍       Gzip是一种流行的文件压缩算法,现在的应用十分广泛,尤其是在Linux平台。当应用Gzip压缩到一个纯文本文件时,效果是非常明显的,大约可以减少70...
kideny 2019-12-01 21:26:45 14569 浏览量 回答数 14

回答

Nginx是一个轻量级的,高性能的Web服务器以及反向代理和邮箱 (IMAP/POP3)代理服务器。它运行在UNIX,GNU /linux,BSD 各种版本,Mac OS X,Solaris和Windows。根据调查统计,6%的网站使用Nginx Web服务器。Nginx是少数能处理C10K问题的服务器之一。跟传统的服务器不同,Nginx不依赖线程来处理请求。相反,它使用了更多的可扩展的事 件驱动(异步)架构。Nginx为一些高流量的网站提供动力,比如WordPress,人人网,腾讯,网易等。这篇文章主要是介绍如何提高运行在 Linux或UNIX系统的Nginx Web服务器的安全性。 默认配置文件和Nginx端口 /usr/local/nginx/conf/ – Nginx配置文件目录,/usr/local/nginx/conf/nginx.conf是主配置文件 /usr/local/nginx/html/ – 默认网站文件位置 /usr/local/nginx/logs/ – 默认日志文件位置 Nginx HTTP默认端口 : TCP 80 Nginx HTTPS默认端口: TCP 443 你可以使用以下命令来测试Nginx配置文件准确性。 /usr/local/nginx/sbin/nginx -t 将会输出: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok configuration file /usr/local/nginx/conf/nginx.conf test is successful 执行以下命令来重新加载配置文件。 /usr/local/nginx/sbin/nginx -s reload 执行以下命令来停止服务器。 /usr/local/nginx/sbin/nginx -s stop 一、配置SELinux 注意:对于云服务器 ECS,参阅 ECS 使用须知 ,基于兼容性、稳定性考虑,请勿开启 SELinux。 安全增强型 Linux(SELinux)是一个Linux内核的功能,它提供支持访问控制的安全政策保护机制。它可以防御大部分攻击。下面我们来看如何启动基于centos/RHEL系统的SELinux。 安装SELinux rpm -qa | grep selinux libselinux-1.23.10-2 selinux-policy-targeted-1.23.16-6 如果没有返回任何结果,代表没有安装 SELinux,如果返回了类似上面的结果,则说明系统安装了 SELinux。 布什值锁定 运行命令getsebool -a来锁定系统。 getsebool -a | less getsebool -a | grep off getsebool -a | grep o 二、通过分区挂载允许最少特权 服务器上的网页/html/php文件单独分区。例如,新建一个分区/dev/sda5(第一逻辑分区),并且挂载在/nginx。确保 /nginx是以noexec, nodev and nosetuid的权限挂载。以下是我的/etc/fstab的挂载/nginx的信息: LABEL=/nginx /nginx ext3 defaults,nosuid,noexec,nodev 1 2 注意:你需要使用fdisk和mkfs.ext3命令创建一个新分区。 三、配置/etc/sysctl.conf强化Linux安全 你可以通过编辑/etc/sysctl.conf来控制和配置Linux内核、网络设置。 Avoid a smurf attack net.ipv4.icmp_echo_ignore_broadcasts = 1 Turn on protection for bad icmp error messages net.ipv4.icmp_ignore_bogus_error_responses = 1 Turn on syncookies for SYN flood attack protection net.ipv4.tcp_syncookies = 1 Turn on and log spoofed, source routed, and redirect packets net.ipv4.conf.all.log_martians = 1 net.ipv4.conf.default.log_martians = 1 No source routed packets here net.ipv4.conf.all.accept_source_route = 0 net.ipv4.conf.default.accept_source_route = 0 Turn on reverse path filtering net.ipv4.conf.all.rp_filter = 1 net.ipv4.conf.default.rp_filter = 1 Make sure no one can alter the routing tables net.ipv4.conf.all.accept_redirects = 0 net.ipv4.conf.default.accept_redirects = 0 net.ipv4.conf.all.secure_redirects = 0 net.ipv4.conf.default.secure_redirects = 0 Don’t act as a router net.ipv4.ip_forward = 0 net.ipv4.conf.all.send_redirects = 0 net.ipv4.conf.default.send_redirects = 0 Turn on execshild kernel.exec-shield = 1 kernel.randomize_va_space = 1 Tuen IPv6 net.ipv6.conf.default.router_solicitations = 0 net.ipv6.conf.default.accept_ra_rtr_pref = 0 net.ipv6.conf.default.accept_ra_pinfo = 0 net.ipv6.conf.default.accept_ra_defrtr = 0 net.ipv6.conf.default.autoconf = 0 net.ipv6.conf.default.dad_transmits = 0 net.ipv6.conf.default.max_addresses = 1 Optimization for port usefor LBs Increase system file descriptor limit fs.file-max = 65535 Allow for more PIDs (to reduce rollover problems); may break some programs 32768 kernel.pid_max = 65536 Increase system IP port limits net.ipv4.ip_local_port_range = 2000 65000 Increase TCP max buffer size setable using setsockopt() net.ipv4.tcp_rmem = 4096 87380 8388608 net.ipv4.tcp_wmem = 4096 87380 8388608 Increase Linux auto tuning TCP buffer limits min, default, and max number of bytes to use set max to at least 4MB, or higher if you use very high BDP paths Tcp Windows etc net.core.rmem_max = 8388608 net.core.wmem_max = 8388608 net.core.netdev_max_backlog = 5000 net.ipv4.tcp_window_scaling = 1 四、删除所有不需要的Nginx模块 你需要直接通过编译Nginx源代码使模块数量最少化。通过限制只允许web服务器访问模块把风险降到最低。你可以只配置安装nginx你所需要的模块。例如,禁用SSL和autoindex模块你可以执行以下命令: ./configure –without-http_autoindex_module –without-http_ssi_module make make install 通过以下命令来查看当编译nginx服务器时哪个模块能开户或关闭: ./configure –help | less 禁用你用不到的nginx模块。 (可选项)更改nginx版本名称。 编辑文件/http/ngx_http_header_filter_module.c: vi +48 src/http/ngx_http_header_filter_module.c 找到行: static char ngx_http_server_string[] = “Server: nginx” CRLF; static char ngx_http_server_full_string[] = “Server: ” NGINX_VER CRLF; 按照以下行修改: static char ngx_http_server_string[] = “Server: Ninja Web Server” CRLF; static char ngx_http_server_full_string[] = “Server: Ninja Web Server” CRLF; 保存并关闭文件。现在你可以编辑服务器了。增加以下代码到nginx.conf文件来关闭nginx版本号的显示。 server_tokens off 五、使用mod_security(只适合后端Apache服务器) mod_security为Apache提供一个应用程序级的防火墙。为后端Apache Web服务器安装mod_security,这会阻止很多注入式攻击。 六、安装SELinux策略以强化Nginx Web服务器 默认的SELinux不会保护Nginx Web服务器,但是你可以安装和编译保护软件。 1、安装编译SELinux所需环境支持 yum -y install selinux-policy-targeted selinux-policy-devel 2、下载SELinux策略以强化Nginx Web服务器。 cd /opt wget ‘http://downloads.sourceforge.net/project/selinuxnginx/se-ngix_1_0_10.tar.gz?use_mirror=nchc’ 3、解压文件 tar -zxvf se-ngix_1_0_10.tar.gz 4、编译文件 cd se-ngix_1_0_10/nginx make 将会输出如下: Compiling targeted nginx module /usr/bin/checkmodule: loading policy configuration from tmp/nginx.tmp /usr/bin/checkmodule: policy configuration loaded /usr/bin/checkmodule: writing binary representation (version 6) to tmp/nginx.mod Creating targeted nginx.pp policy package rm tmp/nginx.mod.fc tmp/nginx.mod 5、安装生成的nginx.pp SELinux模块: /usr/sbin/semodule -i nginx.pp 七、基于Iptables防火墙的限制 下面的防火墙脚本阻止任何除了允许: 来自HTTP(TCP端口80)的请求 来自ICMP ping的请求 ntp(端口123)的请求输出 smtp(TCP端口25)的请求输出 #!/bin/bash IPT=”/sbin/iptables” IPS Get server public ip SERVER_IP=$(ifconfig eth0 | grep ‘inet addr:’ | awk -F’inet addr:’ ‘{ print $2}’ | awk ‘{ print $1}’) LB1_IP=”204.54.1.1″ LB2_IP=”204.54.1.2″ Do some smart logic so that we can use damm script on LB2 too OTHER_LB=”" SERVER_IP=”" [[ "$SERVER_IP" == "$LB1_IP" ]] && OTHER_LB=”$LB2_IP” || OTHER_LB=”$LB1_IP” [[ "$OTHER_LB" == "$LB2_IP" ]] && OPP_LB=”$LB1_IP” || OPP_LB=”$LB2_IP” IPs PUB_SSH_ONLY=”122.xx.yy.zz/29″ FILES BLOCKED_IP_TDB=/root/.fw/blocked.ip.txt SPOOFIP=”127.0.0.0/8 192.168.0.0/16 172.16.0.0/12 10.0.0.0/8 169.254.0.0/16 0.0.0.0/8 240.0.0.0/4 255.255.255.255/32 168.254.0.0/16 224.0.0.0/4 240.0.0.0/5 248.0.0.0/5 192.0.2.0/24″ BADIPS=$( [[ -f ${BLOCKED_IP_TDB} ]] && egrep -v “^#|^$” ${BLOCKED_IP_TDB}) Interfaces PUB_IF=”eth0″ # public interface LO_IF=”lo” # loopback VPN_IF=”eth1″ # vpn / private net start firewall echo “Setting LB1 $(hostname) Firewall…” DROP and close everything $IPT -P INPUT DROP $IPT -P OUTPUT DROP $IPT -P FORWARD DROP Unlimited lo access $IPT -A INPUT -i ${LO_IF} -j ACCEPT $IPT -A OUTPUT -o ${LO_IF} -j ACCEPT Unlimited vpn / pnet access $IPT -A INPUT -i ${VPN_IF} -j ACCEPT $IPT -A OUTPUT -o ${VPN_IF} -j ACCEPT Drop sync $IPT -A INPUT -i ${PUB_IF} -p tcp ! –syn -m state –state NEW -j DROP Drop Fragments $IPT -A INPUT -i ${PUB_IF} -f -j DROP $IPT -A INPUT -i ${PUB_IF} -p tcp –tcp-flags ALL FIN,URG,PSH -j DROP $IPT -A INPUT -i ${PUB_IF} -p tcp –tcp-flags ALL ALL -j DROP Drop NULL packets $IPT -A INPUT -i ${PUB_IF} -p tcp –tcp-flags ALL NONE -m limit –limit 5/m –limit-burst 7 -j LOG –log-prefix ” NULL Packets “ $IPT -A INPUT -i ${PUB_IF} -p tcp –tcp-flags ALL NONE -j DROP $IPT -A INPUT -i ${PUB_IF} -p tcp –tcp-flags SYN,RST SYN,RST -j DROP Drop XMAS $IPT -A INPUT -i ${PUB_IF} -p tcp –tcp-flags SYN,FIN SYN,FIN -m limit –limit 5/m –limit-burst 7 -j LOG –log-prefix ” XMAS Packets “ $IPT -A INPUT -i ${PUB_IF} -p tcp –tcp-flags SYN,FIN SYN,FIN -j DROP Drop FIN packet scans $IPT -A INPUT -i ${PUB_IF} -p tcp –tcp-flags FIN,ACK FIN -m limit –limit 5/m –limit-burst 7 -j LOG –log-prefix ” Fin Packets Scan “ $IPT -A INPUT -i ${PUB_IF} -p tcp –tcp-flags FIN,ACK FIN -j DROP $IPT -A INPUT -i ${PUB_IF} -p tcp –tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP Log and get rid of broadcast / multicast and invalid $IPT -A INPUT -i ${PUB_IF} -m pkttype –pkt-type broadcast -j LOG –log-prefix ” Broadcast “ $IPT -A INPUT -i ${PUB_IF} -m pkttype –pkt-type broadcast -j DROP $IPT -A INPUT -i ${PUB_IF} -m pkttype –pkt-type multicast -j LOG –log-prefix ” Multicast “ $IPT -A INPUT -i ${PUB_IF} -m pkttype –pkt-type multicast -j DROP $IPT -A INPUT -i ${PUB_IF} -m state –state INVALID -j LOG –log-prefix ” Invalid “ $IPT -A INPUT -i ${PUB_IF} -m state –state INVALID -j DROP Log and block spoofed ips $IPT -N spooflist for ipblock in $SPOOFIP do $IPT -A spooflist -i ${PUB_IF} -s $ipblock -j LOG –log-prefix ” SPOOF List Block “ $IPT -A spooflist -i ${PUB_IF} -s $ipblock -j DROP done $IPT -I INPUT -j spooflist $IPT -I OUTPUT -j spooflist $IPT -I FORWARD -j spooflist Allow ssh only from selected public ips for ip in ${PUB_SSH_ONLY} do $IPT -A INPUT -i ${PUB_IF} -s ${ip} -p tcp -d ${SERVER_IP} –destination-port 22 -j ACCEPT $IPT -A OUTPUT -o ${PUB_IF} -d ${ip} -p tcp -s ${SERVER_IP} –sport 22 -j ACCEPT done allow incoming ICMP ping pong stuff $IPT -A INPUT -i ${PUB_IF} -p icmp –icmp-type 8 -s 0/0 -m state –state NEW,ESTABLISHED,RELATED -m limit –limit 30/sec -j ACCEPT $IPT -A OUTPUT -o ${PUB_IF} -p icmp –icmp-type 0 -d 0/0 -m state –state ESTABLISHED,RELATED -j ACCEPT allow incoming HTTP port 80 $IPT -A INPUT -i ${PUB_IF} -p tcp -s 0/0 –sport 1024:65535 –dport 80 -m state –state NEW,ESTABLISHED -j ACCEPT $IPT -A OUTPUT -o ${PUB_IF} -p tcp –sport 80 -d 0/0 –dport 1024:65535 -m state –state ESTABLISHED -j ACCEPT allow outgoing ntp $IPT -A OUTPUT -o ${PUB_IF} -p udp –dport 123 -m state –state NEW,ESTABLISHED -j ACCEPT $IPT -A INPUT -i ${PUB_IF} -p udp –sport 123 -m state –state ESTABLISHED -j ACCEPT allow outgoing smtp $IPT -A OUTPUT -o ${PUB_IF} -p tcp –dport 25 -m state –state NEW,ESTABLISHED -j ACCEPT $IPT -A INPUT -i ${PUB_IF} -p tcp –sport 25 -m state –state ESTABLISHED -j ACCEPT add your other rules here ####################### drop and log everything else $IPT -A INPUT -m limit –limit 5/m –limit-burst 7 -j LOG –log-prefix ” DEFAULT DROP “ $IPT -A INPUT -j DROP exit 0 八、控制缓冲区溢出攻击 编辑nginx.conf,为所有客户端设置缓冲区的大小限制。 vi /usr/local/nginx/conf/nginx.conf 编辑和设置所有客户端缓冲区的大小限制如下: Start: Size Limits & Buffer Overflows client_body_buffer_size 1K; client_header_buffer_size 1k; client_max_body_size 1k; large_client_header_buffers 2 1k; END: Size Limits & Buffer Overflows 解释: 1、client_body_buffer_size 1k-(默认8k或16k)这个指令可以指定连接请求实体的缓冲区大小。如果连接请求超过缓存区指定的值,那么这些请求实体的整体或部分将尝试写入一个临时文件。 2、client_header_buffer_size 1k-指令指定客户端请求头部的缓冲区大小。绝大多数情况下一个请求头不会大于1k,不过如果有来自于wap客户端的较大的cookie它可能会大于 1k,Nginx将分配给它一个更大的缓冲区,这个值可以在large_client_header_buffers里面设置。 3、client_max_body_size 1k-指令指定允许客户端连接的最大请求实体大小,它出现在请求头部的Content-Length字段。 如果请求大于指定的值,客户端将收到一个”Request Entity Too Large” (413)错误。记住,浏览器并不知道怎样显示这个错误。 4、large_client_header_buffers-指定客户端一些比较大的请求头使用的缓冲区数量和大小。请求字段不能大于一个缓冲区大小,如果客户端发送一个比较大的头,nginx将返回”Request URI too large” (414) 同样,请求的头部最长字段不能大于一个缓冲区,否则服务器将返回”Bad request” (400)。缓冲区只在需求时分开。默认一个缓冲区大小为操作系统中分页文件大小,通常是4k或8k,如果一个连接请求最终将状态转换为keep- alive,它所占用的缓冲区将被释放。 你还需要控制超时来提高服务器性能并与客户端断开连接。按照如下编辑: Start: Timeouts client_body_timeout 10; client_header_timeout 10; keepalive_timeout 5 5; send_timeout 10; End: Timeouts 1、client_body_timeout 10;-指令指定读取请求实体的超时时间。这里的超时是指一个请求实体没有进入读取步骤,如果连接超过这个时间而客户端没有任何响应,Nginx将返回一个”Request time out” (408)错误。 2、client_header_timeout 10;-指令指定读取客户端请求头标题的超时时间。这里的超时是指一个请求头没有进入读取步骤,如果连接超过这个时间而客户端没有任何响应,Nginx将返回一个”Request time out” (408)错误。 3、keepalive_timeout 5 5; – 参数的第一个值指定了客户端与服务器长连接的超时时间,超过这个时间,服务器将关闭连接。参数的第二个值(可选)指定了应答头中Keep-Alive: timeout=time的time值,这个值可以使一些浏览器知道什么时候关闭连接,以便服务器不用重复关闭,如果不指定这个参数,nginx不会在应 答头中发送Keep-Alive信息。(但这并不是指怎样将一个连接“Keep-Alive”)参数的这两个值可以不相同。 4、send_timeout 10; 指令指定了发送给客户端应答后的超时时间,Timeout是指没有进入完整established状态,只完成了两次握手,如果超过这个时间客户端没有任何响应,nginx将关闭连接。 九、控制并发连接 你可以使用NginxHttpLimitZone模块来限制指定的会话或者一个IP地址的特殊情况下的并发连接。编辑nginx.conf: Directive describes the zone, in which the session states are stored i.e. store in slimits. 1m can handle 32000 sessions with 32 bytes/session, set to 5m x 32000 session limit_zone slimits $binary_remote_addr 5m; Control maximum number of simultaneous connections for one session i.e. restricts the amount of connections from a single ip address limit_conn slimits 5; 上面表示限制每个远程IP地址的客户端同时打开连接不能超过5个。 十、只允许我们的域名的访问 如果机器人只是随机扫描服务器的所有域名,那拒绝这个请求。你必须允许配置的虚拟域或反向代理请求。你不必使用IP地址来拒绝。 Only requests to our Host are allowed i.e. nixcraft.in, images.nixcraft.in and www.nixcraft.in if ($host !~ ^(nixcraft.in|www.nixcraft.in|images.nixcraft.in)$ ) { return 444; } 十一、限制可用的请求方法 GET和POST是互联网上最常用的方法。 Web服务器的方法被定义在RFC 2616。如果Web服务器不要求启用所有可用的方法,它们应该被禁用。下面的指令将过滤只允许GET,HEAD和POST方法: Only allow these request methods if ($request_method !~ ^(GET|HEAD|POST)$ ) { return 444; } Do not accept DELETE, SEARCH and other methods 更多关于HTTP方法的介绍 GET方法是用来请求,如文件http://www.moqifei.com/index.php。 HEAD方法是一样的,除非该服务器的GET请求无法返回消息体。 POST方法可能涉及到很多东西,如储存或更新数据,或订购产品,或通过提交表单发送电子邮件。这通常是使用服务器端处理,如PHP,Perl和Python等脚本。如果你要上传的文件和在服务器处理数据,你必须使用这个方法。 十二、如何拒绝一些User-Agents? 你可以很容易地阻止User-Agents,如扫描器,机器人以及滥用你服务器的垃圾邮件发送者。 Block download agents if ($http_user_agent ~* LWP::Simple|BBBike|wget) { return 403; } 阻止Soso和有道的机器人: Block some robots if ($http_user_agent ~* Sosospider|YodaoBot) { return 403; } 十三、如何防止图片盗链 图片或HTML盗链的意思是有人直接用你网站的图片地址来显示在他的网站上。最终的结果,你需要支付额外的宽带费用。这通常是在论坛和博客。我强烈建议您封锁,并阻止盗链行为。 Stop deep linking or hot linking location /images/ { valid_referers none blocked www.example.com example.com; if ($invalid_referer) { return 403; } } 例如:重定向并显示指定图片 valid_referers blocked www.example.com example.com; if ($invalid_referer) { rewrite ^/images/uploads.*.(gif|jpg|jpeg|png)$ http://www.examples.com/banned.jpg last } 十四、目录限制 你可以对指定的目录设置访问权限。所有的网站目录应该一一的配置,只允许必须的目录访问权限。 通过IP地址限制访问 你可以通过IP地址来限制访问目录/admin/: location /docs/ { block one workstation deny 192.168.1.1; allow anyone in 192.168.1.0/24 allow 192.168.1.0/24; drop rest of the world deny all; } 通过密码保护目录 首先创建密码文件并增加“user”用户: mkdir /usr/local/nginx/conf/.htpasswd/ htpasswd -c /usr/local/nginx/conf/.htpasswd/passwd user 编辑nginx.conf,加入需要保护的目录: Password Protect /personal-images/ and /delta/ directories location ~ /(personal-images/.|delta/.) { auth_basic “Restricted”; auth_basic_user_file /usr/local/nginx/conf/.htpasswd/passwd; } 一旦密码文件已经生成,你也可以用以下的命令来增加允许访问的用户: htpasswd -s /usr/local/nginx/conf/.htpasswd/passwd userName 十五、Nginx SSL配置 HTTP是一个纯文本协议,它是开放的被动监测。你应该使用SSL来加密你的用户内容。 创建SSL证书 执行以下命令: cd /usr/local/nginx/conf openssl genrsa -des3 -out server.key 1024 openssl req -new -key server.key -out server.csr cp server.key server.key.org openssl rsa -in server.key.org -out server.key openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt 编辑nginx.conf并按如下来更新: server { server_name example.com; listen 443; ssl on; ssl_certificate /usr/local/nginx/conf/server.crt; ssl_certificate_key /usr/local/nginx/conf/server.key; access_log /usr/local/nginx/logs/ssl.access.log; error_log /usr/local/nginx/logs/ssl.error.log; } 重启nginx: /usr/local/nginx/sbin/nginx -s reload 十六、Nginx与PHP安全建议 PHP是流行的服务器端脚本语言之一。如下编辑/etc/php.ini文件: Disallow dangerous functions disable_functions = phpinfo, system, mail, exec Try to limit resources Maximum execution time of each script, in seconds max_execution_time = 30 Maximum amount of time each script may spend parsing request data max_input_time = 60 Maximum amount of memory a script may consume (8MB) memory_limit = 8M Maximum size of POST data that PHP will accept. post_max_size = 8M Whether to allow HTTP file uploads. file_uploads = Off Maximum allowed size for uploaded files. upload_max_filesize = 2M Do not expose PHP error messages to external users display_errors = Off Turn on safe mode safe_mode = On Only allow access to executables in isolated directory safe_mode_exec_dir = php-required-executables-path Limit external access to PHP environment safemode_allowed_env_vars = PHP Restrict PHP information leakage expose_php = Off Log all errors log_errors = On Do not register globals for input data register_globals = Off Minimize allowable PHP post size post_max_size = 1K Ensure PHP redirects appropriately cgi.force_redirect = 0 Disallow uploading unless necessary file_uploads = Off Enable SQL safe mode sql.safe_mode = On Avoid Opening remote files allow_url_fopen = Off 十七、如果可能让Nginx运行在一个chroot监狱 把nginx放在一个chroot监狱以减小潜在的非法进入其它目录。你可以使用传统的与nginx一起安装的chroot。如果可能,那使用FreeBSD jails,Xen,OpenVZ虚拟化的容器概念。 十八、在防火墙级限制每个IP的连接数 网络服务器必须监视连接和每秒连接限制。PF和Iptales都能够在进入你的nginx服务器之前阻止最终用户的访问。 Linux Iptables:限制每次Nginx连接数 下面的例子会阻止来自一个IP的60秒钟内超过15个连接端口80的连接数。 /sbin/iptables -A INPUT -p tcp –dport 80 -i eth0 -m state –state NEW -m recent –set /sbin/iptables -A INPUT -p tcp –dport 80 -i eth0 -m state –state NEW -m recent –update –seconds 60 –hitcount 15 -j DROP service iptables save 请根据你的具体情况来设置限制的连接数。 十九:配置操作系统保护Web服务器 像以上介绍的启动SELinux.正确设置/nginx文档根目录的权限。Nginx以用户nginx运行。但是根目录(/nginx或者/usr /local/nginx/html)不应该设置属于用户nginx或对用户nginx可写。找出错误权限的文件可以使用如下命令: find /nginx -user nginx find /usr/local/nginx/html -user nginx 确保你更所有权为root或其它用户,一个典型的权限设置 /usr/local/nginx/html/ ls -l /usr/local/nginx/html/ 示例输出: -rw-r–r– 1 root root 925 Jan 3 00:50 error4xx.html -rw-r–r– 1 root root 52 Jan 3 10:00 error5xx.html -rw-r–r– 1 root root 134 Jan 3 00:52 index.html 你必须删除由vi或其它文本编辑器创建的备份文件: find /nginx -name ‘.?’ -not -name .ht -or -name ‘~’ -or -name ‘.bak’ -or -name ‘.old*’ find /usr/local/nginx/html/ -name ‘.?’ -not -name .ht -or -name ‘~’ -or -name ‘.bak’ -or -name ‘.old*’ 通过find命令的-delete选项来删除这些文件。 二十、限制Nginx连接传出 黑客会使用工具如wget下载你服务器本地的文件。使用Iptables从nginx用户来阻止传出连接。ipt_owner模块试图匹配本地产生的数据包的创建者。下面的例子中只允许user用户在外面使用80连接。 /sbin/iptables -A OUTPUT -o eth0 -m owner –uid-owner vivek -p tcp –dport 80 -m state –state NEW,ESTABLISHED -j ACCEPT 通过以上的配置,你的nginx服务器已经非常安全了并可以发布网页。可是,你还应该根据你网站程序查找更多的安全设置资料。例如,wordpress或者第三方程序。
KB小秘书 2019-12-02 02:06:56 0 浏览量 回答数 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

问题

基础语言百问-Python

基础语言百问-Python 软件界最近非常流行一句话“人生苦短,快用Python”,这就展示出了Python的特点,那就是快,当然这个快并不是指的Python运行快,毕竟是脚本语言,再怎样也快不过C语言和C++这样的底层语言,这里的快指的是...
薯条酱 2019-12-01 20:12:27 56807 浏览量 回答数 30

问题

Android安全开发之ZIP文件目录遍历

1、ZIP文件目录遍历简介 因为ZIP压缩包文件中允许存在“../”的字符串,攻击者可以利用多个“../”在解压时改变ZIP包中某个文件的存放位置,覆盖掉应用原有的文件。如果被覆盖掉的文件是动态链接so、d...
移动安全 2019-12-01 21:18:52 3164 浏览量 回答数 0

问题

在Eclipse中配置Heritrix HTTP ERROR: 500 ...:报错

开源爬虫: Heritrix 1.14.4 安装/使用 Heritrix 是一个由 java 开发的、开源的网络爬虫,用户可以使用它来从网上抓取想要的资源。其最出色之处在于它良好的可扩展性,方便用户实现自己...
kun坤 2020-06-06 22:31:03 1 浏览量 回答数 1

回答

这个网站分页是js生成的,要用自定义处理链(项目要再gitpull下)。 这个分页的处理链简单写了下: publicclassCustomDemoRuleimplementsDecideRule{publicList<Object>handle(Rulerule,List<Object>contentList,MapvalueMap){//valueMap默认会有fetchUrl和 taskName的值StringfetchUrl=String.valueOf(valueMap.get("fetchUrl"));if(contentList!=null){for(inti=0;i<contentList.size();i++){//('page_div',4,2,'lists','shtml',80)Stringcon=String.valueOf(contentList.get(i));String[]arr=con.split(",");if(arr.length>5){inttotalPage=Integer.parseInt(arr[1]);StringlistStr=StringUtil.cutNotContainStartAndEnd(arr[3],"'","'");StringshtmlStr=StringUtil.cutNotContainStartAndEnd(arr[4],"'","'");StringpreUrl=StringUtil.cutNotContainStartAndEnd(fetchUrl,"",listStr);List<Object>list=newArrayList<Object>();for(intj=1;j<=totalPage;j++){Stringurl=preUrl+listStr+"_"+j+"."+shtmlStr;list.add(url);}returnlist;}}}returnnull;}} 配置: <?xmlversion="1.0"encoding="UTF-8"?><task><!-- timeOutSecond:抓取时请求超时时间(单位:秒)   errorRetry:抓取失败重连次数   errorDelayTime:抓取失败后等待时间 fetchPrepareDelay:抓取前延迟时间(单位:秒),防止对某个网站太频繁爬 runThreadNum: 线程数 charset:编码 (如果设为auto,会根据返回的页面编码标志取,如果取不到,可能会报错)--><fetchConfigcharset="utf-8"timeOutSecond="5"errorRetry="5"errorDelayTime="10"runThreadNum="5" fetchPrepareDelayTime="5">  <userAgent>Mozilla/5.0(compatible;webpasser;)</userAgent><headers><headername="Referer"value="http://www.nhfpc.gov.cn"/></headers><!--HTTPCookie--><cookies><!-- <cookie name="cookie1"value=""host=""path=""/>     <cookiename="cookie2"value="1" />--></cookies><!--代理设置:从ip.txt中批量获读取ip,每次抓取随机使用某个ip--><!--<proxiespath="ip.txt"></proxies>--></fetchConfig><customConfig>    <!--自定义rule--><customRules>     <customRulename="digJumpPage"classPath="com.hxt.webpasser.regular.CustomDemoRule"/></customRules></customConfig><!--抓取的域名范围--><scope><limitHostvalue="www.nhfpc.gov.cn"/></scope><!--种子--><seeds><seed url="http://www.nhfpc.gov.cn/zhuzhan/flfg/lists.shtml"/></seeds><!--挖取网页链接,放入抓取队列--><page><scope> <ruletype="regex"value="http://www.nhfpc.gov.cn/zhuzhan/(.*)/(.*).shtml"/></scope><!--列表数据挖取-->  <digLink>     <rules><ruletype="xpath"value="//div[@class='contents']//ul//li//a[@href]"attr="href" /><ruletype="replace">  <oldChars>../</oldChars>    <newChars></newChars>  </rule><ruletype="combine"value="http://www.nhfpc.gov.cn/[$this]"/> </rules>  </digLink>  <!--分页挖取--> <digLink>     <rules>           <ruletype="cut">   <!--截取分页js example:createPageHTML('page_div',4,2,'lists','shtml',80);}-->  <pre><![CDATA[createPageHTML(]]></pre>  <end><![CDATA[);]]></end></rule>  <!--自己定义的处理链, 分页--><ruletype="digJumpPage" />      </rules>  </digLink></page><!--解析具体的业务数据,处理后是一个map --><pagename="films"><scope> <ruletype="regex"value="http://www.nhfpc.gov.cn/\w+/\w+/\d*/\w+.shtml"/></scope><fieldname="title"><rules><!--提取某个字段数据的处理链 --><ruletype="xpath"value="//div[@class='content_title']"exp="text()"/><ruletype="toText"></rule></rules></field><fieldname="subTitle"><rules><ruletype="xpath"value="//div[@class='content_subtitle']//span[1]"exp="text()"/><ruletype="toText"></rule><!--  <ruletype="cut">  <pre>年代:</pre>  <end></end> </rule> --></rules></field><fieldname="submitdate"><rules><ruletype="xpath"value="//div[@class='content_subtitle']//span[3]"exp="text()"/></rules></field> <fieldname="content"> <rules><ruletype="xpath"value="//div[@class='content']"exp="text()"/><ruletype="toText"></rule></rules></field><!-- <fieldname="downlist"isList="1">    <rules><ruletype="xpath"value="//div[@class='ndownlist']"exp="html()" /> <ruletype="cut">  <pre>GvodUrls="</pre>  <end>";</end> </rule> <ruletype="split"> <paramname="splitMark"value="###"/> </rule></rules></field> -->  </page><!--抓取解析后的数据持久化--><resultHandlertarget="handleResultMapInterface"classPath="com.hxt.webpasser.persistent.impl.DiskJsonHandleResult"><propertyname="rootDir"value="d:/www.nhfpc.gov.cn/data"></property><propertyname="charSet"value="gbk"></property></resultHandler> </task> @hxt168谢谢~
爱吃鱼的程序员 2020-06-09 13:20:55 0 浏览量 回答数 0

问题

在Eclipse中配置Heritrix HTTP ERROR: 500 Unable+to+comp

"开源爬虫: Heritrix 1.14.4 安装/使用 Heritrix 是一个由 java 开发的、开源的网络爬虫,用户可以使用它来从网上抓取想要的资源。其最出色之处在于它良好的可扩展性,方便用...
python小菜菜 2020-06-02 19:41:11 1 浏览量 回答数 1

云产品推荐

上海奇点人才服务相关的云产品 小程序定制 上海微企信息技术相关的云产品 国内短信套餐包 ECS云服务器安全配置相关的云产品 开发者问答 阿里云建站 自然场景识别相关的云产品 万网 小程序开发制作 视频内容分析 视频集锦 代理记账服务 阿里云AIoT