473 lines
12 KiB
JavaScript
473 lines
12 KiB
JavaScript
|
var fs = require('fs');
|
|||
|
var path_lib = require("path");
|
|||
|
var charset = "utf-8";
|
|||
|
if (!fs.existsSync)
|
|||
|
fs.existsSync = path_lib.existsSync; // node < 0.8
|
|||
|
|
|||
|
/**
|
|||
|
* 保存数据到指定文件
|
|||
|
* @param path 文件完整路径名
|
|||
|
* @param data 要保存的数据
|
|||
|
*/
|
|||
|
function save(path,data){
|
|||
|
if(exists(path)) {
|
|||
|
remove(path);
|
|||
|
}
|
|||
|
path = escapePath(path);
|
|||
|
createDirectory(path_lib.dirname(path));
|
|||
|
fs.writeFileSync(path,data,charset);
|
|||
|
}
|
|||
|
/**
|
|||
|
* 创建文件夹
|
|||
|
*/
|
|||
|
function createDirectory(path, mode, made) {
|
|||
|
path = escapePath(path);
|
|||
|
if (mode === undefined) {
|
|||
|
mode = 0777 & (~process.umask());
|
|||
|
}
|
|||
|
if (!made) made = null;
|
|||
|
|
|||
|
if (typeof mode === 'string')
|
|||
|
mode = parseInt(mode, 8);
|
|||
|
path = path_lib.resolve(path);
|
|||
|
|
|||
|
try {
|
|||
|
fs.mkdirSync(path, mode);
|
|||
|
made = made || path;
|
|||
|
}
|
|||
|
catch (err0) {
|
|||
|
switch (err0.code) {
|
|||
|
case 'ENOENT' :
|
|||
|
made = createDirectory(path_lib.dirname(path), mode, made);
|
|||
|
createDirectory(path, mode, made);
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
var stat;
|
|||
|
try {
|
|||
|
stat = fs.statSync(path);
|
|||
|
}
|
|||
|
catch (err1) {
|
|||
|
throw err0;
|
|||
|
}
|
|||
|
if (!stat.isDirectory()) throw err0;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
return made;
|
|||
|
}
|
|||
|
|
|||
|
var textTemp = {};
|
|||
|
/**
|
|||
|
* 读取文本文件,返回打开文本的字符串内容,若失败,返回"".
|
|||
|
* @param path 要打开的文件路径
|
|||
|
*/
|
|||
|
function read(path) {
|
|||
|
path = escapePath(path);
|
|||
|
var text = textTemp[path];
|
|||
|
if(text){
|
|||
|
return text;
|
|||
|
}
|
|||
|
try{
|
|||
|
text = fs.readFileSync(path,charset);
|
|||
|
text = text.replace(/^\uFEFF/, '');
|
|||
|
}
|
|||
|
catch (err0) {
|
|||
|
return "";
|
|||
|
}
|
|||
|
if(text){
|
|||
|
var ext = getExtension(path).toLowerCase();
|
|||
|
if(ext=="ts"||ext=="exml"){
|
|||
|
textTemp[path] = text;
|
|||
|
}
|
|||
|
}
|
|||
|
return text;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 读取字节流文件,返回字节流,若失败,返回null.
|
|||
|
* @param path 要打开的文件路径
|
|||
|
*/
|
|||
|
function readBinary(path) {
|
|||
|
path = escapePath(path);
|
|||
|
try{
|
|||
|
var binary = fs.readFileSync(path);
|
|||
|
}
|
|||
|
catch (e) {
|
|||
|
return null;
|
|||
|
}
|
|||
|
return binary;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 复制文件或目录
|
|||
|
* @param source 文件源路径
|
|||
|
* @param dest 文件要复制到的目标路径
|
|||
|
*/
|
|||
|
function copy(source, dest) {
|
|||
|
source = escapePath(source);
|
|||
|
dest = escapePath(dest);
|
|||
|
var stat = fs.lstatSync(source);
|
|||
|
if (stat.isDirectory()) {
|
|||
|
_copy_dir(source, dest);
|
|||
|
}
|
|||
|
else {
|
|||
|
_copy_file(source, dest);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function isDirectory(path){
|
|||
|
path = escapePath(path);
|
|||
|
try{
|
|||
|
var stat = fs.statSync(path);
|
|||
|
}
|
|||
|
catch(e){
|
|||
|
return false;
|
|||
|
}
|
|||
|
return stat.isDirectory();
|
|||
|
}
|
|||
|
|
|||
|
function isSymbolicLink(path){
|
|||
|
path = escapePath(path);
|
|||
|
try{
|
|||
|
var stat = fs.statSync(path);
|
|||
|
}
|
|||
|
catch(e){
|
|||
|
return false;
|
|||
|
}
|
|||
|
return stat.isSymbolicLink();
|
|||
|
}
|
|||
|
|
|||
|
function isFile(path){
|
|||
|
path = escapePath(path);
|
|||
|
try{
|
|||
|
var stat = fs.statSync(path);
|
|||
|
}
|
|||
|
catch(e){
|
|||
|
return false;
|
|||
|
}
|
|||
|
return stat.isFile();
|
|||
|
}
|
|||
|
|
|||
|
function _copy_file(source_file, output_file) {
|
|||
|
createDirectory(path_lib.dirname(output_file))
|
|||
|
var byteArray = fs.readFileSync(source_file);
|
|||
|
fs.writeFileSync(output_file, byteArray);
|
|||
|
}
|
|||
|
|
|||
|
function _copy_dir(sourceDir, outputDir) {
|
|||
|
createDirectory(outputDir);
|
|||
|
var list = fs.readdirSync(sourceDir);
|
|||
|
list.forEach(function (fileName) {
|
|||
|
copy(path_lib.join(sourceDir, fileName), path_lib.join(outputDir, fileName));
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 删除文件或目录
|
|||
|
* @param path 要删除的文件源路径
|
|||
|
*/
|
|||
|
function remove(path) {
|
|||
|
path = escapePath(path);
|
|||
|
try{
|
|||
|
fs.lstatSync(path).isDirectory()
|
|||
|
? rmdir(path)
|
|||
|
: fs.unlinkSync(path)
|
|||
|
}
|
|||
|
catch (e){
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function rmdir(path) {
|
|||
|
var files = [];
|
|||
|
if( fs.existsSync(path) ) {
|
|||
|
files = fs.readdirSync(path);
|
|||
|
files.forEach(function(file){
|
|||
|
var curPath = path + "/" + file;
|
|||
|
if(fs.statSync(curPath).isDirectory()) {
|
|||
|
rmdir(curPath);
|
|||
|
}
|
|||
|
else {
|
|||
|
fs.unlinkSync(curPath);
|
|||
|
}
|
|||
|
});
|
|||
|
fs.rmdirSync(path);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 返回指定文件的父级文件夹路径,返回字符串的结尾已包含分隔符。
|
|||
|
*/
|
|||
|
function getDirectory(path) {
|
|||
|
path = escapePath(path);
|
|||
|
return path_lib.dirname(path)+"/";
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 获得路径的扩展名,不包含点字符。
|
|||
|
*/
|
|||
|
function getExtension(path) {
|
|||
|
path = escapePath(path);
|
|||
|
var index = path.lastIndexOf(".");
|
|||
|
if(index==-1)
|
|||
|
return "";
|
|||
|
var i = path.lastIndexOf("/");
|
|||
|
if(i>index)
|
|||
|
return "";
|
|||
|
return path.substring(index+1);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 获取路径的文件名(不含扩展名)或文件夹名
|
|||
|
*/
|
|||
|
function getFileName(path) {
|
|||
|
if (!path)
|
|||
|
return "";
|
|||
|
path = escapePath(path);
|
|||
|
var startIndex = path.lastIndexOf("/");
|
|||
|
var endIndex;
|
|||
|
if (startIndex > 0 && startIndex == path.length - 1) {
|
|||
|
path = path.substring(0, path.length - 1);
|
|||
|
startIndex = path.lastIndexOf("/");
|
|||
|
endIndex = path.length;
|
|||
|
return path.substring(startIndex + 1, endIndex);
|
|||
|
}
|
|||
|
endIndex = path.lastIndexOf(".");
|
|||
|
if (endIndex == -1)
|
|||
|
endIndex = path.length;
|
|||
|
return path.substring(startIndex + 1, endIndex);
|
|||
|
}
|
|||
|
/**
|
|||
|
* 获取指定文件夹下的文件或文件夹列表,不包含子文件夹内的文件。
|
|||
|
* @param path 要搜索的文件夹
|
|||
|
* @param relative 是否返回相对路径,若不传入或传入false,都返回绝对路径。
|
|||
|
*/
|
|||
|
function getDirectoryListing(path){
|
|||
|
var relative = arguments[1];
|
|||
|
path = escapePath(path);
|
|||
|
try{
|
|||
|
var list = fs.readdirSync(path);
|
|||
|
}
|
|||
|
catch (e){
|
|||
|
return [];
|
|||
|
}
|
|||
|
if(!relative){
|
|||
|
var length = list.length;
|
|||
|
for(var i = 0;i<length;i++){
|
|||
|
list[i] = joinPath(path,list[i]);
|
|||
|
}
|
|||
|
}
|
|||
|
return list;
|
|||
|
}
|
|||
|
|
|||
|
function getDirectoryAllListing(path) {
|
|||
|
var list = [];
|
|||
|
if (isDirectory(path)) {
|
|||
|
var fileList = getDirectoryListing(path);
|
|||
|
for (var key in fileList) {
|
|||
|
list = list.concat(getDirectoryAllListing(fileList[key]));
|
|||
|
}
|
|||
|
|
|||
|
return list;
|
|||
|
}
|
|||
|
|
|||
|
return [path];
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 使用指定扩展名搜索文件夹及其子文件夹下所有的文件
|
|||
|
* @param dir 要搜索的文件夹
|
|||
|
* @param extension 要搜索的文件扩展名,不包含点字符,例如:"png"。不设置表示获取所有类型文件。
|
|||
|
*/
|
|||
|
function search(dir, extension) {
|
|||
|
var list = [];
|
|||
|
try{
|
|||
|
var stat = fs.statSync(dir);
|
|||
|
}
|
|||
|
catch(e){
|
|||
|
return list;
|
|||
|
}
|
|||
|
if (stat.isDirectory()) {
|
|||
|
findFiles(dir,list,extension,null);
|
|||
|
}
|
|||
|
return list;
|
|||
|
}
|
|||
|
/**
|
|||
|
* 使用过滤函数搜索文件夹及其子文件夹下所有的文件
|
|||
|
* @param dir 要搜索的文件夹
|
|||
|
* @param filterFunc 过滤函数:filterFunc(file:File):Boolean,参数为遍历过程中的每一个文件,返回true则加入结果列表
|
|||
|
*/
|
|||
|
function searchByFunction(dir, filterFunc) {
|
|||
|
var list = [];
|
|||
|
var checkDir = arguments[2];
|
|||
|
try{
|
|||
|
var stat = fs.statSync(dir);
|
|||
|
}
|
|||
|
catch(e){
|
|||
|
return list;
|
|||
|
}
|
|||
|
if (stat.isDirectory()) {
|
|||
|
findFiles(dir,list,"",filterFunc,checkDir);
|
|||
|
}
|
|||
|
return list;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
function findFiles(filePath,list,extension,filterFunc,checkDir) {
|
|||
|
var files = fs.readdirSync(filePath);
|
|||
|
var length = files.length;
|
|||
|
for (var i = 0; i < length; i++) {
|
|||
|
if (files[i].charAt(0) == ".") {
|
|||
|
continue;
|
|||
|
}
|
|||
|
var path = joinPath(filePath ,files[i]);
|
|||
|
var stat = fs.statSync(path);
|
|||
|
if (stat.isDirectory()) {
|
|||
|
if(checkDir){
|
|||
|
if (!filterFunc(path)) {
|
|||
|
continue;
|
|||
|
}
|
|||
|
}
|
|||
|
findFiles(path, list,extension,filterFunc);
|
|||
|
}
|
|||
|
else if (filterFunc != null) {
|
|||
|
if (filterFunc(path)) {
|
|||
|
list.push(path);
|
|||
|
}
|
|||
|
}
|
|||
|
else if(extension){
|
|||
|
var len = extension.length;
|
|||
|
if(path.charAt(path.length-len-1)=="."&&
|
|||
|
path.substr(path.length-len,len).toLowerCase()==extension){
|
|||
|
list.push(path);
|
|||
|
}
|
|||
|
}
|
|||
|
else{
|
|||
|
list.push(path);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 指定路径的文件或文件夹是否存在
|
|||
|
*/
|
|||
|
function exists(path) {
|
|||
|
path = escapePath(path);
|
|||
|
return fs.existsSync(path);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 转换本机路径为Unix风格路径。
|
|||
|
*/
|
|||
|
function escapePath(path) {
|
|||
|
if (!path)
|
|||
|
return "";
|
|||
|
return path.split("\\").join("/");
|
|||
|
}
|
|||
|
/**
|
|||
|
* 连接路径,支持传入多于两个的参数。也支持"../"相对路径解析。返回的分隔符为Unix风格。
|
|||
|
*/
|
|||
|
function joinPath(dir,filename){
|
|||
|
var path = path_lib.join.apply(null,arguments);
|
|||
|
path = escapePath(path);
|
|||
|
return path;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 检查文件是否为UTF8格式
|
|||
|
*/
|
|||
|
function isUTF8(text) {
|
|||
|
var i = 0;
|
|||
|
while(i < text.length){
|
|||
|
if( (// ASCII
|
|||
|
text[i] == 0x09 ||
|
|||
|
text[i] == 0x0A ||
|
|||
|
text[i] == 0x0D ||
|
|||
|
(0x20 <= text[i] && text[i] <= 0x7E)
|
|||
|
)
|
|||
|
) {
|
|||
|
i += 1;
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
if( (// non-overlong 2-byte
|
|||
|
(0xC2 <= text[i] && text[i] <= 0xDF) &&
|
|||
|
(0x80 <= text[i+1] && text[i+1] <= 0xBF)
|
|||
|
)
|
|||
|
) {
|
|||
|
i += 2;
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
if( (// excluding overlongs
|
|||
|
text[i] == 0xE0 &&
|
|||
|
(0xA0 <= text[i + 1] && text[i + 1] <= 0xBF) &&
|
|||
|
(0x80 <= text[i + 2] && text[i + 2] <= 0xBF)
|
|||
|
) ||
|
|||
|
(// straight 3-byte
|
|||
|
((0xE1 <= text[i] && text[i] <= 0xEC) ||
|
|||
|
text[i] == 0xEE ||
|
|||
|
text[i] == 0xEF) &&
|
|||
|
(0x80 <= text[i + 1] && text[i+1] <= 0xBF) &&
|
|||
|
(0x80 <= text[i+2] && text[i+2] <= 0xBF)
|
|||
|
) ||
|
|||
|
(// excluding surrogates
|
|||
|
text[i] == 0xED &&
|
|||
|
(0x80 <= text[i+1] && text[i+1] <= 0x9F) &&
|
|||
|
(0x80 <= text[i+2] && text[i+2] <= 0xBF)
|
|||
|
)
|
|||
|
) {
|
|||
|
i += 3;
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
if( (// planes 1-3
|
|||
|
text[i] == 0xF0 &&
|
|||
|
(0x90 <= text[i + 1] && text[i + 1] <= 0xBF) &&
|
|||
|
(0x80 <= text[i + 2] && text[i + 2] <= 0xBF) &&
|
|||
|
(0x80 <= text[i + 3] && text[i + 3] <= 0xBF)
|
|||
|
) ||
|
|||
|
(// planes 4-15
|
|||
|
(0xF1 <= text[i] && text[i] <= 0xF3) &&
|
|||
|
(0x80 <= text[i + 1] && text[i + 1] <= 0xBF) &&
|
|||
|
(0x80 <= text[i + 2] && text[i + 2] <= 0xBF) &&
|
|||
|
(0x80 <= text[i + 3] && text[i + 3] <= 0xBF)
|
|||
|
) ||
|
|||
|
(// plane 16
|
|||
|
text[i] == 0xF4 &&
|
|||
|
(0x80 <= text[i + 1] && text[i + 1] <= 0x8F) &&
|
|||
|
(0x80 <= text[i + 2] && text[i + 2] <= 0xBF) &&
|
|||
|
(0x80 <= text[i + 3] && text[i + 3] <= 0xBF)
|
|||
|
)
|
|||
|
) {
|
|||
|
i += 4;
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
exports.save = save;
|
|||
|
exports.read = read;
|
|||
|
exports.readBinary = readBinary;
|
|||
|
exports.copy = copy;
|
|||
|
exports.remove = remove;
|
|||
|
exports.exists = exists;
|
|||
|
exports.search = search;
|
|||
|
exports.getDirectoryAllListing = getDirectoryAllListing;
|
|||
|
exports.getDirectoryListing = getDirectoryListing;
|
|||
|
exports.isDirectory = isDirectory;
|
|||
|
exports.isSymbolicLink = isSymbolicLink;
|
|||
|
exports.isFile = isFile;
|
|||
|
exports.searchByFunction = searchByFunction;
|
|||
|
exports.createDirectory = createDirectory;
|
|||
|
exports.getDirectory = getDirectory;
|
|||
|
exports.getExtension = getExtension;
|
|||
|
exports.getFileName = getFileName;
|
|||
|
exports.escapePath = escapePath;
|
|||
|
exports.joinPath = joinPath;
|
|||
|
exports.isUTF8 = isUTF8;
|