赞
踩
JS是脚本语言,脚本语言都需要一个解析器才能运行。对于写在HTML页面里的JS,浏览器充当了解析器的角色。而对于需要独立运行的JS,NodeJS就是一个解析器。
每一种解析器都是一个运行环境,不但允许JS定义各种数据结构,进行各种计算,还允许JS使用运行环境提供的内置对象和方法做一些事情。例如运行在浏览器中的JS的用途是操作DOM,浏览器就提供了document
之类的内置对象。而运行在NodeJS中的JS的用途是操作磁盘文件或搭建HTTP服务器,NodeJS就相应提供了fs
、http
等内置对象。
在引入
TypedArray
之前,JavaScript 语言没有用于读取或操作二进制数据流的机制。Buffer
类是作为 Node.js API 的一部分引入的,用于在 TCP 流、文件系统操作、以及其他上下文中与八位字节流进行交互。Buffer对象是Node处理二进制数据的一个接口。它是Node原生提供的全局对象,可以直接使用,不需要require(‘buffer’),我的理解其实buffer就是个字节数组。
write() 向buffer对象中写入内容
slice() 截取新的buffer对象
toString() 把buf对象转成字符串
toJson() 把buf对象转成json形式的字符串
toJSON方法不需要显式调用,当JSON.stringify方法调用的时候会自动调用toJSON方法
path
模块提供用于处理文件路径和目录路径的实用工具。 它可以使用以下方式访问:
const path = require('path');
const path = require('path'); console.log(path) // 结果: // { resolve: [Function: resolve], // normalize: [Function: normalize], // isAbsolute: [Function: isAbsolute], // join: [Function: join], // relative: [Function: relative], // toNamespacedPath: [Function: toNamespacedPath], // dirname: [Function: dirname], // basename: [Function: basename], // extname: [Function: extname], // format: [Function: format], // parse: [Function: parse], // sep: '\\', // delimiter: ';', // win32: [Circular], // posix: // { resolve: [Function: resolve], // normalize: [Function: normalize], // isAbsolute: [Function: isAbsolute], // join: [Function: join], // relative: [Function: relative], // toNamespacedPath: [Function: toNamespacedPath], // dirname: [Function: dirname], // basename: [Function: basename], // extname: [Function: extname], // format: [Function: format], // parse: [Function: parse], // sep: '/', // delimiter: ':', // win32: [Circular], // posix: [Circular], // _makeLong: [Function: toNamespacedPath] }, // _makeLong: [Function: toNamespacedPath] }
console.log(path.basename('/foo/bar/baz/asdf/quux.html'));
// 返回: 'quux.html'
console.log(path.basename('/foo/bar/baz/asdf/quux.html', '.html'));
// 返回: 'quux'
console.log(__dirname);
// 返回 此文件目录的绝对路径C:\Users\xiaox\Desktop\code
console.log(__filename)
// 返回 此文件的绝对路径C:\Users\xiaox\Desktop\code\1.js
console.log(path.dirname('/abc/qqq/www/abc'));
// 返回 /abc/qqq/www
console.log(path.dirname('/abc/qqq/www/abc.txt'));
// 返回 /abc/qqq/www
console.log(path.extname('index.html'));
// 返回 .html
path.format(pathObject) obj->string
let objpath = {
root: 'C:\\',
dir:
'C:\\Users\\xiaox\\Desktop\\code',
base: '1.js',
ext: '.js',
name: '1'
};
console.log(path.format(objpath));
// 返回C:\Users\xiaox\Desktop\code\1.js
当为
pathObject
提供属性时,注意以下组合,其中一些属性优先于另一些属性:
- 如果提供了
pathObject.dir
,则忽略pathObject.root
。- 如果
pathObject.base
存在,则忽略pathObject.ext
和pathObject.name
。
path.parse(path) string->obj
console.log(path.parse(__filename));
/*
{ root: 'C:\\',
dir:
'C:\\Users\\xiaox\\Desktop\\code',
base: '1.js',
ext: '.js',
name: '1'
}
*/
console.log(path.isAbsolute('/foo/bar'));
// 返回true
console.log(path.isAbsolute('C:/foo/..'));
// 返回true
(…表示上层路径;.表示当前路径),在连接路径的时候会格式化路径
path.join('/foo', 'bar', 'baz/asdf', 'quux', '..');
// 返回: '/foo/bar/baz/asdf'
path.join('foo', {}, 'bar');
// 抛出 'TypeError: Path must be a string. Received {}'
console.log(path.normalize('/foo/bar//baz/asdf/quux/..'));
// 返回: '/foo/bar/baz/asdf'
console.log(path.normalize('C:\\temp\\\\foo\\bar\\..\\'));
// 返回: 'C:\\temp\\foo\\'
console.log(path.relative('/data/orandea/test/aaa','/data/orandea/impl/bbb'));
// 返回: '../../impl/bbb'
console.log(path.relative('C:\\orandea\\test\\aaa','C:\\orandea\\impl\\bbb'));
// 返回: '..\\..\\impl\\bbb'
给定的路径序列从右到左进行处理,每个后续的 path
前置,直到构造出一个绝对路径
path.resolve('wwwroot', 'static_files/png/', '../gif/image.gif');
// 如果当前工作目录是 /home/myself/node,
// 则返回 '/home/myself/node/wwwroot/static_files/gif/image.gif'
console.log(path.delimiter);//表示路径分隔符(windows是\ Linux是/) 在 POSIX 上: console.log(process.env.PATH); // 打印: '/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin' process.env.PATH.split(path.delimiter); // 返回: ['/usr/bin', '/bin', '/usr/sbin', '/sbin', '/usr/local/bin'] 在 Windows 上: console.log(process.env.PATH); // 打印: 'C:\Windows\system32;C:\Windows;C:\Program Files\node\' process.env.PATH.split(path.delimiter); // 返回: ['C:\\Windows\\system32', 'C:\\Windows', 'C:\\Program Files\\node\\'] ------------------------------------------------------------------------------ console.log(path.sep);//环境变量分隔符(windows中使用; linux中使用:) 在 POSIX 上: 'foo/bar/baz'.split(path.sep); // 返回: ['foo', 'bar', 'baz'] 在 Windows 上: 'foo\\bar\\baz'.split(path.sep); // 返回: ['foo', 'bar', 'baz'] 在 Windows 上,正斜杠(/)和反斜杠(\)都被接受为路径片段分隔符。 但是, path 方法只添加反斜杠(\)。
/* 异步I/O input/output 1、文件操作 2、网络操作 在浏览器中也存在异步操作: 1、定时任务 2、事件处理 3、Ajax回调处理 js的运行时单线程的 引入事件队列机制 Node.js中的事件模型与浏览器中的事件模型类似 单线程+事件队列 Node.js中异步执行的任务: 1、文件I/O 2、网络I/O 基于回调函数的编码风格 */
Stats { dev: 2114,//该文件的设备的数字标识符 ino: 48064969,//文件系统特定的文件索引节点编号 mode: 33188,//描述文件类型和模式的位字段 nlink: 1,//文件存在的硬链接数 uid: 85,//拥有该文件(POSIX)的用户的数字型用户标识符 gid: 100,//拥有该文件(POSIX)的群组的数字型群组标识符 rdev: 0,//如果文件被视为特殊文件,则此值为数字型设备标识符 size: 527,//文件的大小(以字节为单位) blksize: 4096,//用于 I/O 操作的文件系统块的大小 blocks: 8,//为此文件分配的块数 atimeMs: 1318289051000.1,//表明上次访问此文件的时间戳,以 POSIX 纪元以来的毫秒数表示 mtimeMs: 1318289051000.1,//表明上次修改此文件的时间戳,以 POSIX 纪元以来的毫秒数表示 ctimeMs: 1318289051000.1,//表明上次更改文件状态的时间戳,以 POSIX 纪元以来的毫秒数表示 birthtimeMs: 1318289051000.1,//表明此文件的创建时间的时间戳,以 POSIX 纪元以来的毫秒数表示 atime: Mon, 10 Oct 2011 23:24:11 GMT,//表明上次访问此文件的时间戳 文件访问时间 mtime: Mon, 10 Oct 2011 23:24:11 GMT,//表明上次修改此文件的时间戳 文件数据发生变化的时间 ctime: Mon, 10 Oct 2011 23:24:11 GMT,//表明上次更改文件状态的时间戳 文件的状态信息发生变化的时间(比如文件的权限) birthtime: Mon, 10 Oct 2011 23:24:11 GMT //表示此文件的创建时间的时间戳 文件创建的时间 }
常用判断是否为常规文件stats.isFile()和文件目录stats.isDirectory()返回布尔值
fs.stat(path[, options], callback)
// const fs = require('fs'); // const pathsToCheck = ['./txtDir', './txtDir/file.txt']; //异步操作 // for (let i = 0; i < pathsToCheck.length; i++) { // fs.stat(pathsToCheck[i], function(err, stats) { // if(stats.isFile()){ // console.log(pathsToCheck[i]+'---文件'); // console.log(stats) // }else if(stats.isDirectory()){ // console.log(pathsToCheck[i]+'---目录'); // console.log(stats) // }else{ // console.log(err) // } // }); // } // 同步操作Sync // console.log(1); // let ret = fs.statSync('./data.txt'); // console.log(ret); // console.log(2);
/* 读文件操作 */ const fs = require('fs'); const path = require('path'); let strpath = path.join(__dirname,'data.txt'); fs.readFile(strpath,(err,data)=>{ if(err) return; console.log(data.toString()); }); 如果有第二个参数并且是编码,那么回调函数获取到的数据就是字符串 如果没有第二个参数,那么得到的就是Buffer实例对象 fs.readFile(strpath,'utf8',(err,data)=>{ if(err) return; // console.log(data.toString()); console.log(data); }); 同步操作 let ret = fs.readFileSync(strpath,'utf8'); console.log(ret);
/* 写文件操作 */ const fs = require('fs'); const path = require('path'); // 异步操作 let strpath = path.join(__dirname,'data.txt'); fs.writeFile(strpath,'hello nihao','utf8',(err)=>{ if(!err){ console.log('文件写入成功'); } }); let buf = Buffer.from('hi'); fs.writeFile(strpath,buf,'utf8',(err)=>{ if(!err){ console.log('文件写入成功'); } }); // 同步操作 fs.writeFileSync(strpath,'tom and jerry');
将文件从一个地方写入另一个地方 const path = require('path'); const fs = require('fs'); let spath = path.join(__dirname,'../03-source','file.zip'); let dpath = path.join('C:\\Users\\www\\Desktop','file.zip'); let readStream = fs.createReadStream(spath); let writeStream = fs.createWriteStream(dpath); // 基于事件的处理方式 // $('input[type=button]').on('click',function(){ // console.log('hello'); // }); 方法一 // ----------------------------------- let num = 1; readStream.on('data',(chunk)=>{ num++; writeStream.write(chunk); }); readStream.on('end',()=>{ console.log('文件处理完成'+num); }); 方法二 // ----------------------------------- // pipe的作用直接把输入流和输出流 readStream.pipe(writeStream); 方法三 // ---------------------------------- fs.createReadStream(spath).pipe(fs.createWriteStream(dpath));
创建目录fs.mkdir(path[, mode], callback)/fs.mkdirSync(path[, mode])
const path = require('path');
const fs = require('fs');
// 创建目录
fs.mkdir(path.join(__dirname,'abc'),(err)=>{
console.log(err);
});
fs.mkdirSync(path.join(__dirname,'hello'));
// 创建 /tmp/a/apple 目录,无论是否存在 /tmp 和 /tmp/a 目录。
// recursive 属性(指示是否应创建父文件夹)的对象
fs.mkdir('/tmp/a/apple', { recursive: true }, (err) => {
if (err) throw err;
});
读取目录fs.readdir(path[, options], callback)/fs.readdirSync(path[, options])
const path = require('path'); const fs = require('fs'); // 读取目录 fs.readdir(__dirname,(err,files)=>{ files.forEach((item,index)=>{ fs.stat(path.join(__dirname,item),(err,stat)=>{ if(stat.isFile()){ console.log(item,'文件'); }else if(stat.isDirectory()){ console.log(item,'目录'); } }); }); }); let files = fs.readdirSync(__dirname); files.forEach((item,index)=>{ fs.stat(path.join(__dirname,item),(err,stat)=>{ if(stat.isFile()){ console.log(item,'文件'); }else if(stat.isDirectory()){ console.log(item,'目录'); } }); });
删除目录fs.rmdir(path, callback)/fs.rmdirSync(path)
// 删除目录
fs.rmdir(path.join(__dirname,'abc'),(err)=>{
console.log(err);
});
fs.rmdirSync(path.join(__dirname,'qqq'));
/* 文件操作案例(初始化目录结构) */ const path = require('path'); const fs = require('fs'); let root = 'C:\\Users\\www\\Desktop'; let fileContent = ` <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <div>welcome to this</div> </body> </html> `; // 初始化数据 let initData = { projectName : 'mydemo', data : [{ name : 'img', type : 'dir' },{ name : 'css', type : 'dir' },{ name : 'js', type : 'dir' },{ name : 'index.html', type : 'file' }] } // 创建项目跟路径 fs.mkdir(path.join(root,initData.projectName),(err)=>{ if(err) return; // 创建子目录和文件 initData.data.forEach((item)=>{ if(item.type == 'dir'){ // 创建子目录 fs.mkdirSync(path.join(root,initData.projectName,item.name)); }else if(item.type == 'file'){ // 创建文件并写入内容 fs.writeFileSync(path.join(root,initData.projectName,item.name),fileContent); } }); });
传统的动态网站开发需要应用软件 PHP : Apache + php模块 java :Tomcat 、Weblogic Node.js : 不需要应用软件(可以自己实现) /* Node.js的Web开发相关的内容: 1、Node.js不需要依赖第三方应用软件(Apache),可以基于api自己实现 2、实现静态资源服务器 3、路由处理 4、动态网站 5、模板引擎 6、get和post参数传递和处理 Web开发框架:express */
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
const http = require('http'); // // 创建服务器实例对象 let server = http.createServer(); console.log(server) Server { _events: [Object: null prototype] { connection: [Function: connectionListener] }, _eventsCount: 1, _maxListeners: undefined, _connections: 0, _handle: null, _usingWorkers: false, _workers: [], _unref: false, allowHalfOpen: true, pauseOnConnect: false, httpAllowHalfOpen: false, timeout: 120000,//超时时间(以毫秒为单位)。默认值: 120000(2 分钟) keepAliveTimeout: 5000,//超时时间(以毫秒为单位)。默认值: 5000(5 秒)更改此值仅影响到服务器的新连接,而不影响任何现有连接 maxHeadersCount: null,//限制最大传入请求头数。 如果设置为 0,则不会应用任何限制 默认值: 2000 headersTimeout: 40000,//限制解析器等待接收完整 HTTP 请求头的时间 默认值: 40000 [Symbol(IncomingMessage)]: { [Function: IncomingMessage] super_: { [Function: Readable] ReadableState: [Function: ReadableState], super_: [Function], _fromList: [Function: fromList] } }, [Symbol(ServerResponse)]: { [Function: ServerResponse] super_: { [Function: OutgoingMessage] super_: [Function] } }, [Symbol(asyncId)]: -1 }
http.createServer
方法会返回一个http.Server
对象实例,requestListener
可选参数传入时,将做为http.Server
对象'request'
事件的监听器。
request
<http.IncomingMessage>response
<http.ServerResponse>每次有请求时都会触发。 每个连接可能有多个请求(在 HTTP Keep-Alive 连接的情况下)。
/* 初步实现服务器功能 */ const http = require('http'); // ----------------------------- 方法一: // 创建服务器实例对象 let server = http.createServer(); console.log(server) // 绑定请求事件 server.on('request',(req,res)=>{ res.end('hello'); }); // 监听端口 server.listen(3000); // ----------------------------- 方法二: http.createServer((req,res)=>{ res.end('ok');//response.end([data[, encoding]][, callback]) }).listen(3000,'192.168.0.106',()=>{ console.log('running...'); });
res.end()就是上述response类的方法;[response.end(data[, encoding]][, callback])
res.end('ok','utf-8',()=>{
console.log('一切正常')
});
此方法与 net.Server
中的 server.listen()
相同。
上一例子也可,详细可见官方api
server.listen({
host: 'localhost',
port: 80,
exclusive: true
});
1、req对象是Class: http.IncomingMessage的实例对象
2、res对象是Class: http.ServerResponse的实例对象
const http = require('http'); http.createServer((req,res)=>{ // req.url可以获取URL中的路径(端口之后部分) // res.end(req.url); if(req.url.startsWith('/index')){ // write向客户端响应内容,可以写多次 res.write('hello'); res.write('hi'); res.write('nihao'); // end方法用来完成响应,只能执行一次 res.end(); }else if(req.url.startsWith('/about')){ res.end('about'); }else{ res.end('no content'); } }).listen(3000,'192.168.0.106',()=>{ console.log('running...'); });
res.write()就是上述response类的方法;[response.write(chunk, encoding][, callback])
/* 响应完整的页面信息 */ const http = require('http'); const path = require('path'); const fs = require('fs'); // 根据路径读取文件的内容,并且响应到浏览器端 let readFile = (url,res) => { fs.readFile(path.join(__dirname,'www',url),'utf8',(err,fileContent)=>{ if(err){ res.end('server error'); }else{ res.end(fileContent); } }); } http.createServer((req,res)=>{ // 处理路径的分发 if(req.url.startsWith('/index')){ readFile('index.html',res); }else if(req.url.startsWith('/about')){ readFile('about.html',res); }else if(req.url.startsWith('/list')){ readFile('list.html',res); }else{ // 设置相应类型和编码 res.writeHead(200,{ 'Content-Type':'text/plain; charset=utf8' }); res.end('页面被狗狗叼走了'); } }).listen(3000,'192.168.0.106',()=>{ console.log('running...'); });
设置响应头[response.writeHead(statusCode, statusMessage][, headers])与response.setHeader(name, value)
当使用 response.setHeader()
设置响应头时,它们将与传给 response.writeHead()
的任何响应头合并,其中 response.writeHead()
的响应头优先。
// 返回 content-type = text/plain
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'text/html');
res.setHeader('X-Foo', 'bar');
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('ok');
});
const url = require('url');
console.log(url)
{ Url: [Function: Url],
parse: [Function: urlParse],
resolve: [Function: urlResolve],
resolveObject: [Function: urlResolveObject],
format: [Function: urlFormat],
URL: [Function: URL],
URLSearchParams: [Function: URLSearchParams],
domainToASCII: [Function: domainToASCII],
domainToUnicode: [Function: domainToUnicode],
pathToFileURL: [Function: pathToFileURL],
fileURLToPath: [Function: fileURLToPath]
}
parse方法的作用就是把URL字符串转化为对象
const url = require('url'); let str = 'http://www.baidu.com/abc/qqq?flag=123&keyword=java'; let ret = url.parse(str) console.log(ret) //以下可以参展urlObject Url { protocol: 'http:',//协议 slashes: true,// url里characters (/)的是true,否则false auth: null,//用户名和密码 host: 'www.baidu.com',//主机地址 主机名+端口 port: null,//端口 hostname: 'www.baidu.com',//主机名 hash: null,//characters (#) search: '?flag=123&keyword=java',//查询参数 query: 'flag=123&keyword=java',//去掉?的查询参数 pathname: '/abc/qqq',//路径名 path: '/abc/qqq?flag=123&keyword=java',//路径 href: 'http://www.baidu.com/abc/qqq?flag=123&keyword=java' //完整url }
第二个参数parseQueryString
其实将query.parse了
const url = require('url'); let str = 'http://www.baidu.com/abc/qqq?flag=123&keyword=java'; let ret = url.parse(str,true) console.log(ret) Url { protocol: 'http:', slashes: true, auth: null, host: 'www.baidu.com', port: null, hostname: 'www.baidu.com', hash: null, search: '?flag=123&keyword=java', query: [Object: null prototype] { flag: '123', keyword: 'java' }, pathname: '/abc/qqq', path: '/abc/qqq?flag=123&keyword=java', href: 'http://www.baidu.com/abc/qqq?flag=123&keyword=java' }
format的作用就是把对象转化为标准的URL字符串
url.format({
protocol: 'https',
hostname: 'example.com',
pathname: '/some/path',
query: {
page: 1,
format: 'json'
}
});
// => 'https://example.com/some/path?page=1&format=json'
querystring
模块提供用于解析和格式化 URL 查询字符串的实用工具。 它可以使用以下方式访问:
const querystring = require('querystring');
parse方法的作用就是把字符串转成对象
str
string 要解析的 URL 查询字符串。sep
string 用于在查询字符串中分隔键值对的子字符串。默认值: '&'
。eq
string 用于在查询字符串中分隔键和值的子字符串。默认值: '='
。options
object
querystring.parse()
方法将 URL 查询字符串 str
解析为键值对的集合。
例如,查询字符串 'foo=bar&abc=xyz&abc=123'
被解析为:
const querystring = require('querystring');
let param = 'foo=bar&abc=xyz&abc=123';
let obj = querystring.parse(param);
console.log(obj);
{
foo: 'bar',
abc: ['xyz', '123']
}
querystring.parse()
方法返回的对象不是原型继承自 JavaScript Object
。 这意味着典型的 Object
方法如 obj.toString()
、 obj.hasOwnProperty()
等都没有定义并且不起作用。
stringify的作用就是把对象转成字符串
obj
object 要序列化为 URL 查询字符串的对象。sep
string 用于在查询字符串中分隔键值对的子字符串。默认值: '&'
。eq
string 用于在查询字符串中分隔键和值的子字符串。默认值: '='
。options
encodeURIComponent
function 在查询字符串中将 URL 不安全字符转换为百分比编码时使用的函数。默认值: querystring.escape()
。querystring.stringify()
方法通过迭代对象的自身属性从给定的 obj
生成 URL 查询字符串。
它序列化了传入 obj
中的以下类型的值: | | | <string[]> | <number[]> | <boolean[]>。 任何其他输入值都将被强制转换为空字符串。
querystring.stringify({ foo: 'bar', baz: ['qux', 'quux'], corge: '' });
// 返回 'foo=bar&baz=qux&baz=quux&corge='
querystring.stringify({ foo: 'bar', baz: 'qux' }, ';', ':');
// 返回 'foo:bar;baz:qux'
let obj1 = {
flag : '123',
abc : ['hello','hi']
}
let str1 = querystring.stringify(obj1);
console.log(str1);
const querystring = require('querystring'); const http = require('http'); http.createServer((req,res)=>{ if(req.url.startsWith('/login')){ let pdata = ''; req.on('data',(chunk)=>{ // 每次获取一部分数据 pdata += chunk; }); req.on('end',()=>{ // 这里才能得到完整的数据 console.log(pdata); let obj = querystring.parse(pdata); res.end(obj.username+'-----'+obj.password); }); } }).listen(3000,()=>{ console.log('running...'); }) //这里可以自己用postman调试
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。