All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.alibaba.nacos.sys.utils.DiskUtils Maven / Gradle / Ivy

/*
 * Copyright 1999-2018 Alibaba Group Holding Ltd.
 *
 * 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.
 */

package com.alibaba.nacos.sys.utils;

import com.alibaba.nacos.common.utils.ByteUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.output.NullOutputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.zip.CheckedInputStream;
import java.util.zip.CheckedOutputStream;
import java.util.zip.Checksum;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

/**
 * IO operates on the utility class.
 *
 * @author liaochuntao
 */
public final class DiskUtils {
    
    private static final Logger LOGGER = LoggerFactory.getLogger(DiskUtils.class);
    
    private static final String NO_SPACE_CN = "设备上没有空间";
    
    private static final String NO_SPACE_EN = "No space left on device";
    
    private static final String DISK_QUATA_CN = "超出磁盘限额";
    
    private static final String DISK_QUATA_EN = "Disk quota exceeded";
    
    private static final Charset CHARSET = StandardCharsets.UTF_8;
    
    private static final CharsetDecoder DECODER = CHARSET.newDecoder();
    
    public static void touch(String path, String fileName) throws IOException {
        FileUtils.touch(Paths.get(path, fileName).toFile());
    }
    
    /**
     * Implements the same behaviour as the "touch" utility on Unix. It creates a new file with size 0 or, if the file
     * exists already, it is opened and closed without modifying it, but updating the file date and time.
     *
     * 

NOTE: As from v1.3, this method throws an IOException if the last * modified date of the file cannot be set. Also, as from v1.3 this method creates parent directories if they do not * exist. * * @param file the File to touch * @throws IOException If an I/O problem occurs */ public static void touch(File file) throws IOException { FileUtils.touch(file); } /** * Creates a new empty file in the specified directory, using the given prefix and suffix strings to generate its * name. The resulting {@code Path} is associated with the same {@code FileSystem} as the given directory. * *

The details as to how the name of the file is constructed is * implementation dependent and therefore not specified. Where possible the {@code prefix} and {@code suffix} are * used to construct candidate names in the same manner as the {@link java.io.File#createTempFile(String, String, * File)} method. * * @param dir the path to directory in which to create the file * @param prefix the prefix string to be used in generating the file's name; may be {@code null} * @param suffix the suffix string to be used in generating the file's name; may be {@code null}, in which case * "{@code .tmp}" is used * @return the path to the newly created file that did not exist before this method was invoked * @throws IllegalArgumentException if the prefix or suffix parameters cannot be used to generate a candidate * file name * @throws UnsupportedOperationException if the array contains an attribute that cannot be set atomically when * creating the directory * @throws IOException if an I/O error occurs or {@code dir} does not exist * @throws SecurityException In the case of the default provider, and a security manager is installed, * the {@link SecurityManager#checkWrite(String) checkWrite} method is invoked * to check write access to the file. */ public static File createTmpFile(String dir, String prefix, String suffix) throws IOException { return Files.createTempFile(Paths.get(dir), prefix, suffix).toFile(); } /** * Creates an empty file in the default temporary-file directory, using the given prefix and suffix to generate its * name. The resulting {@code Path} is associated with the default {@code FileSystem}. * * @param prefix the prefix string to be used in generating the file's name; may be {@code null} * @param suffix the suffix string to be used in generating the file's name; may be {@code null}, in which case * "{@code .tmp}" is used * @return the path to the newly created file that did not exist before this method was invoked * @throws IllegalArgumentException if the prefix or suffix parameters cannot be used to generate a candidate * file name * @throws UnsupportedOperationException if the array contains an attribute that cannot be set atomically when * creating the directory * @throws IOException if an I/O error occurs or the temporary-file directory does not exist * @throws SecurityException In the case of the default provider, and a security manager is installed, * the {@link SecurityManager#checkWrite(String) checkWrite} method is invoked * to check write access to the file. */ public static File createTmpFile(String prefix, String suffix) throws IOException { return Files.createTempFile(prefix, suffix).toFile(); } /** * read file which under the path. * * @param path directory * @param fileName filename * @return content */ public static String readFile(String path, String fileName) { File file = openFile(path, fileName); if (file.exists()) { return readFile(file); } return null; } /** * read file content by {@link InputStream}. * * @param is {@link InputStream} * @return content */ public static String readFile(InputStream is) { try (BufferedReader reader = new BufferedReader(new InputStreamReader(is))) { StringBuilder textBuilder = new StringBuilder(); String lineTxt = null; while ((lineTxt = reader.readLine()) != null) { textBuilder.append(lineTxt); } return textBuilder.toString(); } catch (IOException e) { return null; } } /** * read this file content. * * @param file {@link File} * @return content */ public static String readFile(File file) { try (FileChannel fileChannel = new FileInputStream(file).getChannel()) { StringBuilder text = new StringBuilder(); ByteBuffer buffer = ByteBuffer.allocate(4096); CharBuffer charBuffer = CharBuffer.allocate(4096); while (fileChannel.read(buffer) != -1) { buffer.flip(); DECODER.decode(buffer, charBuffer, false); charBuffer.flip(); while (charBuffer.hasRemaining()) { text.append(charBuffer.get()); } buffer.clear(); charBuffer.clear(); } return text.toString(); } catch (IOException e) { return null; } } /** * read this file content then return bytes. * * @param file {@link File} * @return content bytes */ public static byte[] readFileBytes(File file) { if (file.exists()) { String result = readFile(file); if (result != null) { return ByteUtils.toBytes(result); } } return null; } public static byte[] readFileBytes(String path, String fileName) { File file = openFile(path, fileName); return readFileBytes(file); } /** * Writes the contents to the target file. * * @param file target file * @param content content * @param append write append mode * @return write success */ public static boolean writeFile(File file, byte[] content, boolean append) { try (FileChannel fileChannel = new FileOutputStream(file, append).getChannel()) { ByteBuffer buffer = ByteBuffer.wrap(content); fileChannel.write(buffer); return true; } catch (IOException ioe) { if (ioe.getMessage() != null) { String errMsg = ioe.getMessage(); if (NO_SPACE_CN.equals(errMsg) || NO_SPACE_EN.equals(errMsg) || errMsg.contains(DISK_QUATA_CN) || errMsg .contains(DISK_QUATA_EN)) { LOGGER.warn("磁盘满,自杀退出"); System.exit(0); } } } return false; } public static void deleteQuietly(File file) { Objects.requireNonNull(file, "file"); FileUtils.deleteQuietly(file); } public static void deleteQuietly(Path path) { Objects.requireNonNull(path, "path"); FileUtils.deleteQuietly(path.toFile()); } /** * delete target file. * * @param path directory * @param fileName filename * @return delete success */ public static boolean deleteFile(String path, String fileName) { File file = Paths.get(path, fileName).toFile(); if (file.exists()) { return file.delete(); } return false; } public static void deleteDirectory(String path) throws IOException { FileUtils.deleteDirectory(new File(path)); } public static void forceMkdir(String path) throws IOException { FileUtils.forceMkdir(new File(path)); } public static void forceMkdir(File file) throws IOException { FileUtils.forceMkdir(file); } public static void deleteDirThenMkdir(String path) throws IOException { deleteDirectory(path); forceMkdir(path); } public static void copyDirectory(File srcDir, File destDir) throws IOException { FileUtils.copyDirectory(srcDir, destDir); } public static void copyFile(File src, File target) throws IOException { FileUtils.copyFile(src, target); } public static File openFile(String path, String fileName) { return openFile(path, fileName, false); } /** * open file. * * @param path directory * @param fileName filename * @param rewrite if rewrite is true, will delete old file and create new one * @return {@link File} */ public static File openFile(String path, String fileName, boolean rewrite) { File directory = new File(path); boolean mkdirs = true; if (!directory.exists()) { mkdirs = directory.mkdirs(); } if (!mkdirs) { LOGGER.error("[DiskUtils] can't create directory"); return null; } File file = new File(path, fileName); try { boolean create = true; if (!file.exists()) { file.createNewFile(); } if (file.exists()) { if (rewrite) { file.delete(); } else { create = false; } } if (create) { file.createNewFile(); } } catch (IOException e) { throw new RuntimeException(e); } return file; } // copy from sofa-jraft /** * Compress a folder in a directory. * * @param rootDir directory * @param sourceDir folder * @param outputFile output file * @param checksum checksum * @throws IOException IOException */ public static void compress(final String rootDir, final String sourceDir, final String outputFile, final Checksum checksum) throws IOException { try (final FileOutputStream fos = new FileOutputStream(outputFile); final CheckedOutputStream cos = new CheckedOutputStream(fos, checksum); final ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(cos))) { compressDirectoryToZipFile(rootDir, sourceDir, zos); zos.flush(); fos.getFD().sync(); } } // copy from sofa-jraft private static void compressDirectoryToZipFile(final String rootDir, final String sourceDir, final ZipOutputStream zos) throws IOException { final String dir = Paths.get(rootDir, sourceDir).toString(); final File[] files = Objects.requireNonNull(new File(dir).listFiles(), "files"); for (final File file : files) { final String child = Paths.get(sourceDir, file.getName()).toString(); if (file.isDirectory()) { compressDirectoryToZipFile(rootDir, child, zos); } else { try (final FileInputStream fis = new FileInputStream(file); final BufferedInputStream bis = new BufferedInputStream(fis)) { compressIntoZipFile(child, bis, zos); } } } } /** * Compress an input stream to zip file. * * @param childName child name in zip file * @param inputStream input stream needed compress * @param outputFile output file * @param checksum check sum * @throws IOException IOException during compress */ public static void compressIntoZipFile(final String childName, final InputStream inputStream, final String outputFile, final Checksum checksum) throws IOException { try (final FileOutputStream fileOutputStream = new FileOutputStream(outputFile); final CheckedOutputStream checkedOutputStream = new CheckedOutputStream(fileOutputStream, checksum); final ZipOutputStream zipStream = new ZipOutputStream(new BufferedOutputStream(checkedOutputStream))) { compressIntoZipFile(childName, inputStream, zipStream); zipStream.flush(); fileOutputStream.getFD().sync(); } } private static void compressIntoZipFile(final String childName, final InputStream inputStream, final ZipOutputStream zipOutputStream) throws IOException { zipOutputStream.putNextEntry(new ZipEntry(childName)); IOUtils.copy(inputStream, zipOutputStream); } // copy from sofa-jraft /** * Unzip the target file to the specified folder. * * @param sourceFile target file * @param outputDir specified folder * @param checksum checksum * @throws IOException IOException */ public static void decompress(final String sourceFile, final String outputDir, final Checksum checksum) throws IOException { try (final FileInputStream fis = new FileInputStream(sourceFile); final CheckedInputStream cis = new CheckedInputStream(fis, checksum); final ZipInputStream zis = new ZipInputStream(new BufferedInputStream(cis))) { ZipEntry entry; while ((entry = zis.getNextEntry()) != null) { final String fileName = entry.getName(); final File entryFile = new File(Paths.get(outputDir, fileName).toString()); FileUtils.forceMkdir(entryFile.getParentFile()); try (final FileOutputStream fos = new FileOutputStream(entryFile); final BufferedOutputStream bos = new BufferedOutputStream(fos)) { IOUtils.copy(zis, bos); bos.flush(); fos.getFD().sync(); } } // Continue to read all remaining bytes(extra metadata of ZipEntry) directly from the checked stream, // Otherwise, the checksum value maybe unexpected. // // See https://coderanch.com/t/279175/java/ZipInputStream IOUtils.copy(cis, NullOutputStream.NULL_OUTPUT_STREAM); } } /** * Unzip the target file to byte array. * * @param sourceFile target file * @param checksum checksum * @return decompress byte array * @throws IOException IOException during decompress */ public static byte[] decompress(final String sourceFile, final Checksum checksum) throws IOException { byte[] result; try (final FileInputStream fis = new FileInputStream(sourceFile); final CheckedInputStream cis = new CheckedInputStream(fis, checksum); final ZipInputStream zis = new ZipInputStream(new BufferedInputStream(cis)); final ByteArrayOutputStream bos = new ByteArrayOutputStream(1024)) { while (zis.getNextEntry() != null) { IOUtils.copy(zis, bos); bos.flush(); } IOUtils.copy(cis, NullOutputStream.NULL_OUTPUT_STREAM); result = bos.toByteArray(); } return result; } /** * Returns an Iterator for the lines in a File. *

* This method opens an InputStream for the file. When you have finished with the iterator you should * close the stream to free internal resources. This can be done by calling the {@link * org.apache.commons.io.LineIterator#close()} or {@link org.apache.commons.io.LineIterator#closeQuietly(org.apache.commons.io.LineIterator)} * method. *

* The recommended usage pattern is: *
     * LineIterator it = FileUtils.lineIterator(file, "UTF-8");
     * try {
     *   while (it.hasNext()) {
     *     String line = it.nextLine();
     *     /// do something with line
     *   }
     * } finally {
     *   LineIterator.closeQuietly(iterator);
     * }
     * 
*

* If an exception occurs during the creation of the iterator, the underlying stream is closed. *

* * @param file the file to open for input, must not be null * @param encoding the encoding to use, null means platform default * @return an Iterator of the lines in the file, never null * @throws IOException in case of an I/O error (file closed) * @since 1.2 */ public static LineIterator lineIterator(File file, String encoding) throws IOException { return new LineIterator(FileUtils.lineIterator(file, encoding)); } /** * Returns an Iterator for the lines in a File using the default encoding for the VM. * * @param file the file to open for input, must not be null * @return an Iterator of the lines in the file, never null * @throws IOException in case of an I/O error (file closed) * @see #lineIterator(File, String) * @since 1.3 */ public static LineIterator lineIterator(File file) throws IOException { return new LineIterator(FileUtils.lineIterator(file, null)); } public static class LineIterator implements AutoCloseable { private final org.apache.commons.io.LineIterator target; /** * Constructs an iterator of the lines for a Reader. * * @param target {@link org.apache.commons.io.LineIterator} */ LineIterator(org.apache.commons.io.LineIterator target) { this.target = target; } public boolean hasNext() { return target.hasNext(); } public String next() { return target.next(); } public String nextLine() { return target.nextLine(); } @Override public void close() throws IOException { target.close(); } public void remove() { target.remove(); } public void forEachRemaining(Consumer action) { target.forEachRemaining(action); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy