Mal so als Beispiel, wie man das angehen könnte. Die verschiedenen Problemchen dabei habe ich in verschiedene Klassen zerlegt. Vielleicht mag es helfen:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class FindNearestTimesToFullSeconds {
private static final Data NO_DATA_FOUND = new Data(-1.1, -1, -1);
private List<Data> dataSets;
public void work(List<Data> dataSets) {
this.dataSets = dataSets;
List<Integer> fullSeconds = createFullSeconds();
List<Data> nearestDataSets = createNearestDataSets(fullSeconds);
printNearest(nearestDataSets);
}
private List<Integer> createFullSeconds() {
List<Double> allSeconds = generateAllSeconds();
int minSecond = findLowerBorder(allSeconds);
int maxSecond = findUpperBorder(allSeconds);
List<Integer> fullSeconds = new ArrayList<>();
for (int fullSecond = minSecond; fullSecond <= maxSecond; ++fullSecond) {
fullSeconds.add(fullSecond);
}
return fullSeconds;
}
private List<Double> generateAllSeconds() {
List<Double> allSeconds = new ArrayList<>();
for (Data data :dataSets) {
allSeconds.add(data.getTime());
}
return allSeconds;
}
private int findLowerBorder(List<Double> allSeconds) {
if (allSeconds.isEmpty()) {
return 0;
}
double minTime = Collections.min(allSeconds);
return (int) Math.floor(minTime);
}
private int findUpperBorder(List<Double> allSeconds) {
if (allSeconds.isEmpty()) {
return 0;
}
double maxTime = Collections.max(allSeconds);
return (int) Math.ceil(maxTime);
}
private List<Data> createNearestDataSets(List<Integer> fullSeconds) {
List<Data> nearestDataSets = new ArrayList<>();
for (int fullSecond : fullSeconds) {
double fullSecondDouble = fullSecond;
double minDistance = Double.MAX_VALUE;
Data minDistanceData = NO_DATA_FOUND;
for (Data data : dataSets) {
double distance = Math.abs(data.getTime() - fullSecondDouble);
if (minDistance > distance) {
minDistance = distance;
minDistanceData = data;
}
}
if (NO_DATA_FOUND == minDistanceData) {
throw new RuntimeException("no min value found");
}
nearestDataSets.add(minDistanceData);
System.out.println("Volle Sekunde : " + fullSecond + " -> " + minDistanceData);
}
return nearestDataSets;
}
private void printNearest(List<Data> nearestDataSets) {
System.out.println("Nächste Datenobjekte:");
for (Data data : nearestDataSets) {
System.out.println(data);
}
}
public static void main(String[] args) {
List<String> lines = readFile("c:/temp/sekundendaten.txt");
printLines(lines);
lines.remove(0); // Titelzeile entfernen
CreateLineObjects create = new CreateLineObjects();
List<Data> dataSets = create.create(lines);
printDataSets(dataSets);
FindNearestTimesToFullSeconds find = new FindNearestTimesToFullSeconds();
find.work(dataSets);
}
private static List<String> readFile(String filename) {
ReadFile reader = new ReadFile(filename);
List<String> list = reader.read();
reader.close();
return list;
}
private static void printLines(List<String> lines) {
System.out.println("Eingelesene Zeilen:");
for (String line : lines) {
System.out.println(line);
}
}
private static void printDataSets(List<Data> dataSets) {
System.out.println("Eingelesene Daten-Objekte:");
for (Data dataSet : dataSets) {
System.out.println(dataSet);
}
}
}
class ReadFile {
private static final String CHAR_SET = "ISO-8859-1";
private final String filename;
private final LineNumberReader reader;
public ReadFile(String filename) {
this.filename = filename;
reader = openReader();
}
public List<String> read() {
List<String> list = new ArrayList<>();
String line = readNextLine();
while (line != null) {
list.add(line);
line = readNextLine();
}
return list;
}
private String readNextLine() {
try {
return reader.readLine();
}
catch (IOException e) {
throw new RuntimeException("Es trat ein Fehler beim Einlesen der nächsten Zeile "
+ "aus der Datei '" + filename + "' auf. (" + e.getMessage() + ")");
}
}
private LineNumberReader openReader() {
try {
return tryToOpenReader();
}
catch (FileNotFoundException e) {
throw new RuntimeException("Die Eingabedatei '" + filename
+ "' wurde nicht gefunden. (" + e.getMessage() + ")");
}
catch (UnsupportedEncodingException e) {
throw new RuntimeException("Bei der Erzeugung des "
+ "InputStreamReaders für die Eingabedatei '" + filename
+ "' wurde eine nicht unterstützte Kodierung verwendet. (" + e.getMessage()
+ ")");
}
}
private LineNumberReader tryToOpenReader() throws UnsupportedEncodingException,
FileNotFoundException {
InputStream inputStream = new FileInputStream(filename);
InputStreamReader reader = new InputStreamReader(inputStream, CHAR_SET);
return new LineNumberReader(reader);
}
public void close() {
try {
reader.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
class Data {
private final double time;
private final int valueA;
private final int valueB;
public Data(double time, int valueA, int valueB) {
this.time = time;
this.valueA = valueA;
this.valueB = valueB;
}
public double getTime() {
return time;
}
public int getValueA() {
return valueA;
}
public int getValueB() {
return valueB;
}
@Override
public String toString() {
return "Data [time=" + time + ", valueA=" + valueA + ", valueB=" + valueB + "]";
}
}
class CreateLineObjects {
public List<Data> create(List<String> lines) {
List<Data> list = new ArrayList<>();
for (String line : lines) {
Data data = createDataFromLine(line);
list.add(data);
}
return list;
}
private Data createDataFromLine(String line) {
int expectedSize = 3;
List<String> values = splitBy(line, " ");
if (values.size() != expectedSize) {
throw new RuntimeException("Eine Zeile lässt sich nicht in " + expectedSize
+ " Teile teilen, sondern in " + values.size() + "!
line = '" + line + "'");
}
double seconds = parseDoubleValue(values.get(0));
int valueA = parseIntValue(values.get(1));
int valueB = parseIntValue(values.get(1));
return new Data(seconds, valueA, valueB);
}
private List<String> splitBy(String input, String regex) {
List<String> list = new ArrayList<>();
list.addAll(Arrays.asList(input.split(regex, -1)));
return list;
}
private double parseDoubleValue(String stringValue) {
try {
return Double.parseDouble(stringValue);
}
catch (NumberFormatException excpetion) {
throw new RuntimeException("Die Zahl '" + stringValue + "' ließ sich nicht in einen "
+ "double-Wert parsen!");
}
}
private int parseIntValue(String stringValue) {
try {
return Integer.parseInt(stringValue);
}
catch (NumberFormatException excpetion) {
throw new RuntimeException("Die Zahl '" + stringValue + "' ließ sich nicht in einen "
+ "int-Wert parsen!");
}
}
}```
Die Eingabedatei c:/temp/sekundendaten.txt sieht so aus:
Zeit Messwert-A Messwert-B
0.002 15 27
3.223 12 556
3.998 9 523
4.001 10 231
4.002 12 23
4.003 14 22
5.002 19 28
Die Ausgabe so:
Eingelesene Zeilen:
Zeit Messwert-A Messwert-B
0.002 15 27
3.223 12 556
3.998 9 523
4.001 10 231
4.002 12 23
4.003 14 22
5.002 19 28
Eingelesene Daten-Objekte:
Data [time=0.002, valueA=15, valueB=15]
Data [time=3.223, valueA=12, valueB=12]
Data [time=3.998, valueA=9, valueB=9]
Data [time=4.001, valueA=10, valueB=10]
Data [time=4.002, valueA=12, valueB=12]
Data [time=4.003, valueA=14, valueB=14]
Data [time=5.002, valueA=19, valueB=19]
Volle Sekunde : 0 -> Data [time=0.002, valueA=15, valueB=15]
Volle Sekunde : 1 -> Data [time=0.002, valueA=15, valueB=15]
Volle Sekunde : 2 -> Data [time=3.223, valueA=12, valueB=12]
Volle Sekunde : 3 -> Data [time=3.223, valueA=12, valueB=12]
Volle Sekunde : 4 -> Data [time=4.001, valueA=10, valueB=10]
Volle Sekunde : 5 -> Data [time=5.002, valueA=19, valueB=19]
Volle Sekunde : 6 -> Data [time=5.002, valueA=19, valueB=19]
Nächste Datenobjekte:
Data [time=0.002, valueA=15, valueB=15]
Data [time=0.002, valueA=15, valueB=15]
Data [time=3.223, valueA=12, valueB=12]
Data [time=3.223, valueA=12, valueB=12]
Data [time=4.001, valueA=10, valueB=10]
Data [time=5.002, valueA=19, valueB=19]
Data [time=5.002, valueA=19, valueB=19]