-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added Directory and RegularFile facades for convenient file operations.
- Loading branch information
Showing
10 changed files
with
670 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
25 changes: 25 additions & 0 deletions
25
lis-commons-io/src/main/java/com/link_intersystems/io/IOConsumer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package com.link_intersystems.io; | ||
|
||
import java.io.IOException; | ||
|
||
/** | ||
* An {@link java.util.function.Consumer} like interface for I/O related stuff. | ||
* | ||
* @param <T> an I/O type that might raise an {@link IOException}. | ||
*/ | ||
@FunctionalInterface | ||
public interface IOConsumer<T> { | ||
|
||
/** | ||
* An {@link IOConsumer} that does nothing (<b>no</b> <b>op</b>eration). | ||
* | ||
* @param <T> | ||
* @return | ||
*/ | ||
public static <T> IOConsumer<T> noop() { | ||
return t -> { | ||
}; | ||
} | ||
|
||
public void accept(T t) throws IOException; | ||
} |
54 changes: 54 additions & 0 deletions
54
lis-commons-io/src/main/java/com/link_intersystems/io/file/AbstractFile.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package com.link_intersystems.io.file; | ||
|
||
import java.io.IOException; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.util.Objects; | ||
|
||
import static java.util.Objects.requireNonNull; | ||
|
||
public abstract class AbstractFile { | ||
|
||
private Path path; | ||
|
||
protected AbstractFile(Path path) { | ||
this.path = requireNonNull(path); | ||
} | ||
|
||
/** | ||
* @return the {@link Path} of this {@link AbstractFile}. | ||
*/ | ||
public Path getPath() { | ||
return path; | ||
} | ||
|
||
/** | ||
* Creates this file. This method does nothing, if the file already exists. | ||
* | ||
* @throws IOException | ||
*/ | ||
public abstract void create() throws IOException; | ||
|
||
/** | ||
* @return the parent file of this file if any or <code>null</code>. | ||
* @throws IOException | ||
*/ | ||
public abstract AbstractFile getParent(); | ||
|
||
public boolean exists() { | ||
return Files.exists(getPath()); | ||
} | ||
|
||
@Override | ||
public boolean equals(Object o) { | ||
if (this == o) return true; | ||
if (o == null || getClass() != o.getClass()) return false; | ||
AbstractFile that = (AbstractFile) o; | ||
return Objects.equals(getPath(), that.getPath()); | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return Objects.hash(getPath()); | ||
} | ||
} |
117 changes: 117 additions & 0 deletions
117
lis-commons-io/src/main/java/com/link_intersystems/io/file/Directory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
package com.link_intersystems.io.file; | ||
|
||
import com.link_intersystems.io.IOConsumer; | ||
|
||
import java.io.File; | ||
import java.io.IOException; | ||
import java.nio.file.DirectoryStream; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.nio.file.Paths; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
public class Directory extends AbstractFile { | ||
|
||
/** | ||
* Creates a {@link Directory} based on the given {@link File}. | ||
*/ | ||
public Directory(File dir) { | ||
this(dir.toPath()); | ||
} | ||
|
||
/** | ||
* Creates a {@link Directory} based on the given dirpath. | ||
* | ||
* @param dirpath the path of this {@link Directory}. | ||
*/ | ||
public Directory(Path dirpath) { | ||
super(dirpath); | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
* <p> | ||
* If this directory does not exist, all parent directories that also do not exist | ||
* will be created as well. | ||
* | ||
* @throws IOException | ||
*/ | ||
@Override | ||
public void create() throws IOException { | ||
Files.createDirectories(getPath()); | ||
} | ||
|
||
@Override | ||
public Directory getParent() { | ||
Path parent = getPath().getParent(); | ||
|
||
if (parent != null) { | ||
return new Directory(parent); | ||
} | ||
|
||
return null; | ||
} | ||
|
||
/** | ||
* @param directoryRelativePath | ||
* @return the {@link RegularFile} of the given path relative to this directory. | ||
* @throws IOException | ||
*/ | ||
public RegularFile file(String directoryRelativePath) throws IOException { | ||
return file(Paths.get(directoryRelativePath)); | ||
} | ||
|
||
/** | ||
* @param directoryRelativePath | ||
* @return the {@link RegularFile} of the given path relative to this directory. | ||
* @throws IOException | ||
*/ | ||
public RegularFile file(Path directoryRelativePath) throws IOException { | ||
return new RegularFile(getPath().resolve(directoryRelativePath)); | ||
} | ||
|
||
/** | ||
* @return all regular files in this directory. | ||
* @throws IOException | ||
*/ | ||
public List<RegularFile> listFiles() throws IOException { | ||
return listFiles(path -> true); | ||
} | ||
|
||
/** | ||
* @return all regular files in this directory that match the given file filter. | ||
* @throws IOException | ||
*/ | ||
public List<RegularFile> listFiles(DirectoryStream.Filter<Path> fileFilter) throws IOException { | ||
List<RegularFile> files = new ArrayList<>(); | ||
forEachFiles(files::add, fileFilter); | ||
return files; | ||
} | ||
|
||
/** | ||
* Invokes the given {@link IOConsumer} for each {@link RegularFile} in this directory. | ||
* | ||
* @throws IOException | ||
*/ | ||
public void forEachFiles(IOConsumer<RegularFile> fileConsumer) throws IOException { | ||
forEachFiles(fileConsumer, path -> true); | ||
} | ||
|
||
/** | ||
* Invokes the given {@link IOConsumer} for each {@link RegularFile} in this directory | ||
* that match the given file filter. | ||
* | ||
* @throws IOException | ||
*/ | ||
public void forEachFiles(IOConsumer<RegularFile> fileConsumer, DirectoryStream.Filter<Path> fileFilter) throws IOException { | ||
DirectoryStream.Filter<Path> filter = path -> Files.isRegularFile(path) && fileFilter.accept(path); | ||
|
||
try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(getPath(), filter)) { | ||
for (Path path : directoryStream) { | ||
RegularFile regularFile = new RegularFile(path); | ||
fileConsumer.accept(regularFile); | ||
} | ||
} | ||
} | ||
} |
131 changes: 131 additions & 0 deletions
131
lis-commons-io/src/main/java/com/link_intersystems/io/file/RegularFile.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
package com.link_intersystems.io.file; | ||
|
||
import com.link_intersystems.io.IOConsumer; | ||
|
||
import java.io.File; | ||
import java.io.IOException; | ||
import java.io.OutputStreamWriter; | ||
import java.io.PrintWriter; | ||
import java.nio.charset.Charset; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
|
||
import static java.nio.charset.StandardCharsets.UTF_8; | ||
import static java.nio.file.StandardOpenOption.*; | ||
|
||
public class RegularFile extends AbstractFile { | ||
|
||
|
||
/** | ||
* Creates a {@link RegularFile} based on the given {@link File}. | ||
*/ | ||
public RegularFile(File file) { | ||
this(file.toPath()); | ||
} | ||
|
||
/** | ||
* Creates a {@link RegularFile} based on the given filepath. | ||
* | ||
* @param filepath the path of this {@link RegularFile}. | ||
*/ | ||
public RegularFile(Path filepath) { | ||
super(filepath); | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
* <p> | ||
* If the file is created it will be empty. | ||
* <p> | ||
* You do not have to call this method before any | ||
* {@link #write(IOConsumer, Charset)} or {@link #append(IOConsumer, Charset)} | ||
* invocation, because these methods will also create this file if it does not exist. | ||
* | ||
* @throws IOException | ||
*/ | ||
@Override | ||
public void create() throws IOException { | ||
append(IOConsumer.noop()); | ||
} | ||
|
||
@Override | ||
public Directory getParent() { | ||
Path parent = getPath().getParent(); | ||
|
||
if (parent != null) { | ||
return new Directory(parent); | ||
} | ||
|
||
return null; | ||
} | ||
|
||
/** | ||
* Writes the content provided by the {@link Appendable} to this {@link RegularFile} using {@link java.nio.charset.StandardCharsets#UTF_8}. | ||
* | ||
* @see #write(IOConsumer, Charset) | ||
*/ | ||
public void write(IOConsumer<Appendable> contentWriter) throws IOException { | ||
write(contentWriter, UTF_8); | ||
} | ||
|
||
/** | ||
* Writes the content provided by the {@link Appendable} to this {@link RegularFile} using the specified {@link Charset}. | ||
* | ||
* <ul> | ||
* <li>If parent directories do not exist, they will be created.</li> | ||
* <li>If the file does not exist, it will be created.</li> | ||
* <li>If the file already exists, it will be overwritten.</li> | ||
* <li>If the file is an existent directory, an {@link IOException} is raised.</li> | ||
* </ul> | ||
* <p> | ||
* This method can also be used to create an empty file | ||
* | ||
* <pre> | ||
* RegularFile regularFile = ...; | ||
* regularFile.write({@link IOConsumer#noop()}); | ||
* </pre> | ||
* | ||
* @param contentWriter an {@link Appendable} {@link IOConsumer} used to write the content of this file. | ||
* @throws IOException if the file is an existent directory or if the content could not be written. | ||
*/ | ||
public void write(IOConsumer<Appendable> contentWriter, Charset charset) throws IOException { | ||
ensureParentDirs(); | ||
|
||
try (PrintWriter pw = new PrintWriter(new OutputStreamWriter(Files.newOutputStream(getPath(), CREATE, TRUNCATE_EXISTING), charset))) { | ||
contentWriter.accept(pw); | ||
} | ||
} | ||
|
||
private void ensureParentDirs() throws IOException { | ||
Path filePath = getPath(); | ||
Path parentPath = filePath.getParent(); | ||
if (parentPath != null && !Files.exists(parentPath)) { | ||
Files.createDirectories(parentPath); | ||
} | ||
} | ||
|
||
public void append(IOConsumer<Appendable> contentWriter) throws IOException { | ||
append(contentWriter, UTF_8); | ||
} | ||
|
||
/** | ||
* Appends content provided by the {@link Appendable} to this {@link RegularFile} using the specified {@link Charset}. | ||
* | ||
* <ul> | ||
* <li>If parent directories do not exist, they will be created.</li> | ||
* <li>If the file does not exist, it will be created and the content will be appended.</li> | ||
* <li>If the file already exists, the content will be appended.</li> | ||
* <li>If the file is an existent directory an {@link IOException} is raised.</li> | ||
* </ul> | ||
* | ||
* @param contentWriter an {@link Appendable} {@link IOConsumer} used to append to the content of this file. | ||
* @throws IOException if the file is an existent directory or if the content could not be appended. | ||
*/ | ||
public void append(IOConsumer<Appendable> contentWriter, Charset charset) throws IOException { | ||
ensureParentDirs(); | ||
|
||
try (PrintWriter pw = new PrintWriter(new OutputStreamWriter(Files.newOutputStream(getPath(), CREATE, APPEND), charset))) { | ||
contentWriter.accept(pw); | ||
} | ||
} | ||
} |
61 changes: 61 additions & 0 deletions
61
lis-commons-io/src/test/java/com/link_intersystems/io/file/AbstractFileTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package com.link_intersystems.io.file; | ||
|
||
import org.junit.jupiter.api.BeforeEach; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.api.io.TempDir; | ||
|
||
import java.io.IOException; | ||
import java.nio.file.Path; | ||
|
||
import static org.junit.jupiter.api.Assertions.*; | ||
|
||
class AbstractFileTest { | ||
|
||
private static class TestFile extends AbstractFile { | ||
|
||
protected TestFile(Path path) { | ||
super(path); | ||
} | ||
|
||
@Override | ||
public void create() { | ||
|
||
} | ||
|
||
@Override | ||
public AbstractFile getParent() { | ||
return null; | ||
} | ||
} | ||
|
||
private AbstractFile abstractFile; | ||
|
||
@BeforeEach | ||
void setUp(@TempDir Path tempDir) { | ||
abstractFile = new TestFile(tempDir); | ||
} | ||
|
||
@Test | ||
void exists() { | ||
assertTrue(abstractFile.exists()); | ||
} | ||
|
||
@Test | ||
void testEquals(@TempDir Path unequalPath) { | ||
TestFile equal = new TestFile(abstractFile.getPath()); | ||
TestFile unequal = new TestFile(unequalPath); | ||
|
||
assertEquals(abstractFile, equal); | ||
assertEquals(equal, abstractFile); | ||
assertNotEquals(equal, unequal); | ||
assertNotEquals(equal, null); | ||
assertNotEquals(equal, ""); | ||
} | ||
|
||
@Test | ||
void testHashCode() { | ||
TestFile actual = new TestFile(abstractFile.getPath()); | ||
|
||
assertEquals(abstractFile.hashCode(), actual.hashCode()); | ||
} | ||
} |
Oops, something went wrong.