2010-08-26 5 views
4

Я выполняю потоковое считывание объекта с использованием BufferedReader.Clojure/Java: наиболее эффективный метод минимизации потребления полосы пропускания при выполнении сложных операций над потоком данных Amazon S3

мне нужно сделать две вещи с этим объектом:

  1. передать его читателю SuperCSV Csv
  2. Получить исходные линии и держать их в (Clojure) ленивым последовательность

В настоящее время мне приходится использовать два разных BufferedReaders: один в качестве аргумента для класса чтения SuperCSV CSV и один для инициализации ленивой последовательности исходных строк. Я эффективно загружаю объект S3 дважды, что дорого ($) и медленный.

Один из моих коллег указал, что что-то похожее на команду «tee» Unix - это то, что я ищу. BufferedReader, который можно каким-то образом «разбить», загрузить фрагмент данных и передать копию как для ленивой последовательности, так и для функции чтения csv.

Я также изучаю, можно ли обернуть ленивую последовательность в BufferedReader и передать , что в супер csv. У меня было несколько проблем с кучей Java, когда передавали очень большие ленивые последовательности нескольким потребителям, поэтому я немного обеспокоен использованием этого решения.

Другое решение просто загружает файл локально, а затем открывает два потока в этом файле. Это устраняет оригинальную мотивацию потоковой передачи: позволяет начать работу с файлом, как только начнутся данные.

Окончательное решение, которое я бы рассматривал только в том случае, если ничего не работает, реализует мой собственный CSV-ридер, который возвращает как проанализированный CSV, так и оригинальную непараметрированную строку. Если вы использовали очень прочный CSV-ридер, который может возвращать как Java-Hash проанализированных CSV-данных, так и оригинальную строку без ссылок, пожалуйста, дайте мне знать!

Спасибо!

+0

Я думаю, я немного не понимаю, как именно вы получаете своих персонажей из S3, может быть, немного более конкретный контекст? Я мог бы просто полностью упустить его, так что простите меня, что это так, может быть, немного олл-дауннинг-Крюгер. – Isaac

+0

Эй, Исаак, я использую функциональность, которую я создал с помощью jclouds blobstore.clj, чтобы вернуть BufferedReader, который позволяет мне читать объекты Amazon S3. – jkndrkn

ответ

0

Решение было использовать один BufferedReader для всех заходов, а затем сбросить() Ing это каждый раз, когда он передается в функциональности, которая должна читать с самого начала.

2

Я был бы склонен идти с созданием seq линий из сети, а затем передать это, несмотря на то, что многие процессы должны работать над этим seq; Таким образом, устойчивые структуры данных выглядят здорово. В случае необходимости превратить SEQ строк в считыватель, который можно передать от АНИ SuperCSV, это похоже на работу:

 
(import '[java.io Reader StringReader]) 

(defn concat-reader 
    "Returns a Reader that reads from a sequence of strings." 
    [lines] 
    (let [srs (atom (map #(StringReader. %) lines))] 
    (proxy [Reader] [] 
     (read 
     ([] 
      (let [c (.read (first @srs))] 
      (if (and (neg? c) (swap! srs next)) 
       (.read this) 
       c))) 
     ([cbuf] 
      (.read this cbuf 0 (count cbuf))) 
     ([cbuf off len] 
      (let [actual (.read (first @srs) cbuf off len)] 
      (if (and (neg? actual) (swap! srs next)) 
       (.read this cbuf off len) 
       actual)))) 
     (close [])))) 

Э.Г.

 
user=> (def r (concat-reader ["foo" "bar"])) 
#'user/r 
user=> (def cbuf (char-array 2)) 
#'user/cbuf 
user=> (.read r cbuf) 
2 
user=> (seq cbuf) 
(\f \o) 
user=> (char (.read r)) 
\o 
user=> (char (.read r)) 
\b 
+0

wwmorgan on #clojure помог мне в решении, которое принципиально придерживается вашего утверждения: «Я бы склонен пойти с созданием ряда строк из сети, а затем передать это тому, что многие процессы должны работать над этим seq «Я использовал (имя-строка-seq (create-buffered-reader-for-s3-object)».csv ")), чтобы получить ленивую последовательность, а затем завернул каждую строку в свой собственный StringReader, который затем был передан в собственный CsvMapReader. Мне пришлось создать CsvMapReader для каждой строки, а не передавать читателю, который читает через весь файл в CsvMapReader. – jkndrkn

+0

Мое окончательное решение выглядит примерно так: (let [lines (line-seq amazon-s3-reader)] [(map # (. read (CsvMapReader. (java.io.StringReader. line) CsvPreference/STANDARD_PREFERENCE))) lines)) Вышеприведенный код не анализируется, но он описывает общее решение: он возвращает как разобранные CSV-данные, так и необработанные строки и позволяет мне получить доступ как к безвредным взаимодействиям. – jkndrkn

+0

Ugh. моего решения показало, что потребление пропускной способности в 4 раза выше, чем я хотел, а не потребление 2x, которое я получал, используя два отдельных считывателя. проблема с последующим сетевым ресурсом заключается в том, что все места, где потребляется этот seq, заставляет ресурсы снова и снова извлекаться из сети, что приводит к проблемам с высокой пропускной способностью, которые я испытываю. – jkndrkn