The Pervasive.in_channel in the ocaml std library is not extensible. If you want to mix different in_channel, for example, one from Pervasive and on from the Gzip library, then you are in trouble. The good fellows of extlib solved this problem providing an extensible stream data type in the IO library [1] . This is a small example using that module.
let gzip_open_in file =
let ch = Gzip.open_in file in
IO.create_in
~read:(fun () -> Gzip.input_char ch)
~input:(Gzip.input ch)
~close:(fun () -> Gzip.close_in ch)
let std_open_in file =
let ch = open_in file in
IO.create_in
~read:(fun () -> input_char ch)
~input:(input ch)
~close:(fun () -> close_in ch)
let main () =
let file = Sys.argv.(1) in
let ch =
if Filename.check_suffix file ".gz" then gzip_open_in file
else std_open_in file
in
try
while true do
print_endline (IO.read_line ch)
done
with End_of_file ->
IO.close_in ch
;;
main ();;
untested compile commands (I use ocamlbuild + custom myocamlbuild.ml):
ocamlfind ocamldep -package extlib -package zip -modules test.ml > test.ml.depends
ocamlfind ocamlc -c -package extlib -package zip -o test.cmo test.ml
ocamlfind ocamlc -linkpkg -package extlib -package zip test.cmo -o test.byte
[1] http://ocaml-lib.sourceforge.net/doc/IO.html
Comments
Batteries
Or you can use OCaml Batteries Included (which both includes extlib and offers access to the features of ocamlzip). OCaml Batteries Included defines, among other things, your gzip_open_in (as GZip.open_in) and your std_open_in (as File.open_in).
Enjoy :)