2016-08-01 29 views
2

Ich möchte meine OCAML-Anwendung direkt herunterladen, dekomprimieren (gzip) und dann die resultierende Textdatei Zeile für Zeile ohne eine temporäre Datei und externe Programme zu verarbeiten.Wie kann ich eine gzip-Datei in OCaml herunterladen, dekomprimieren und verarbeiten?

Die Bibliotheken Ich sah sind cohttp, ocurl und camlzip. Leider habe ich keine gute Möglichkeit gefunden, sie zusammenzuarbeiten.

Wie würde OCaml dies erreichen?

+0

Ich finde keine solche Bibliothek im OPAM Repo. Wahrscheinlich gibt es in diesem Moment keine. – camlspotter

+0

Was ist mit einer temporären Datei falsch? – PatJ

+0

Ich habe nur gehofft, dass es einen einfachen Weg wie in vielen anderen Sprachen gibt, zB: new GzipInputStream (url.openStream()). Foreach (println) – gruenewa

Antwort

4

Sie können ocurl und camlzip zusammenarbeiten, indem Sie Rohre und Gewinde verwenden. Proof of Concept:

#use "topfind";; 
#thread;; 
#require "unix";; 
#require "curl";; 
#require "zip";; 

let() = Curl.(global_init CURLINIT_GLOBALALL) 

let download url oc = 
    let open Curl in 
    let h = init() in 
    setopt h (CURLOPT_URL url); 
    setopt h (CURLOPT_WRITEFUNCTION (fun x -> output_string oc x; String.length x)); 
    perform h; 
    cleanup h 

let read_line really_input = 
    let buf = Buffer.create 256 in 
    try 
    while true do 
     let x = " " in 
     let() = really_input x 0 1 in 
     if x = "\n" then raise Exit else Buffer.add_string buf x; 
    done; 
    assert false 
    with 
    | Exit -> Buffer.contents buf 
    | End_of_file -> if Buffer.length buf = 0 then raise End_of_file else Buffer.contents buf 

let curl_gzip_iter f url = 
    let ic, oc = Unix.pipe() in 
    let ic = Unix.in_channel_of_descr ic and oc = Unix.out_channel_of_descr oc in 
    let t = Thread.create (fun() -> download url oc; close_out oc)() in 
    let zic = Gzip.open_in_chan ic in 
    let zii = Gzip.really_input zic in 
    let() = 
    try 
     while true do 
     let() = f (read_line zii) in() 
     done; 
     assert false 
    with 
    | End_of_file ->() 
    in 
    Gzip.close_in zic; 
    Thread.join t 

let() = curl_gzip_iter print_endline "file:///tmp/toto.gz" 

Es wird schmerzhaft, wenn man mit Fehlern umgehen muss.