Пользовательская реализация InputStream - PullRequest
5 голосов
/ 26 января 2011

Чтобы отправить данные в файл на моем FTP-сервере, мне нужно создать собственную реализацию InputStream, которая читает строку за строкой данные базы данных, преобразовывает их в CSV и публикует их с помощью методов read (): из базы данных я получаюList<Application> объект с данными.Для каждого объекта Application я хочу создать строку в файле CSV.

Моя идея состоит в том, чтобы загрузить все данные в конструкторе и затем переопределить метод чтения.Нужно ли переопределять все методы InputStream?Я пробовал поискать в Google примеры, но не получилось - не могли бы вы дать мне ссылку на один из них?

Ответы [ 6 ]

9 голосов
/ 26 января 2011

Вам нужно только реализовать метод read() без параметров .Все остальные методы реализованы как вызовы этого метода.По причинам производительности (и даже простоты реализации) может быть проще реализовать метод с тремя аргументами read() вместо и повторно реализовать метод без аргументов read() в терминах этого метода.

5 голосов
/ 29 декабря 2015

Некоторые очень важные моменты, с которыми я столкнулся при реализации моего InputStream.

  1. Доступно переопределение ().Как сказано в Javadoc:

    Доступный метод для класса InputStream всегда возвращает 0. Этот метод должен быть переопределен подклассами.

    не переопределение этого метода вызовет любой соблазнпроверить, доступен ли этот поток для чтения , вернуть false .Например, если вы подадите свой inputStream на inputStreamReader, этот читатель будет всегда возвращать false при вызове reader.ready().

  2. return -1в read().В документе это не подчеркивалось:

    Если байт недоступен, поскольку достигнут конец потока, возвращается значение -1.Этот метод блокирует до тех пор, пока не будут доступны входные данные, не будет обнаружен конец потока или сгенерировано исключение.

    Если вы решите заблокировать read(), когда данные недоступны, вы должны запомнитьдо return -1 в некоторых ситуациях.Невыполнение этого требования может привести к тому, что другие read(byte b[], int off, int len) блокируют следующий код в исходном коде:

    for (; i < len ; i++) {// default len is a relative large number (8192 - readPosition)
        c = read();
        if (c == -1) {
            break;
        }
        b[off + i] = (byte)c;
    }
    

    И это вызывает некоторые (если не все) высокоуровневые блоки чтения, такие как readLine(), read() и т. Д.

3 голосов
/ 26 января 2011

Для больших данных вы можете использовать com.google.common.io.FileBackedOutputStream из guava .

Javadoc: OutputStream, который начинает буферизацию в байтовый массив, но переключается на буферизацию файла, когда данные достигают настраиваемого размера. Используя out.getSupplier().getInput(), вы получаете ваш InputStream.

1 голос
/ 26 января 2011

Зачем вам нужен входной поток custon?почему бы просто не записать данные csv по мере их генерации в выходной поток, записываемый на ftp-сервер?

0 голосов
/ 26 января 2011

Абсолютно не нужно создавать кастом InputStream. Используйте ByteArrayInputStream, что-то вроде этого:

public static InputStream createStream(){
    final String csv = createCsvFromDataBaseValues();
    return new ByteArrayInputStream(csv.getBytes());
}

Особенно учитывая эту цитату:

Моя идея - загрузить все данные в конструктор, а затем переопределить чтение способ.

Если вы сделаете это так, вы абсолютно ничего не получите, внедрив пользовательский InputStream. Это в значительной степени эквивалентно подходу, который я изложил выше.

0 голосов
/ 26 января 2011

Если данные не слишком велики, вы можете:

  • Читать всеString.getBytes(encoding))
  • Но байтовый массив в ByteArrayInputStream
...