"clojure.lang.PersistentVector cannot be cast to java.lang.String"

2,147 views
Skip to first unread message

Vincent Liard

unread,
May 20, 2011, 9:22:22 AM5/20/11
to clojure
Hello,

I would like to open an excel file from multipart data without saving
it (forbidden by Google Appengine). I have adapted the incanter's
read-xls which reads from actual files to read-xls-stream which takes
an object of the same kind that with-open provides.

I wanted to write something like the following but I get the error
message: "clojure.lang.PersistentVector cannot be cast to
java.lang.String". I don't really understand the mismatch and how to
convert one type to the other...

(use [appengine-magic.multipart-params :only (wrap-multipart-params)])

(defn retailer-stock-update []
(wrap-multipart-params
(fn [req]
(let [xls (get (:params req) "stock-xls")]
(with-in-str [str (:bytes xls)]
(read-xls-stream str))))))

As far as I have understood, (:bytes xls) is seen as a java byte
array, since (class (:bytes xls)) displays "class [B", but I don't get
how it is related to the previous error message. I guess I sould
manually convert (:bytes xls) to the type with-in-str wants but I
don't know how.

I have given a look to
http://code.google.com/appengine/kb/java.html#fileforms but I guess
clojure can do without explicit call to FileItemStream and
FileItemIterator. Anyway, I didn't manage to deal with it either.

Could you give me a clue?

Thanks in advance,

Vincent

David Nolen

unread,
May 20, 2011, 9:55:22 AM5/20/11
to clo...@googlegroups.com
On Fri, May 20, 2011 at 9:22 AM, Vincent Liard <vincen...@free.fr> wrote:
(defn retailer-stock-update []
 (wrap-multipart-params
  (fn [req]
    (let [xls (get (:params req) "stock-xls")]
      (with-in-str [str (:bytes xls)]
        (read-xls-stream str))))))

You usage of with-in-str is not correct, you're passing a vector where it expects a string. I don't know enough about appengine-magic to comment on the rest.

David

Ken Wesson

unread,
May 20, 2011, 9:59:35 AM5/20/11
to clo...@googlegroups.com
On Fri, May 20, 2011 at 9:22 AM, Vincent Liard <vincen...@free.fr> wrote:
> (defn retailer-stock-update []
>  (wrap-multipart-params
>   (fn [req]
>     (let [xls (get (:params req) "stock-xls")]
>       (with-in-str [str (:bytes xls)]
>         (read-xls-stream str))))))
>
> As far as I have understood, (:bytes xls) is seen as a java byte
> array, since (class (:bytes xls)) displays "class [B"

That is correct. So try replacing the last two lines with:

(with-open [str (ByteArrayInputStream. (:bytes xls))]
(read-xls-stream str))

The exception is because with-in-str is expecting a single string
argument, not a binding vector; with-in-str temporarily rebinds *in*
to read from a string rather than binding an arbitrary stream.

--
Protege: What is this seething mass of parentheses?!
Master: Your father's Lisp REPL. This is the language of a true
hacker. Not as clumsy or random as C++; a language for a more
civilized age.

Vincent Liard

unread,
May 20, 2011, 10:22:40 AM5/20/11
to clo...@googlegroups.com
At Fri, 20 May 2011 09:55:22 -0400,

David Nolen wrote:
> On Fri, May 20, 2011 at 9:22 AM, Vincent Liard <vincen...@free.fr> wrote:
> [...]

>       (with-in-str [str (:bytes xls)]
>         (read-xls-stream str))))))
>
> You usage of with-in-str is not correct, you're passing a vector where it expects a string. I don't know
> enough about appengine-magic to comment on the rest.

You're right, thanks. I noticed this too late.

Vincent Liard

unread,
May 20, 2011, 10:32:28 AM5/20/11
to clo...@googlegroups.com
At Fri, 20 May 2011 09:59:35 -0400,

Ken Wesson wrote:
>
> On Fri, May 20, 2011 at 9:22 AM, Vincent Liard <vincen...@free.fr> wrote:
> > (defn retailer-stock-update []
> >  (wrap-multipart-params
> >   (fn [req]
> >     (let [xls (get (:params req) "stock-xls")]
> >       (with-in-str [str (:bytes xls)]
> >         (read-xls-stream str))))))
> >
> > As far as I have understood, (:bytes xls) is seen as a java byte
> > array, since (class (:bytes xls)) displays "class [B"
>
> That is correct. So try replacing the last two lines with:
>
> (with-open [str (ByteArrayInputStream. (:bytes xls))]
> (read-xls-stream str))
>
> The exception is because with-in-str is expecting a single string
> argument, not a binding vector; with-in-str temporarily rebinds *in*
> to read from a string rather than binding an arbitrary stream.

Thank you! I eventually noticed my error on the with-in-str call, but
I would never have found ByteArrayInputStream. The clojure newcomer
should be ready to learn java :) Many thanks for your help!

Vincent

Ken Wesson

unread,
May 20, 2011, 10:48:24 AM5/20/11
to clo...@googlegroups.com

You're welcome.

sindhu hosamane

unread,
Apr 24, 2014, 12:08:44 PM4/24/14
to clo...@googlegroups.com, vincen...@free.fr
I have the same error above "clojure.lang.PersistentVector cannot be cast to java.lang.String" . but when i use ByteArrayInputStream have "clojure.lang.PersistentList cannot be cast to java.lang.String" . don't know how to fix it .I want to retrieve data between 2 timestamp values . i have some 800 rows in my data .My code snipper below: Please let me know where am i wrong .

(def info-tap
  (<- [?timestamp ?value]
      ((select-fields info ["?timestamp" "?value"]) ?timestamp ?value)))

   (def datefrom "12:05:2010 10:00:00")
   (def custom-formatter (f/formatter "dd:MM:yyyy HH:mm:ss"))
   (def start-value (ct/to-long (f/parse custom-formatter datefrom)))

   (def dateto "12:05:2010 11:00:00")
   (def end-value (ct/to-long (f/parse custom-formatter dateto)))

   (defmacro convert-to-long [a]
       (ct/to-long (f/parse custom-formatter a)) )

  (?<- (stdout)[?timestamp ?value](info-tap ?timestamp ?value)
     (>  convert-to-long[?timestamp]   start-value)
     (<  convert-to-long[?timestamp]   end-value))


I my code i am converting timestamp strings to long (numbers ) so that i can compare .But ?timestamp field have 800 entries (rows) of timestamps . but custom-formatter is expecting a string. How do i deal with it .



Reply all
Reply to author
Forward
0 new messages