Clojure/Java:在AmazonS3数据流上执行复杂操作时最小化带宽消耗的最有效方法
我正在使用BufferedReader执行对象的流式读取 我需要对这个对象做两件事:Clojure/Java:在AmazonS3数据流上执行复杂操作时最小化带宽消耗的最有效方法,java,clojure,amazon-s3,bufferedreader,lazy-sequences,Java,Clojure,Amazon S3,Bufferedreader,Lazy Sequences,我正在使用BufferedReader执行对象的流式读取 我需要对这个对象做两件事: 将其传递给超级SV csv阅读器 获取原始行并将它们保持在(Clojure)惰性序列中 目前,我不得不使用两个不同的BufferedReader:一个作为SuperCSV CSV reader类的参数,另一个用于初始化原始行的惰性序列。我实际上下载了两次S3对象,这既昂贵($)又慢 我的一位同事指出,我正在寻找类似于Unix“tee”命令的东西。一个BufferedReader可能会以某种方式被“拆分”,下载一
最后一个解决方案,我认为只有在没有其他工作的情况下,实现我自己的CSV读取器,它返回已解析的CSV和原始未解析的行。如果您使用了一个非常可靠的CSV阅读器,它可以返回解析CSV数据的Java哈希和原始未解析行,请告诉我
谢谢 我倾向于从网络创建一个序列行,然后将其移交给需要处理该序列的多个进程;持久数据结构就是这样的。如果需要将一系列字符串转换为一个读取器,您可以将其交给SuperCSV api,这似乎是可行的: (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 [] )))) (导入“[java.io读取器StringReader]” (defn concat阅读器 “返回从字符串序列读取的读取器。” [行] (让[srs(原子(映射#(StringReader.%)行))] (代理[读者][] (读 ([] (让[c(.read(first@srs))] (如果(和(neg?c)(互换!srs下一个)) (.读这个) c) )) ([cbuf] (.读取此cbuf 0(计数cbuf))) ([cbuf关闭透镜] (让[实际(.read(first@srs)cbuf off len)] (如果(和(负-实际)(交换!srs下一个)) (.从透镜上读取此cbuf) (实际数字) (关闭[])) 例如 用户=>(DEFR(concat读卡器[“foo”“bar]”) #'用户/r 用户=>(def cbuf(字符数组2)) #'用户/cbuf 用户=>(.read r cbuf) 2. 用户=>(seq cbuf) (\f\o) 用户=>(字符(.read r)) \o 用户=>(字符(.read r)) \b
解决方案是对所有访问使用一个BufferedReader,然后每次将其传递到需要从头开始读取的功能时都将其重置。我想我有点不清楚如何从S3中获取字符-可能更具体一点?我可能完全错过了,所以请原谅我是这样的-可能是老邓宁·克鲁格在说什么。嘿,艾萨克,我正在使用我使用jclouds blobstore.clj构建的功能返回一个BufferedReader,它允许我读取Amazon S3对象。wwmorgan on#clojure向我推荐了一个从根本上符合您声明的解决方案:“我倾向于从网络中创建一个序列行,然后将其交给我使用的序列(序列行(create-buffered-reader-for-s3-object“object name.csv”))为了获得延迟序列,然后将每一行包装在自己的StringReader中,然后将其传递给自己的CsvMapReader。我必须为每一行创建一个CsvMapReader,而不是将读取整个文件的读取器传递给CsvMapReader。我的最终解决方案如下所示:(行seq amazon-s3-reader)[(map#(.read(CsvMapReader.(java.io.StringReader.line)CsvPreference/STANDARD#PREFERENCE))行])上面的代码没有解析,但它概述了一般的解决方案:它返回解析的CSV数据和原始行,让我在没有奇怪交互的情况下访问它们。呃。对我的解决方案进行的广泛测试显示带宽消耗比我想要的高4倍,而不是我使用两个单独的读卡器时得到的2倍。我认为seq'ing a network resources的问题在于,每个seq被消耗的地方都会导致资源一次又一次地从网络中被拉下来,从而导致我遇到的高带宽消耗问题。 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