mirror of
https://github.com/jneug/zeichenmaschine.git
synced 2026-04-14 14:43:33 +02:00
java.io -> java.nio
This commit is contained in:
@@ -2,12 +2,14 @@ package schule.ngb.zm.util.io;
|
|||||||
|
|
||||||
import schule.ngb.zm.util.Log;
|
import schule.ngb.zm.util.Log;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -23,19 +25,24 @@ public final class FileLoader {
|
|||||||
|
|
||||||
public static final Charset ISO_8859_1 = StandardCharsets.ISO_8859_1;
|
public static final Charset ISO_8859_1 = StandardCharsets.ISO_8859_1;
|
||||||
|
|
||||||
|
|
||||||
public static List<String> loadLines( String source ) {
|
public static List<String> loadLines( String source ) {
|
||||||
return loadLines(source, UTF8);
|
return loadLines(source, UTF8);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<String> loadLines( String source, Charset charset ) {
|
public static List<String> loadLines( String source, Charset charset ) {
|
||||||
try {
|
try( BufferedReader reader = ResourceStreamProvider.getReader(source, charset) ) {
|
||||||
return Files.readAllLines(Paths.get(ResourceStreamProvider.getResourceURL(source).toURI()), charset);
|
List<String> result = new ArrayList<>();
|
||||||
} catch( IOException | URISyntaxException ex ) {
|
|
||||||
LOG.error(ex, "Error while loading lines from source <%s>", source);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Collections.emptyList();
|
String line;
|
||||||
|
while( (line = reader.readLine()) != null ) {
|
||||||
|
result.add(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
} catch( IOException ex ) {
|
||||||
|
LOG.error(ex, "Error while loading lines from source <%s>", source);
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String loadText( String source ) {
|
public static String loadText( String source ) {
|
||||||
@@ -43,61 +50,94 @@ public final class FileLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String loadText( String source, Charset charset ) {
|
public static String loadText( String source, Charset charset ) {
|
||||||
try {
|
try( BufferedReader reader = ResourceStreamProvider.getReader(source, charset) ) {
|
||||||
return Files.readString(Paths.get(ResourceStreamProvider.getResourceURL(source).toURI()), charset);
|
StringBuilder result = new StringBuilder();
|
||||||
} catch( IOException | URISyntaxException ex ) {
|
|
||||||
LOG.error(ex, "Error while loading text from source <%s>", source);
|
|
||||||
}
|
|
||||||
|
|
||||||
return "";
|
String line;
|
||||||
|
while( (line = reader.readLine()) != null ) {
|
||||||
|
result.append(line).append('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.toString();
|
||||||
|
} catch( IOException ex ) {
|
||||||
|
LOG.error(ex, "Error while loading string from source <%s>", source);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String[][] loadCsv( String source, boolean skipFirst ) {
|
public static String[][] loadCsv( String source, boolean skipFirst ) {
|
||||||
return loadCsv(source, ',', skipFirst, UTF8);
|
return loadCsv(source, ',', skipFirst, UTF8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lädt die Daten aus einer CSV Datei in ein zweidimensionales
|
||||||
|
* String-Array.
|
||||||
|
* <p>
|
||||||
|
* Die Methode ist nicht in der Lage, komplexe CSV-Dateien zu verarbeiten.
|
||||||
|
* Insbesondere können Inhalte, die das Trennzeichen {@code separator}
|
||||||
|
* enthalten, nicht korrekt erkannt werden. Das Trennzeichen wird unabhängig
|
||||||
|
* vom Kontext immer als Zelltrenner erkannt. (Im Normalfall kann das
|
||||||
|
* Trennzeichen durch die Verwendung doppelter Anführungszeichen in der Art
|
||||||
|
* {@code Inhalt,"Inhalt, der Komma enthält",Inhalt} maskiert werden.)
|
||||||
|
* <p>
|
||||||
|
* Es wird auch keine erweiterte Inhaltserkennung ausgeführt, sondern alle
|
||||||
|
* Inhalte als {@code String} gelesen. Die weitere Verarbeitung mit den
|
||||||
|
* passenden Parser-Methoden (beispielsweise
|
||||||
|
* {@link Double#parseDouble(String)}) obligt dem Nutzer.
|
||||||
|
*
|
||||||
|
* @param source Die Quelle der CSV-Daten.
|
||||||
|
* @param separator Das verwendete Trennzeichen.
|
||||||
|
* @param skipFirst Ob die erste Zeile übersprungen werden soll.
|
||||||
|
* @param charset Die zu verwendende Zeichenkodierung.
|
||||||
|
* @return Ein Array mit den Daten als {@code String}s.
|
||||||
|
*/
|
||||||
public static String[][] loadCsv( String source, char separator, boolean skipFirst, Charset charset ) {
|
public static String[][] loadCsv( String source, char separator, boolean skipFirst, Charset charset ) {
|
||||||
try( Stream<String> lines = Files
|
int n = skipFirst ? 1 : 0;
|
||||||
.lines(Paths.get(ResourceStreamProvider.getResourceURL(source).toURI()), charset)
|
List<String> lines = loadLines(source, charset);
|
||||||
) {
|
return lines.stream().skip(n).map(
|
||||||
int n = skipFirst ? 1 : 0;
|
//( line ) -> line.split(Character.toString(separator))
|
||||||
return lines.skip(n).map(
|
( line ) -> line.split("\\s*" + separator + "\\s*")
|
||||||
( line ) -> line.split(Character.toString(separator))
|
).toArray(String[][]::new);
|
||||||
).toArray(String[][]::new);
|
|
||||||
} catch( IOException | URISyntaxException ex ) {
|
|
||||||
LOG.error(ex, "Error while loading csv source <%s>", source);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new String[0][0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static double[][] loadValues( String source, char separator, boolean skipFirst ) {
|
public static double[][] loadValues( String source, char separator, boolean skipFirst ) {
|
||||||
return loadValues(source, separator, skipFirst, UTF8);
|
return loadValues(source, separator, skipFirst, UTF8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lädt Double-Werte aus einer CSV Datei in ein zweidimensionales Array.
|
||||||
|
* <p>
|
||||||
|
* Die gelesenen Strings werden mit {@link Double#parseDouble(String)} in
|
||||||
|
* {@code double} umgeformt. Es leigt in der Verantwortung des Nutzers
|
||||||
|
* sicherzustellen, dass die CSV-Datei auch nur Zahlen enthält, die korrekt
|
||||||
|
* in {@code double} umgewandelt werden können. Zellen für die die
|
||||||
|
* Umwandlung fehlschlägt werden mit 0.0 befüllt.
|
||||||
|
* <p>
|
||||||
|
* Die Methode unterliegt denselben Einschränkungen wie
|
||||||
|
* {@link #loadCsv(String, char, boolean, Charset)}.
|
||||||
|
*
|
||||||
|
* @param source Die Quelle der CSV-Daten.
|
||||||
|
* @param separator Das verwendete Trennzeichen.
|
||||||
|
* @param skipFirst Ob die erste Zeile übersprungen werden soll.
|
||||||
|
* @param charset Die zu verwendende Zeichenkodierung.
|
||||||
|
* @return Ein Array mit den Daten als {@code String}s.
|
||||||
|
*/
|
||||||
public static double[][] loadValues( String source, char separator, boolean skipFirst, Charset charset ) {
|
public static double[][] loadValues( String source, char separator, boolean skipFirst, Charset charset ) {
|
||||||
try( Stream<String> lines = Files
|
int n = skipFirst ? 1 : 0;
|
||||||
.lines(Paths.get(ResourceStreamProvider.getResourceURL(source).toURI()), charset)
|
List<String> lines = loadLines(source, charset);
|
||||||
) {
|
return lines.stream().skip(n).map(
|
||||||
int n = skipFirst ? 1 : 0;
|
( line ) -> Arrays
|
||||||
return lines.skip(n).map(
|
.stream(line.split(Character.toString(separator)))
|
||||||
( line ) -> Arrays
|
.mapToDouble(
|
||||||
.stream(line.split(Character.toString(separator)))
|
( value ) -> {
|
||||||
.mapToDouble(
|
try {
|
||||||
( value ) -> {
|
return Double.parseDouble(value);
|
||||||
try {
|
} catch( NumberFormatException nfe ) {
|
||||||
return Double.parseDouble(value);
|
return 0.0;
|
||||||
} catch( NumberFormatException nfe ) {
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
).toArray()
|
}
|
||||||
).toArray(double[][]::new);
|
).toArray()
|
||||||
} catch( IOException | URISyntaxException ex ) {
|
).toArray(double[][]::new);
|
||||||
LOG.error(ex, "Error while loading double values from csv source <%s>", source);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new double[0][0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public FileLoader() {
|
public FileLoader() {
|
||||||
|
|||||||
@@ -5,13 +5,66 @@ import schule.ngb.zm.util.Log;
|
|||||||
import schule.ngb.zm.util.Validator;
|
import schule.ngb.zm.util.Validator;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helferklasse, um {@link InputStream}s für Resourcen zu erhalten.
|
* Helferklasse, um {@link InputStream}s für Resourcen zu erhalten.
|
||||||
*/
|
*/
|
||||||
public class ResourceStreamProvider {
|
public class ResourceStreamProvider {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ermittelt zur angegebenen Quelle einen passenden {@link URL} (<em>Unified
|
||||||
|
* Resource Locator</em>). Eine passende Datei-Resource wird wie folgt
|
||||||
|
* ermittelt:
|
||||||
|
* <ol>
|
||||||
|
* <li>Ist {@code source} eine existierende Datei
|
||||||
|
* ({@code new File(source}.isFile() == true})?</li>
|
||||||
|
* <li>Ist {@code source} ein relativer Pfad im Projekt ({@code getResource(source) != null})?.</li>
|
||||||
|
* <li>Ist {@code source} im Classpath enthalten ({@code getClassLoader().getResource(source) != null})?</li>
|
||||||
|
* <li>Ansonten erstellt ein {@link URL}-Objekt.</li>
|
||||||
|
* </ol>
|
||||||
|
* <p>
|
||||||
|
* Ein {@code URL} für die erste gefundene Resource wird zurückgegeben.
|
||||||
|
* Auftretende Exceptions
|
||||||
|
* werden als {@link IOException} geworfen.
|
||||||
|
* <p>
|
||||||
|
* Bei einer Exception werden die folgenden Quellen nicht mehr abgefragt.
|
||||||
|
* Eine {@link java.net.MalformedURLException} beim Konstruieren des {@code URL}
|
||||||
|
* zu einer Datei verhindert daher, dass noch im Classpath gesucht wird.
|
||||||
|
*
|
||||||
|
* @param source Eine Quelle für die Resource (Absoluter Dateipfad,
|
||||||
|
* Dateipfad im Classpath oder Netzwerkresource)
|
||||||
|
* @return Ein {@code InputStream} für die Resource
|
||||||
|
* @throws NullPointerException Falls {@code source} {@code null} ist.
|
||||||
|
* @throws IllegalArgumentException Falls {@code source} ein leerer String
|
||||||
|
* ist.
|
||||||
|
* @throws IOException Geworfen beim Erzeugen einer URL zu
|
||||||
|
* einer bestehenden Resource.
|
||||||
|
*/
|
||||||
|
public static URL getResourceURL( String source ) throws NullPointerException, IllegalArgumentException, IOException {
|
||||||
|
Validator.requireNotNull(source, "Resource source may not be null");
|
||||||
|
Validator.requireNotEmpty(source, "Resource source may not be empty.");
|
||||||
|
|
||||||
|
// Ist source ein valider Dateipfad?
|
||||||
|
File file = new File(source);
|
||||||
|
if( file.isFile() ) {
|
||||||
|
return file.toURI().toURL();
|
||||||
|
}
|
||||||
|
// Ist source im Classpath vorhanden?
|
||||||
|
URL url = Zeichenmaschine.class.getClassLoader().getResource(source);
|
||||||
|
if( url != null ) {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
// Dann versuchen aus source direkt eine URL zu machen.
|
||||||
|
return new URL(source);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sucht eine zur angegebenen Quelle passende Resource und öffnet einen
|
* Sucht eine zur angegebenen Quelle passende Resource und öffnet einen
|
||||||
* passenden {@link InputStream}. Die konkrete Art des Streams hängt davon
|
* passenden {@link InputStream}. Die konkrete Art des Streams hängt davon
|
||||||
@@ -45,134 +98,41 @@ public class ResourceStreamProvider {
|
|||||||
* @throws NullPointerException Falls {@code source} {@code null} ist.
|
* @throws NullPointerException Falls {@code source} {@code null} ist.
|
||||||
* @throws IllegalArgumentException Falls {@code source} ein leerer String
|
* @throws IllegalArgumentException Falls {@code source} ein leerer String
|
||||||
* ist.
|
* ist.
|
||||||
* @throws IOException Geworfen beim öffnen des Streams zu
|
* @throws IOException Geworfen beim Öffnen des Streams zu
|
||||||
* einer bestehenden Resource oder falls
|
* einer bestehenden Resource oder falls
|
||||||
* keine passende Resource gefunden wurde.
|
* keine passende Resource gefunden wurde.
|
||||||
*/
|
*/
|
||||||
public static InputStream getInputStream( String source ) throws NullPointerException, IllegalArgumentException, IOException {
|
public static InputStream getInputStream( String source ) throws NullPointerException, IllegalArgumentException, IOException {
|
||||||
Validator.requireNotNull(source, "Resource source may not be null");
|
return getResourceURL(source).openStream();
|
||||||
Validator.requireNotEmpty(source, "Resource source may not be empty.");
|
|
||||||
|
|
||||||
InputStream in = null;
|
|
||||||
|
|
||||||
// See if source is a readable file
|
|
||||||
File file = new File(source);
|
|
||||||
try {
|
|
||||||
if( file.isFile() ) {
|
|
||||||
in = new FileInputStream(file);
|
|
||||||
}
|
|
||||||
} catch( FileNotFoundException fnfex ) {
|
|
||||||
// Somehow an exception occurred, but we still try other sources
|
|
||||||
}
|
|
||||||
// File does not exist, try other means
|
|
||||||
// load ressource relative to .class-file
|
|
||||||
if( in == null ) {
|
|
||||||
in = Zeichenmaschine.class.getResourceAsStream(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
// relative to ClassLoader
|
|
||||||
if( in == null ) {
|
|
||||||
in = Zeichenmaschine.class.getClassLoader().getResourceAsStream(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
// load form web or jar-file
|
|
||||||
if( in == null ) {
|
|
||||||
in = new URL(source).openStream();
|
|
||||||
}
|
|
||||||
|
|
||||||
// One of the above got a valid Stream,
|
|
||||||
// otherwise an Exception was thrown
|
|
||||||
return in;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static InputStream getInputStream( File file ) throws IOException {
|
|
||||||
Validator.requireNotNull(file, "Provided file can't be null.");
|
|
||||||
return new FileInputStream(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static InputStream getInputStream( URL url ) throws IOException {
|
|
||||||
Validator.requireNotNull(url, "Provided URL can't be null.");
|
|
||||||
return url.openStream();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ermittelt zur angegebenen Quelle einen passenden {@link URL} (<em>Unified
|
|
||||||
* Resource Locator</em>). Eine passende Datei-Resource wird wie folgt
|
|
||||||
* ermittelt:
|
|
||||||
* <ol>
|
|
||||||
* <li>Ist {@code source} eine existierende Datei
|
|
||||||
* ({@code new File(source}.isFile() == true})?</li>
|
|
||||||
* <li>Ist {@code source} ein relativer Pfad im Projekt ({@code getResource(source) != null})?.</li>
|
|
||||||
* <li>Ist {@code source} im Classpath enthalten ({@code getClassLoader().getResource(source) != null})?</li>
|
|
||||||
* <li>Ansonten erstellt ein {@link URL}-Objekt.</li>
|
|
||||||
* </ol>
|
|
||||||
* <p>
|
|
||||||
* Ein {@code URL} für die erste gefundene Resource wird zurückgegeben.
|
|
||||||
* Auftretende Exceptions
|
|
||||||
* werden als {@link IOException} geworfen.
|
|
||||||
* <p>
|
|
||||||
* Bei einer Exception werden die folgenden Quellen nicht mehr abgefragt.
|
|
||||||
* Eine {@link java.net.MalformedURLException} beim Konstruieren des {@code URL}
|
|
||||||
* zu einer Datei verhindert daher, dass noch im Classpath gesucht wird.
|
|
||||||
*
|
|
||||||
* @param source Eine Quelle für die Resource (Absoluter Dateipfad,
|
|
||||||
* Dateipfad im Classpath oder Netzwerkresource)
|
|
||||||
* @return Ein {@code InputStream} für die Resource
|
|
||||||
* @throws NullPointerException Falls {@code source} {@code null} ist.
|
|
||||||
* @throws IllegalArgumentException Falls {@code source} ein leerer String
|
|
||||||
* ist.
|
|
||||||
* @throws IOException Geworfen beim erzeugen eines URL zu
|
|
||||||
* einer bestehenden Resource.
|
|
||||||
*/
|
|
||||||
public static URL getResourceURL( String source ) throws NullPointerException, IllegalArgumentException, IOException {
|
|
||||||
Validator.requireNotNull(source, "Resource source may not be null");
|
|
||||||
Validator.requireNotEmpty(source, "Resource source may not be empty.");
|
|
||||||
|
|
||||||
File file = new File(source);
|
|
||||||
if( file.isFile() ) {
|
|
||||||
return file.toURI().toURL();
|
|
||||||
}
|
|
||||||
|
|
||||||
URL url;
|
|
||||||
|
|
||||||
url = Zeichenmaschine.class.getResource(source);
|
|
||||||
if( url != null ) {
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
url = Zeichenmaschine.class.getClassLoader().getResource(source);
|
|
||||||
if( url != null ) {
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new URL(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ver
|
|
||||||
*
|
|
||||||
* @param source
|
* @param source
|
||||||
* @return
|
* @return
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public static OutputStream getOutputStream( String source ) throws IOException {
|
public static OutputStream getOutputStream( String source ) throws IOException {
|
||||||
Validator.requireNotNull(source, "Resource source may not be null");
|
try {
|
||||||
Validator.requireNotEmpty(source, "Resource source may not be empty.");
|
return Files.newOutputStream(Path.of(getResourceURL(source).toURI()));
|
||||||
URL url = getResourceURL(source);
|
} catch( URISyntaxException ex ) {
|
||||||
return getOutputStream(new File(url.getPath()));
|
throw new IOException(ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static OutputStream getOutputStream( File file ) throws IOException {
|
public static BufferedReader getReader( String source ) throws IOException {
|
||||||
Validator.requireNotNull(file, "Provided file can't be null.");
|
return getReader(source, StandardCharsets.UTF_8);
|
||||||
return new FileOutputStream(file);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Reader getReader( String source ) throws IOException {
|
public static BufferedReader getReader( String source, Charset charset ) throws IOException {
|
||||||
return new InputStreamReader(getInputStream(source));
|
return new BufferedReader(new InputStreamReader(getInputStream(source), charset.newDecoder()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Writer getWriter( String source ) throws IOException {
|
public static BufferedWriter getWriter( String source ) throws IOException {
|
||||||
return new OutputStreamWriter(getOutputStream(source));
|
return getWriter(source, StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BufferedWriter getWriter( String source, Charset charset ) throws IOException {
|
||||||
|
return new BufferedWriter(new OutputStreamWriter(getOutputStream(source), charset.newEncoder()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private ResourceStreamProvider() {
|
private ResourceStreamProvider() {
|
||||||
|
|||||||
Reference in New Issue
Block a user