CsvInputStream.java
package de.dlr.shepard.data.timeseries.utilities;
import jakarta.annotation.Nonnull;
import java.io.IOException;
import java.io.InputStream;
import java.util.Objects;
import lombok.NonNull;
public class CsvInputStream extends InputStream {
@NonNull
private final CsvLineProvider lineProvider;
private String lineBuffer;
private int lineBufferLen = 0;
private int lineBufferPos = 0;
public CsvInputStream(@NonNull CsvLineProvider lineProvider) {
this.lineProvider = Objects.requireNonNull(lineProvider);
try {
readCSVLine();
} catch (IOException e) {
// Ignore, will be thrown again in read method
}
}
@Override
public int read() throws IOException {
var remaining = checkBuffer();
if (remaining <= 0) return -1;
return lineBuffer.charAt(lineBufferPos++);
}
@Override
public int read(@Nonnull byte[] b, int off, int len) throws IOException {
var remaining = checkBuffer();
if (remaining <= 0) return -1;
var strLen = Math.min(len, remaining);
System.arraycopy(lineBuffer.getBytes(), lineBufferPos, b, off, strLen);
lineBufferPos += strLen;
return strLen;
}
@Override
public int available() throws IOException {
return lineBufferLen - lineBufferPos;
}
private int checkBuffer() throws IOException {
// Check whether a new CSV line must be generated
if (lineBufferPos >= lineBufferLen || lineBufferLen <= 0) readCSVLine();
if (lineBufferLen > 0 && lineBufferPos >= lineBufferLen) {
// It should be impossible to reach this
throw new IOException("Buffer overflow");
}
return lineBufferLen - lineBufferPos;
}
private void readCSVLine() throws IOException {
lineBuffer = lineProvider.readCsvLine();
lineBufferLen = lineBuffer.length();
lineBufferPos = 0;
}
}