Я хочу постепенно обработать текст, записанный в OutputStream
, как он написан.
Например, предположим, что у нас есть эта программа:
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.Charset;
public class Streaming {
// Writes file, incrementally, to OutputStream.
static void dump(File file, OutputStream out) throws IOException {
// Implementation omitted
}
static int sum = 0;
public static void main(String[] args) throws IOException {
Charset charSet = Charset.defaultCharset(); // Interpret the file as having this encoding.
dump(new File("file.txt"), new OutputStream() {
@Override
public void write(int b) throws IOException {
// Add b to bytes already read,
// Determine if we have reached the end of the token (using
// the default encoding),
// And parse the token and add it to `sum`
}
});
System.out.println("Sum: " + sum);
}
}
Предположим, file.txt
- это текстовый файл, содержащий разделенный пробелами список целых чисел. В этой программе я хочу найти сумму значений в file.txt
, накапливая сумму в переменной sum
. Я бы хотел избежать создания строки длиной в миллионы символов.
Меня интересует способ, которым я могу сделать это, используя функцию dump
, которая записывает содержимое файла в выходной поток. Я не заинтересован в чтении файла другим способом (например, создание Scanner
для file.txt
и повторный вызов nextInt
на сканере). Я налагаю это ограничение, потому что я использую библиотеку, API которой похож на dump
, где клиент должен предоставить OutputStream
, и библиотека впоследствии записывает много текста в выходной поток.
Как я могу реализовать метод write
, чтобы правильно выполнить описанные шаги? Я хотел бы избежать выполнения токенизации вручную, поскольку такие утилиты, как Scanner
, уже способны выполнять токенизацию, и я хочу иметь возможность обрабатывать любую кодировку текста (как указано charSet
). Однако я не могу использовать Scanner
напрямую, потому что нет способа проверить (неблокирующим способом), доступен ли токен:
public static void main(String[] args) throws IOException {
Charset charSet = Charset.defaultCharset();
PipedInputStream in = new PipedInputStream();
try (Scanner sc = new Scanner(in, charSet)) {
dump(new File("file.txt"), new PipedOutputStream(in) {
@Override
public void write(byte[] b, int off, int len) throws IOException {
super.write(b, off, len);
// This will loop infinitely, because `hasNextInt`
// will block if there is no int token currently available.
if (sc.hasNextInt()) {
sum += sc.nextInt();
}
}
});
}
System.out.println("Sum: " + sum);
System.out.println(charSet);
}
Существует ли неблокирующая утилита, которая может выполнять для меня токенизацию при записи данных в выходной поток?