/*** * 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 };