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

org.apache.jena.atlas.io.IOX Maven / Gradle / Ivy

There is a newer version: 5.2.0
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.jena.atlas.io;

import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileAttribute;
import java.util.function.Function;

import org.apache.jena.atlas.RuntimeIOException;
import org.apache.jena.atlas.logging.FmtLog;

public class IOX {

    public static final Path currentDirectory = Path.of(".");

    /** A Consumer that can throw {@link IOException}. */
    @FunctionalInterface
    public interface IOConsumer {
        void actionEx(X arg) throws IOException;
    }

    /**
     * Convert an {@link IOException} into a {@link RuntimeIOException}.
     * 

* Idiom: * *

     *     catch(IOException ex) { throw new exception(ex); }
     * 
* * @param ioException * @return RuntimeIOException */ public static RuntimeIOException exception(IOException ioException) { return new RuntimeIOException(ioException); } /** * Convert an {@link IOException} into a {@link RuntimeIOException}. *

* Idiom: * *

     *     catch(IOException ex) { throw new exception("Oh dear", ex); }
     * 
* * @param message * @param ioException * @return RuntimeIOException */ public static RuntimeIOException exception(String message, IOException ioException) { return new RuntimeIOException(message, ioException); } /** Run I/O code */ @FunctionalInterface public interface ActionIO { void run() throws IOException; } /** * Run an action, converting an {@link IOException} into a * {@link RuntimeIOException}. *

* Idiom: * *

     *     run(()->...));
     * 
*/ public static void run(ActionIO action) { try { action.run(); } catch (IOException e) { throw exception(e); } } /** * Write a file safely - the change happens (the function returns true) or * something went wrong (the function throws a runtime exception) and the file is * not changed. */ public static boolean safeWrite(Path file, IOConsumer writerAction) { Path tmp = createTempFile(file.toAbsolutePath().getParent(), file.getFileName().toString(), ".tmp"); return safeWrite(file, tmp, writerAction); } /** * Write a file safely - the change happens (the function returns true) or * something went wrong (the function throws a runtime exception) and the file is * not changed. Note that the tmpfile must be in the same directory as the actual * file so an OS-atomic rename can be done. */ public static boolean safeWrite(Path file, Path tmpFile, IOConsumer writerAction) { try { try (OutputStream out = new BufferedOutputStream(Files.newOutputStream(tmpFile))) { writerAction.actionEx(out); } move(tmpFile, file); return true; } catch (IOException ex) { throw IOX.exception(ex); } } /** * Write a file safely, but allow system to use copy-delete if the chnage can not * be done atomically. Prefer {@link #safeWrite} which requires an atomic move. */ public static boolean safeWriteOrCopy(Path file, Path tmpFile, IOConsumer writerAction) { try { try (OutputStream out = new BufferedOutputStream(Files.newOutputStream(tmpFile))) { writerAction.actionEx(out); } moveAllowCopy(tmpFile, file); return true; } catch (IOException ex) { throw IOX.exception(ex); } } /** Delete a file. */ public static void delete(Path path) { try { Files.delete(path); } catch (IOException ex) { FmtLog.error(IOX.class, ex, "IOException deleting %s", path); throw IOX.exception(ex); } } /** Atomically move a file. */ public static void move(Path src, Path dst) { try { Files.move(src, dst, StandardCopyOption.ATOMIC_MOVE); } catch (IOException ex) { FmtLog.error(IOX.class, ex, "IOException moving %s to %s", src, dst); throw IOX.exception(ex); } } /** * Move a file, allowing the system to copy-delete it if it can not be moved * atomically. */ public static void moveAllowCopy(Path src, Path dst) { try { Files.move(src, dst); } catch (IOException ex) { FmtLog.error(IOX.class, ex, "IOException moving %s to %s", src, dst); throw IOX.exception(ex); } } public static void deleteAll(String start) { deleteAll(Paths.get(start)); } /** * Delete everything from a {@code Path} start point, including the path itself. * Works on files or directories. Walks down the tree and deletes directories on * the way backup. */ public static void deleteAll(Path start) { if ( !Files.exists(start) ) return; try { Files.walkFileTree(start, new SimpleFileVisitor() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { Files.delete(file); return FileVisitResult.CONTINUE; } @Override public FileVisitResult postVisitDirectory(Path dir, IOException e) throws IOException { if ( e == null ) { Files.delete(dir); return FileVisitResult.CONTINUE; } else { throw e; } } }); } catch (IOException ex) { throw IOX.exception(ex); } } /** * Copy a file, not atomic. * Can copy to a directory or over an existing file. * * @param srcFilename * @param dstFilename */ public static void copy(String srcFilename, String dstFilename) { Path src = Path.of(srcFilename); if ( !Files.exists(src) ) throw new RuntimeIOException("No such file: " + srcFilename); Path dst = Path.of(dstFilename); if ( Files.isDirectory(dst) ) dst = dst.resolve(src.getFileName()); try { Files.copy(src, dst); } catch (IOException ex) { FmtLog.error(IOX.class, ex, "IOException copying %s to %s", srcFilename, dstFilename); throw IOX.exception(ex); } } /** * Create a directory - throw a runtime exception if there are any problems. This * function wraps {@code Files.createDirectory}. */ public static void createDirectory(Path dir) { try { Files.createDirectory(dir); } catch (IOException ex) { throw IOX.exception(ex); } } /** Read the whole of a file */ public static byte[] readAll(Path pathname) { try { return Files.readAllBytes(pathname); } catch (IOException ex) { throw IOX.exception(ex); } } /** Write the whole of a file */ public static void writeAll(Path pathname, byte[] value) { try { Files.write(pathname, value, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE); } catch (IOException ex) { throw IOX.exception(ex); } } // /** // * Ensure a directory exists, creating the directory and any missing // * directories on the path to it. // */ // public static void ensureDirectory(Path dir, FileAttribute... attrs) { // if ( Files.exists(dir) ) { // if ( ! Files.isDirectory(dir) ) // throw new DeltaFileException("Exists but not a directory: "+dir); // } // try { Files.createDirectories(dir, attrs); } // catch (IOException ex) { new DeltaFileException("Failed to create directory: // "+dir, ex);} // } // // /** // * Ensure a file exists - create an empty one if not. This operation does // * not create a directory path to the file. // */ // public static void ensureFile(Path filePath, FileAttribute... attrs) { // if ( Files.exists(filePath) ) { // if ( ! Files.isRegularFile(filePath) ) // throw new DeltaFileException("Exists but not a regular file: "+filePath); // } // try { Files.createFile(filePath); } // catch (IOException ex) { new DeltaFileException("Failed to create file: // "+filePath, ex);} // } /** * Return a temporary filename path. *

* This operation is thread-safe. */ public static Path createTempFile(Path dir, String prefix, String suffix, FileAttribute...attrs) { try { return Files.createTempFile(dir, prefix, suffix, attrs); } catch (IOException ex) { throw IOX.exception(ex); } } /** * Generate a unique place related to path; Optionally, provide a mapping of old * name to new namebase. This method always adds "-1", "-2" etc. */ public static Path uniqueDerivedPath(Path path, Function basenameMapping) { String base = path.getFileName().toString(); if ( basenameMapping != null ) base = basenameMapping.apply(base); // Some large limit "just in case" for ( int x = 0 ; x < 10_000 ; x++ ) { String destname = base + "-" + x; Path destpath = path.resolveSibling(destname); if ( !Files.exists(destpath) ) return destpath; } return null; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy