Java tutorial
// Copyright (C) 2014-2015 Guibing Guo // // This file is part of LibRec. // // LibRec is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // LibRec is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with LibRec. If not, see <http://www.gnu.org/licenses/>. // package net.librec.util; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.io.*; import java.net.URISyntaxException; import java.net.URL; import java.nio.channels.FileChannel; import java.nio.file.Paths; import java.util.*; import java.util.zip.CRC32; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; public class FileUtil { private static final Log LOG = LogFactory.getLog(FileUtil.class); // 1G in bytes or units public static final long ONE_KB = 1024; public static final long ONE_K = 1000; // 1M in bytes or units public static final long ONE_MB = ONE_KB * ONE_KB; public static final long ONE_M = ONE_K * ONE_K; // 1K in bytes or units public static final long ONE_GB = ONE_KB * ONE_MB; public static final long ONE_G = ONE_K * ONE_M; /* comma without consideration in the quotas, such as "boys, girls" */ public final static String comma = ",(?=([^\"]*\"[^\"]*\")*[^\"]*$)"; /** * interface for converting an entry of a map to string * * @param <K> key type * @param <V> value type */ public interface MapWriter<K, V> { String processEntry(K key, V val); } /** * Transform an input object with Type K to an output object with type T * * @param <K> type of input object * @param <T> type of output object */ public interface Converter<K, T> { T transform(K in) throws Exception; } /** * Should not be instanced */ private FileUtil() { } /** * Returns a human-readable version of the file size, where the input represents a specific number of bytes. * * @param size the number of bytes * @return a human-readable display value (includes units) */ public static String formatBytes(long size) { String display; if (size / ONE_GB > 0) { display = String.format("%.2f", (size + 0.0) / ONE_GB) + " GB"; } else if (size / ONE_MB > 0) { display = String.format("%.2f", (size + 0.0) / ONE_MB) + " MB"; } else if (size / ONE_KB > 0) { display = String.format("%.2f", (size + 0.0) / ONE_KB) + " KB"; } else { display = String.valueOf(size) + " bytes"; } return display; } /** * Returns a human-readable version of the file size. * * @param size the size of a file in units (not in bytes) * @return a human-readable display value */ public static String formatSize(long size) { String display; if (size / ONE_G > 0) { display = String.format("%.2f", (size + 0.0) / ONE_G) + " G"; } else if (size / ONE_M > 0) { display = String.format("%.2f", (size + 0.0) / ONE_M) + " M"; } else if (size / ONE_K > 0) { display = String.format("%.2f", (size + 0.0) / ONE_K) + " K"; } else { display = String.valueOf(size); } return display; } /** * Get resource path, supporting file and url io path * * @param filePath file path * @return path to the file */ public static String getResource(String filePath) { if (FileUtil.exist(filePath)) return filePath; String path = makeDirPath(new String[] { "src", "main", "resources" }) + filePath; if (FileUtil.exist(path)) return path; URL is = Class.class.getResource(filePath); if (is != null) return is.getFile(); is = Class.class.getResource(path); if (is != null) return is.getFile(); return null; } /** * Return the BufferedReader List of files in a specified directory. * * @param path The path of the specified directory or file. * Relative and absolute paths are both supported. * @return the BufferedReader List of files. * @throws IOException if I/O error occurs * @throws URISyntaxException if URI Syntax error occurs */ public static List<BufferedReader> getReader(String path) throws IOException, URISyntaxException { File file = new File(path); List<BufferedReader> readerList = new ArrayList<BufferedReader>(); boolean isRelativePath = !(path.startsWith("/") || path.indexOf(":") > 0); if (isRelativePath) { ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); if (classLoader == null) { classLoader = FileUtil.class.getClassLoader(); } URL url = classLoader.getResource(path); if (null != url) { file = new File(url.toURI()); } } if (file.isFile()) { BufferedReader reader = new BufferedReader(new FileReader(file)); readerList.add(reader); } else if (file.isDirectory()) { File[] files = file.listFiles(); for (int i = 0; i < files.length; i++) { if (files[i].isFile()) { BufferedReader reader = new BufferedReader(new FileReader(files[i])); readerList.add(reader); } } } return readerList; } /** * Get reader of a given file. * * @param file a given file * @return reader of the given file * @throws FileNotFoundException if can't find the file */ public static BufferedReader getReader(File file) throws FileNotFoundException { return new BufferedReader(new FileReader(file)); } /** * Get writer of a given path. * * @param path a given path * @return writer of the given path * @throws Exception if error occurs */ public static BufferedWriter getWriter(String path) throws Exception { return getWriter(new File(path)); } /** * Get writer of a given file. * * @param file a given file * @return writer of the given file * @throws FileNotFoundException if can't find the file */ public static BufferedWriter getWriter(File file) throws Exception { return new BufferedWriter(new FileWriter(file)); } /** * @return the name of current folder */ public static String getCurrentFolder() { return Paths.get("").toAbsolutePath().getFileName().toString(); } /** * @return the path to current folder */ public static String getCurrentPath() { return Paths.get("").toAbsolutePath().toString(); } /** * Make directory path: make sure the path is ended with file separator * * @param dirPath raw directory path * @return corrected directory path with file separator in the end */ public static String makeDirPath(String dirPath) { switch (Systems.getOs()) { case Windows: dirPath = dirPath.replace('/', '\\'); break; default: dirPath = dirPath.replace('\\', '/'); break; } if (!dirPath.endsWith(Systems.FILE_SEPARATOR)) dirPath += Systems.FILE_SEPARATOR; return dirPath; } /** * Make directory path using the names of directories. * * @param dirs names of directories * @return directory path */ public static String makeDirPath(String... dirs) { String dirPath = ""; for (String dir : dirs) dirPath += makeDirPath(dir); return dirPath; } /** * Make directory if it does not exist * * @param dirPath a given directory path * @return Directory path with file separator in the end */ public static String makeDirectory(String dirPath) { File dir = new File(dirPath); if (!dir.exists()) dir.mkdirs(); return makeDirPath(dir.getPath()); } /** * Construct directory and return directory path * * @param dirs names of directories * @return constructed directory path */ public static String makeDirectory(String... dirs) { String dirPath = makeDirPath(dirs); return makeDirectory(dirPath); } /** * Write a string into a file * * @param filePath : the name of file to be written * @param content : the content of a string to be written * @throws Exception if error occurs */ public static void writeString(String filePath, String content) throws Exception { writeString(filePath, content, false); } /** * Write a string into a file with the given path and content. * * @param filePath path of the file * @param content content to write * @param append whether append * @throws Exception if error occurs */ public static void writeString(String filePath, String content, boolean append) throws Exception { String dirPath = filePath.substring(0, filePath.lastIndexOf("/") + 1); File dir = new File(dirPath); if (!dir.exists()) { dir.mkdirs(); } BufferedWriter bw = new BufferedWriter( new OutputStreamWriter(new FileOutputStream(filePath, append), "UTF-8")); if (content.endsWith("\n")) bw.write(content); else bw.write(content + "\n"); bw.close(); } /** * Write contents in {@code Collection<T>} to a file. * * @param filePath path of the file to write * @param objs content to write * @param <T> the type parameter * @throws Exception if error occurs */ public static <T> void writeList(String filePath, Collection<T> objs) throws Exception { writeList(filePath, objs, null, false); } /** * Write contents in {@code Collection<T>} to a file. * * @param filePath path of the file to write * @param objs content to write * @param append whether to append * @param <T> the type parameter * @throws Exception if error occurs */ public static <T> void writeList(String filePath, Collection<T> objs, boolean append) throws Exception { writeList(filePath, objs, null, append); } /** * Write contents in {@code Collection<T>} to a file. * * @param filePath path of the file to write * @param objs content to write * @param <T> the type parameter * @throws Exception if error occurs */ public synchronized static <T> void writeListSyn(String filePath, List<T> objs) throws Exception { writeList(filePath, objs, null, false); } /** * Write contents in {@code Collection<T>} to a file with the help of a writer helper. * * @param filePath path of the file to write * @param ts content to write * @param lw writer helper * @param append whether to append * @param <T> the type parameter * @throws Exception if error occurs */ public static <T> void writeList(String filePath, Collection<T> ts, Converter<T, String> lw, boolean append) throws Exception { BufferedWriter bw = new BufferedWriter( new OutputStreamWriter(new FileOutputStream(filePath, append), "UTF-8")); StringBuilder contents = new StringBuilder(); int count = 0; for (T t : ts) { contents.append(lw != null ? lw.transform(t) : t); contents.append("\n"); count++; if (count >= 1000) { bw.write(contents.toString()); count = 0; contents = new StringBuilder(); } } if (contents.capacity() > 0) bw.write(contents.toString()); bw.close(); } /** * Write contents in {@code List<T>} to a file. * * @param filePath path of the file to write * @param objs content to write * @param <T> the type parameter * @throws Exception if error occurs */ public static <T> void writeVector(String filePath, List<T> objs) throws Exception { writeVector(filePath, objs, null, false); } /** * Write contents in {@code List<T>} to a file with the help of a writer helper. * * @param filePath path of the file to write * @param ts content to write * @param wh writer helper * @param append whether to append * @param <T> the type parameter * @throws Exception if error occurs */ public static <T> void writeVector(String filePath, List<T> ts, Converter<T, String> wh, boolean append) throws Exception { BufferedWriter bw = new BufferedWriter( new OutputStreamWriter(new FileOutputStream(filePath, append), "UTF-8")); int i = 0; StringBuilder sb = new StringBuilder(); for (T t : ts) { sb.append(wh.transform(t)); if (++i < ts.size()) sb.append(", "); } bw.write(sb.toString() + "\n"); bw.close(); } /** * Read the content of a file, if keywords are specified, then only lines with these keywords will be read * * @param filePath the file to be read * @param keywords the keywords of lines to be read * @return the content of a file as string * @throws Exception if error occurs */ public static String readAsString(String filePath, String... keywords) throws Exception { BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(filePath), "UTF-8")); StringBuilder sb = new StringBuilder(); String line = null; while ((line = br.readLine()) != null) { if (keywords != null && keywords.length > 0) { for (String keyword : keywords) { if (line.contains(keyword)) { sb.append(line + "\r\n"); break; } } } else sb.append(line + "\r\n"); } br.close(); return sb.toString(); } /** * Read String from file at specified line numbers, e.g. read two lines at line position 10, 100, starting from line * 1. Note that line numbers must be ordered from min to max; hence before invoke this method, use ordering method * first * * @param filePath file path * @param lines specified line numbers * @return read string * @throws Exception if error occurs during reading */ public static String readAsString(String filePath, int... lines) throws Exception { BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(filePath), "UTF-8")); StringBuilder sb = new StringBuilder(); String line = null; int count = 0; int num = 0; while ((line = br.readLine()) != null) { count++; if (count == lines[num]) { num++; sb.append(line + "\r\n"); } if (num >= lines.length) break; } br.close(); return sb.toString(); } public static String readAsString(String path) throws Exception { if (path.startsWith("http://") || path.contains("www.")) return URLReader.read(path); else return readAsString(path, new String[] {}); } /** * Read the content of a file and return it as a {@code List<String>} * * @param filePath : the file to be read * @return the content of a file in {@code java.util.List<String>} * @throws Exception if error occurs during reading */ public static List<String> readAsList(String filePath) throws Exception { return readAsList(filePath, null); } @SuppressWarnings("unchecked") public static <T> List<T> readAsList(String filePath, Converter<String, T> rh) throws FileNotFoundException, Exception { BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(filePath), "UTF-8")); List<T> contents = new ArrayList<>(); T t = null; String line = null; while ((line = br.readLine()) != null) { if (rh == null) t = (T) line; else t = rh.transform(line); if (t != null) contents.add(t); } br.close(); return contents; } public static Set<String> readAsSet(String filePath) throws FileNotFoundException, Exception { return readAsSet(filePath, null); } @SuppressWarnings("unchecked") public static <T> Set<T> readAsSet(String filePath, Converter<String, T> rh) throws FileNotFoundException, Exception { BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(filePath), "UTF-8")); Set<T> contents = new HashSet<>(); String line = null; T t = null; while ((line = br.readLine()) != null) { if (rh == null) t = (T) line; else t = rh.transform(line); if (t != null) contents.add(t); } br.close(); return contents; } public static Map<String, String> readAsMap(String filePath) throws FileNotFoundException, Exception { return readAsMap(filePath, ","); } public static Map<String, String> readAsMap(String filePath, String seperator) throws Exception { BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(filePath), "UTF-8")); Map<String, String> contents = new HashMap<>(); String line = null; while ((line = br.readLine()) != null) { String[] data = line.split(seperator); if (data.length > 1) contents.put(data[0], data[1]); } br.close(); return contents; } @SuppressWarnings("unchecked") public static <T, E> Map<T, E> readAsMap(String filePath, Converter<String, Object[]> rh) throws Exception { BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(filePath), "UTF-8")); Map<T, E> contents = new HashMap<>(); String line = null; while ((line = br.readLine()) != null) { Object[] obs = rh.transform(line); contents.put((T) obs[0], (E) obs[1]); } br.close(); return contents; } /** * read a map in the form of {@code Map<String, Double>}. * * @param filePath path of the file * @return {@code Map<String, Double>} * @throws Exception if error occurs during reading */ public static Map<String, Double> readAsIDMap(String filePath) throws Exception { return readAsIDMap(filePath, ","); } /** * read a map in the form of {@code Map<String, Double>} * * @param filePath path of the file * @param sep sep * @return {@code Map<String, Double>} * @throws Exception if error occurs during reading */ public static Map<String, Double> readAsIDMap(String filePath, String sep) throws Exception { BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(filePath), "UTF-8")); Map<String, Double> contents = new HashMap<>(); String line = null; while ((line = br.readLine()) != null) { String[] data = line.split(sep); if (data.length > 1) contents.put(data[0], new Double(data[1])); } br.close(); return contents; } public static void serialize(Object obj, String filePath) throws Exception { FileOutputStream fos = new FileOutputStream(filePath); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(obj); oos.flush(); oos.close(); fos.close(); } public static Object deserialize(String filePath) throws Exception { FileInputStream fis = new FileInputStream(filePath); ObjectInputStream ois = new ObjectInputStream(fis); Object obj = ois.readObject(); ois.close(); fis.close(); return obj; } /** * Rename files in a folder by replacing keywords * * @param dirPath the directory of files * @param regex the old string needed to be replaced, supporting regular expression * @param replacement the new string used to replace old string * @throws Exception if error occurs */ public static void renameFiles(String dirPath, String regex, String replacement) throws Exception { File dir = new File(dirPath); if (!dir.isDirectory()) throw new Exception(dirPath + " is not a directory"); File[] files = dir.listFiles(); if (files != null && files.length > 0) { for (File file : files) { renameFile(file, regex, replacement); } } } public static void renameFile(File file, String regex, String replacement) { String filename = file.getName(); filename = filename.replaceAll(regex, replacement); String path = makeDirPath(file.getPath()); file.renameTo(new File(path + filename)); } public static void copyFile(String source, String target) throws Exception { copyFile(new File(source), new File(target)); } /** * fast file copy * * @param source source file * @param target target file * @throws Exception if error occurs */ public static void copyFile(File source, File target) throws Exception { FileInputStream fis = new FileInputStream(source); FileOutputStream fos = new FileOutputStream(target); FileChannel inChannel = fis.getChannel(); FileChannel outChannel = fos.getChannel(); // inChannel.transferTo(0, inChannel.size(), outChannel); // original -- apparently has trouble copying large files on Windows // magic number for Windows, 64Mb - 32Kb int maxCount = (64 * 1024 * 1024) - (32 * 1024); long size = inChannel.size(); long position = 0; while (position < size) { position += inChannel.transferTo(position, maxCount, outChannel); } inChannel.close(); outChannel.close(); fis.close(); fos.close(); } public static void deleteFile(String source) throws Exception { new File(source).delete(); } public static void deleteDirectory(String dirPath) throws Exception { deleteDirectory(new File(dirPath)); } public static void deleteDirectory(File dir) throws Exception { cleanDirectory(dir); dir.delete(); } public static void cleanDirectory(String dirPath) throws Exception { cleanDirectory(new File(dirPath)); } public static void cleanDirectory(File dir) throws Exception { if (!dir.exists()) return; if (!dir.isDirectory()) throw new Exception("The path '" + dir.getPath() + "' is not a directory. "); File[] fs = dir.listFiles(); for (File f : fs) { if (f.isDirectory()) deleteDirectory(f.getPath()); else f.delete(); } } public static void moveFile(String source, String target) throws Exception { copyFile(source, target); deleteFile(source); } public static void moveDirectory(String sourceDir, String targetDir) throws Exception { copyDirectory(sourceDir, targetDir); deleteDirectory(sourceDir); } public static void copyDirectory(String sourceDir, String targetDir) throws Exception { File sDir = new File(sourceDir); File tDir = new File(targetDir); if (sDir.isDirectory()) { if (!tDir.exists()) tDir.mkdirs(); File[] files = sDir.listFiles(); for (File f : files) { if (f.isDirectory()) { copyDirectory(f.getPath(), tDir + Systems.FILE_SEPARATOR + f.getName() + Systems.FILE_SEPARATOR); } else { copyFile(f, new File(tDir.getPath() + Systems.FILE_SEPARATOR + f.getName())); } } } } /** * empty a file content * * @param filePath file path * @throws Exception if error occurs */ public static void empty(String filePath) throws Exception { File file = new File(filePath); if (file.exists()) file.delete(); file.createNewFile(); } /** * check whether a file exists * * @param filePath file path * @return true if the file exists */ public static boolean exist(String filePath) { return new File(filePath).exists(); } /** * list all files of a given folder * * @param dirPath a given folder * @return file list */ public static File[] listFiles(String dirPath) { File dir = new File(dirPath); if (dir.isDirectory()) return dir.listFiles(); else return new File[] { dir }; } /** * Zip a given folder * * @param dirPath a given folder: must be all files (not sub-folders) * @param filePath zipped file * @throws Exception if error occurs */ public static void zipFolder(String dirPath, String filePath) throws Exception { File outFile = new File(filePath); ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(outFile)); int bytesRead; byte[] buffer = new byte[1024]; CRC32 crc = new CRC32(); for (File file : listFiles(dirPath)) { BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file)); crc.reset(); while ((bytesRead = bis.read(buffer)) != -1) { crc.update(buffer, 0, bytesRead); } bis.close(); // Reset to beginning of input stream bis = new BufferedInputStream(new FileInputStream(file)); ZipEntry entry = new ZipEntry(file.getName()); entry.setMethod(ZipEntry.STORED); entry.setCompressedSize(file.length()); entry.setSize(file.length()); entry.setCrc(crc.getValue()); zos.putNextEntry(entry); while ((bytesRead = bis.read(buffer)) != -1) { zos.write(buffer, 0, bytesRead); } bis.close(); } zos.close(); LOG.debug("A zip-file is created to: " + outFile.getPath()); } }