/***
* Copyright 2015 RAPP
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Authors: Konstantinos Panayiotou
* Contact: klpanagi@gmail.com
*
*/
/**
* @module
*
* @description Useful functionalities, while working with file system.
*
* @author Konstantinos Panayiotou <klpanagi@gmail.com>
* @copyright Rapp Project EU 2015
*/
var fs = require('fs');
var path = require('path');
/**
* Resolve a "might-be" relative path to system's absolute path.
*
* @param {String} _path Path to be resolved to absolute.
* @returns {String} - absolute path.
*/
function resolvePath(_path) {
var regexp = /~/g;
var newPath = '';
if (_path.match(regexp)) {
var home = process.env.HOME;
/*<Replaces "~" with "/home/user">*/
newPath = _path.replace(regexp, home);
}
else {
newPath = path.resolve(_path);
}
return newPath;
}
/**
* Node.js readFileSync function wrapper
*
* @function readFileSync
*
* @param _file File to be read, specified by path.
* @param _encoding Encoding type of returned data readen from the specified
* file. Can be one of the following:
* "buffer" OR undefined Raw data from buffer.</li>
* "string/ascii" Ascii encoded string. </li>
* "string/binary" Binary encoded string. </li>
*
* @returns {Object} file - Custom file object.
* @returns {String} file.data - Data payload.
* @returns {String} file.encoding - Data encoding.
* @returns {String} file.basename - File basename.
* @returns {String} file.absolutePaht - File absolute system path.
* @returns {Object} file.size - File size. Has the following parameters:
* <ul>
* <li> bytes </li>
* <li> kilobytes </li>
* </ul>
*/
function readFileSync(_fileUrl, _encoding) {
var file = {
data: undefined,
encoding: undefined,
basename: undefined,
absolutePath: undefined,
size: {
bytes: undefined,
}
};
var fileAbsPath = resolvePath(_fileUrl);
if (fs.existsSync(fileAbsPath)) {
file.absolutePath = fileAbsPath;
file.basename = path.basename( fileAbsPath );
var dataBuffer = fs.readFileSync( fileAbsPath );
file.size.bytes = dataBuffer.length;
encoding = _encoding || "none";
switch (encoding) {
case "buffer":
file.data = dataBuffer;
file.encoding = "raw";
break;
case "ascii":
file.data = dataBuffer.toString( 'ascii' );
file.encoding = "ascii";
break;
case "string/utf8":
file.data = dataBuffer.toString( 'utf8' );
file.encoding = "utf8";
break;
case "string/binary":
var str = dataBuffer.toString( 'binary' );
file.data = str;
file.encoding = "binary";
break;
case "none":
file.data = dataBuffer;
file.encoding = "raw";
break;
default:
}
return file;
}
else {
return 0;
}
}
/**
* Node.js writeFileSync method wrapper
*
* @function writeFileSync
*
* @param _dest Destination file name to write the data, specified by path.
* @param _data Data to be written.
*
* @returns {boolean} - Success index on this operation.
*/
function writeFileSync(_destUrl, _data)
{
var path = resolvePath(_destUrl);
try{
fs.writeFileSync( path, _data );
}
catch(e){
console.log(e);
return false;
}
var filesize = fileSize(path);
return true;
}
/**
* Creates directory non-recursively
*
* @param {String} dirPath - Directory system path.
*
* @returns {boolean} - Success index on this operation.
*/
function createDir(dirPath) {
var dir = resolvePath(dirPath);
if (fs.existsSync(dir)) {
return true;
}
try{
fs.mkdirSync(dir);
}
catch(e){
return false;
}
return true;
}
/**
* Create directory recursively --> a/b/c/d
*
* @function createDirRecur
*
* @param {String} dirPath - Directory system path.
*/
function createDirRecur(dirPath) {
dirPath = resolvePath(dirPath);
if (fs.existsSync(dirPath)) {
return true;
}
if (createDir(dirPath) === false) {
// Create all the parents recursively
createDirRecur(path.dirname(dirPath));
// Then create the child directory
createDirRecur(dirPath);
}
return true;
}
/**
* @brief Remove local file given by system path. Synchronous.
*
* @function rmFileSync
*
* @param {String} filepath - The file system path
*/
function rmFileSync(filepath) {
var _filepath = resolvePath(filepath);
if (fs.existsSync(_filepath) && isFile(_filepath)) {
fs.unlinkSync(_filepath);
return true;
}
else {
return false;
}
}
/**
* @brief Remove local file given by system path. Asynchronous.
*
* @function rmFile
*
* @param {String} filepath - The file system path
*/
function rmFile(filepath) {
var _filepath = resolvePath(filepath);
fs.exists(_filepath, function(exists) {
if (exists) {
fs.unlink(_filepath, function(e) {
if (e) {
console.log(e);
}
});
}
});
}
/**
* brief Reads the contents of a given directory path.
*
* @function lsSync
*
* @param {String} _dir - Directory path.
* Works both with relative and absolute paths.
*
* @returns {Array} - Array that holds the contents of the directory.
*/
function lsSync(_dir) {
var fileList = [];
var dir = resolvePath(_dir);
var files = fs.readdirSync(dir);
for(var i in files) {
var fullPath = dir + '/' + files[i];
if (fs.statSync(fullPath).isDirectory()) {
continue;
}
else {
fileList.push(files[i]);
}
}
return fileList;
}
/**
* Writes ascii encoded strings in a give file.
* DEPRECATED!!!
*
* @function text2File
*
* @param {String|Buffer}_data - Data to be written. Can be both a buffer or string.
* @param {String} _filePath - Destination file path.
* @return Undefined.
*/
function text2File (_data, _filePath) {
var data = null;
if (Buffer.isBuffer(_data)) {
data = _data;
}
else if (typeof _data == 'string') {
data = new Buffer( _data.length );
data.write( _data );
}
else {
return false;
}
var fd = fs.openSync(_filePath, 'w');
var numBytes = fs.writeSync(fd, data, 0, data.length, null);
fs.close(fd);
}
/**
* Append a text into new line into destination file.
*
* @function appendLine
*
* @param {String} str - Text string to append to file.
* @param {String} dest - Destination file path.
*
* @returns {boolean} - Success index on appendLine operation
*/
function appendLine(str, dest) {
var destPath = resolvePath(dest);
try {
fs.appendFileSync(destPath, str + '\n');
return true;
}
catch(e) {
return false;
}
}
/**
* Getting File Size without Reading Entire File.
*
* @function fileSize
*
* @param {String} _fileURL File System Url.
*
* @return {number} - Size of the file in bytes.
*/
function fileSize(_filePath) {
var _path = resolvePath(_filePath);
var stats = fs.statSync(_path);
var filesize_bytes = stats.size;
return filesize_bytes;
}
/**
* Rename file. Can also be used as a funcitonality to copy files.
*
* @function renameFile
*
* @param fileOld Source file path.
* @param fileNew Destination file path.
*
* @returns {boolean} - Success index of the rename-file operation.
* True if file was succesfully renamed, false otherwise.
*/
function renameFile(file, dest) {
var sourcePath = resolvePath(file);
var destPath = resolvePath(dest);
var destDir = parentDir(destPath);
// If source file and destination file match then do not proceed.
if (sourcePath == destPath) {
return true;
}
// If parent directory of given destination file does not exist,
// return false immediately.
if (destDir === false || fs.existsSync(destDir) === false ||
(! isFile(sourcePath)) ) {
return false;
}
// Check if source file exists and destination directory also exists.
if (fs.existsSync(sourcePath)) {
try {
fs.renameSync(sourcePath, destPath);
//copyFile(sourcePath, destPath);
//rmFile(sourcePath);
}
catch(e) {
return false;
}
return true;
}
else {
// If source file does not exist return false.
return false;
}
}
/**
* Copies file from-To. Uses read/write streams and pipes.
*
* @function copyFile.
*
* @param file File (given with either relative or absolute path to copy
* @param dest Destination to copy the file.
*
* @returns {boolean} - Success index of the copy-file operation.
* True if file was succesfully copied, false otherwise.
*/
function copyFile(file, dest) {
var sourcePath = resolvePath(file);
var destPath = resolvePath(dest);
var destDir = parentDir(destPath);
// If source file and destination file match then do not proceed.
if (sourcePath == destPath) {
return true;
}
// If parent directory of given destination file does not exist,
// return false immediately.
if (destDir === false || fs.existsSync(destDir) === false) {
return false;
}
// Check if source file exists and destination directory also exists.
if (fs.existsSync(sourcePath)) {
try {
//fs.createReadStream(sourcePath).pipe(fs.createWriteStream(destPath));
fs.writeFileSync(destPath, fs.readFileSync(sourcePath));
}
catch(e) {
return false;
}
return true;
}
else {
// If source file does not exist return false.
return false;
}
}
/**
* Returns the parent directory name of a path.
*
* @function parentDir
*
* @param {String} _path - System path.
*
* @return {String} - The parent directory. In case of error a zero 0 value
* will be returned.
*/
function parentDir(_path) {
var absPath = resolvePath(_path);
var _parentDir = '';
try {
_parentDir = path.dirname(absPath);
}
catch(e) {
return false;
}
return _parentDir;
}
/**
* Check if a path is a directory
*
* @function isDirectory
*
* @param {String} _path - System path.
*
* @returns {boolean} - True if is directory, false otherwise.
*/
function isDirectory(_path) {
var dirPath = resolvePath(_path);
var isDir = false;
if (fs.existsSync(_path)) {
isDir = fs.lstatSync(_path).isDirectory();
}
return isDir;
}
/**
* Check if a path is a file.
*
* @param {String} _path - System path.
* @returns {boolean} - True if is directory, false otherwise.
*/
function isFile(_path) {
var filePath = resolvePath(_path);
var isFile = false;
if (fs.existsSync(_path)) {
isFile = fs.lstatSync(_path).isFile();
}
return isFile;
}
function readTextFile(filepath, encoding) {
// Encoding is set to utf8 by default
encoding = encoding || 'utf8';
if (! filepath) {
throw new Error("Not a filepath provided");
}
filepath = resolvePath(filepath);
var text = '';
try {
text = fs.readFileSync(filepath, encoding);
}
catch(e) {
throw new Error(e);
}
return text;
}
module.exports = {
resolvePath: resolvePath,
readFileSync: readFileSync,
writeFileSync: writeFileSync,
rmFile: rmFile,
lsSync: lsSync,
text2File: text2File,
appendLine: appendLine,
fileSize: fileSize,
renameFile: renameFile,
createDir: createDir,
createDirRecur: createDirRecur,
copyFile: copyFile,
parentDir: parentDir,
isDirectory: isDirectory,
isFile: isFile,
readTextFile: readTextFile
};