2

I want to redirect the standard input in my Clojure benchmark. I have passed the file as an argument and I am trying to find the equivalant code in java: System.setIn(new FileInputStream(filename)); but for Clojure.

The main issue is that I use the DaCapo suite to calculate the performance of Benchmark and the method that loads the benchmark does not recognize special characters like "<" in contrast to the cmd (running the benchmark's jar directly from the cmd..).

This is what I am trying to do..but still does not work.. I think that br has the standard input from the in and it is used by the rest of the program. How can I change the in while I have in the args the desired path, so I can run the benchmark correctly? This is my effort with the "system/setin"

(defn -main [& args]
  (let [max-dna-chars-per-line 60
    jk  (with-open [is (clojure.java.io/input-stream (first args))]
        (System/setIn is))
        br (java.io.BufferedReader. *in*)
        bw (java.io.BufferedWriter. *out* (* 16 8192)) ; 16 * default size, I think
        ;; We could use the map complement-dna-char-map instead of
        ;; complement-dna-char-fn, but when I tested that, the program
        ;; spent a lot of time running the hashCode method on
        ;; characters.  I'm hoping this is faster.
        complement-dna-char-vec (make-vec-char-mapper complement-dna-char-map)]
    (loop [[desc-str dna-seq-str more] (fasta-slurp-br br)]
      (println-string-to-buffered-writer bw desc-str)
      (print-reverse-complement-of-str-in-lines bw dna-seq-str
                                                complement-dna-char-vec
                                                max-dna-chars-per-line)
      (when more
        (recur (fasta-slurp-br br))))
    (. bw flush))) 
Tunaki
  • 132,869
  • 46
  • 340
  • 423
Spyros
  • 35
  • 5

2 Answers2

1

System.in is normally wrapped in *in*. It is a dynamic binding intended to be rebound in local scope with binding, like so:

(with-open [is (clojure.java.io/reader "/tmp/foo.txt")]
  (binding [*in* is]
    (println (read-line))))

Note that it is a wrapper of System.in, not System.in itself, and changing this binding does not change System.in. It only affects the Clojure functions that use *in*, such as read-line here.

If you are calling some Java code that wants to read System.in, you have to call System.setIn:

(with-open [is (clojure.java.io/input-stream filename)]
  (System/setIn is)
  (do-stuff))

These are the options in Clojure and Java, but I still am not sure I understand your use case. Please clarify in comments if that does not quite make sense.

EDIT: Regarding your program, if you are creating the buffers, do you really need to create them off *in*? What's the difference vs. just opening your own stream?

Konrad Garus
  • 53,145
  • 43
  • 157
  • 230
  • I have a harness class that loads the clojure benchmark revcomp. The args that pass in the benchmark is an array. In this array I can have the path file of the input of this benchmark or its content itself. If I run the jar of revcomp the arguments that it takes are "< filename". However due to the java that cannot recognize the "<" when I load the benchmark from the suite (I have it in my eclipse), I need to find some way to change the redirection (the standard input) inside the clojure code in order to run it. Here is where I am stuck: – Spyros Jul 18 '14 at 14:52
  • (defn -main [& args] (let [max-dna-chars-per-line 60 (with-open [is (clojure.java.io/reader (first args))] (binding [*in* is] (println (read-line)))) br (java.io.BufferedReader. *in*) bw (java.io.BufferedWriter. *out* (* 16 8192)) ; 16 * default size, I think ;; We could use the map complement-dna-char-map instead of ;; complement-dna-char-fn, but when I tested that, the program ;; spent a lot of time running the hashCode method on ;; characters. I'm hoping this is faster. – Spyros Jul 18 '14 at 14:53
  • I have the same problem in regexdna benchmark too. They both (regexdna and revcomp) take as arguments "< filename.txt" in the cmd. However the benchmark suite does not recognise the "<" so I have to change the standard input manually inside the benchmark...(I think so..) – Spyros Jul 18 '14 at 15:28
  • `< filename` is a shell thing, not Java. I think I'm still missing a piece here. If you're calling Clojure from outside, it reads System.in same as Java, and perhaps its that outside thing that needs to be figured out. – Konrad Garus Jul 18 '14 at 16:59
  • System.setIn(new FileInputStream(args[0])); So, if I change the System.In in the revcomp harness class that loads the revcomp benchmark, the System.In will not change? – Spyros Jul 18 '14 at 17:35
  • If you call `System.setIn`, System IN does change to what you set there. – Konrad Garus Jul 21 '14 at 06:16
0

After trying so many different things I finally found the answer...

I had to use the file reader inside the buffer so the code is like this:

(defn -main [& args]
  (let [max-dna-chars-per-line 60
        br (java.io.BufferedReader. (clojure.java.io/reader (first args)))
        bw (java.io.BufferedWriter. *out* (* 16 8192)) ; 16 * default size, I think

where the args contain the filename ...

Spyros
  • 35
  • 5