ventajas reasonml online desventajas caracteristicas ocaml

ocaml - online - reasonml



¿Cómo leo en líneas de un archivo de texto en OCaml? (7)

Esto es lo que tengo hasta ahora. ¿No es esto todo lo que necesitas? Sigo recibiendo el error "Error: Desvinculación del módulo estándar"

let r file = let chan = open_in file in Std.input_list (chan)


Aquí hay una solución recursiva simple que no acumula las líneas ni usa bibliotecas externas, sino que le permite leer una línea, procesarla usando una función, leer la siguiente recursivamente hasta que termine y luego salir limpiamente. La función de salida cierra el identificador de archivo abierto y señala el éxito al programa de llamada.

let read_lines file process = let in_ch = open_in file in let rec read_line () = let line = try input_line in_ch with End_of_file -> exit 0 in (* process line in this block, then read the next line *) process line; read_line (); in read_line ();; read_lines some_file print_endline;;


Aquí hay una solución recursiva usando Scanf:

let read_all_lines file_name = let in_channel = open_in file_name in let rec read_recursive lines = try Scanf.fscanf in_channel "%[^/r/n]/n" (fun x -> read_recursive (x :: lines)) with End_of_file -> lines in let lines = read_recursive [] in let _ = close_in_noerr in_channel in List.rev (lines);;

Uso:

let all_lines = read_all_lines "input.txt";;

Sin embargo, prefiero transmitir línea por línea:

let make_reader file_name = let in_channel = open_in file_name in let closed = ref false in let read_next_line = fun () -> if !closed then None else try Some (Scanf.fscanf in_channel "%[^/r/n]/n" (fun x -> x)) with End_of_file -> let _ = close_in_noerr in_channel in let _ = closed := true in None in read_next_line;;

Uso:

let read_next = make_reader "input.txt";; let next_line = read_next ();;

Y puede ser un poco de glaseado:

type reader = {read_next : unit -> string option};; let make_reader file_name = let in_channel = open_in file_name in let closed = ref false in let read_next_line = fun () -> if !closed then None else try Some (Scanf.fscanf in_channel "%[^/r/n]/n" (fun x -> x)) with End_of_file -> let _ = close_in_noerr in_channel in let _ = closed := true in None in {read_next = read_next_line};;

Uso:

let r = make_reader "input.txt";; let next_line = r.read_next ();;

¡Espero que esto ayude!


Esto lee las líneas del archivo e imprime cada una de ellas:

open Core.Std let handle_line line = printf "Your line: %s /n" line let () = let file_to_read = "./file_to_read.txt" in let lines = In_channel.read_lines file_to_read in List.iter ~f: handle_line lines


Otro estilo para leer líneas de un archivo utilizando la "indicación de cadena" de Scanf y el carácter de ancho cero. Es como el estilo imperativo tradicional.

open Scanf open Printf (* little helper functions *) let id x = x let const x = fun _ -> x let read_line file = fscanf file "%s@/n" id let is_eof file = try fscanf file "%0c" (const false) with End_of_file -> true let _ = let file = open_in "/path/to/file" in while not (is_eof file) do let s = read_line file in (* do something with s *) printf "%s/n" s done; close_in file

NOTA:

  1. read_line ignore un final / n, por lo que si el último carácter de su archivo es / n, puede parecer que ha perdido la última línea vacía.
  2. cuando utilice Scanf, debido a la búfer, no mezcle otras lecturas de bajo nivel en el mismo canal, de lo contrario se producirá un comportamiento extraño.

Si no tiene Extlib instalado (y aparentemente no se basa en el mensaje de error anterior), generalmente se hace algo como esto:

let read_file filename = let lines = ref [] in let chan = open_in filename in try while true; do lines := input_line chan :: !lines done; !lines with End_of_file -> close_in chan; List.rev !lines ;;

Si tiene Extlib:

let read_file filename = let chan = open_in filename in Std.input_list chan

... que es más o menos lo que tienes.

Si tiene la biblioteca Batteries-included puede leer un archivo en un Enum.t e iterar sobre él de la siguiente manera:

let filelines = File.lines_of filename in Enum.iter ( fun line -> (*Do something with line here*) ) filelines


Si tiene instalada la biblioteca Core de OCaml, es tan simple como:

open Core.Std let r file = In_channel.read_lines file

Si tiene instalado corebuild , simplemente puede compilar su código con él:

corebuild filename.byte

si su código reside en un archivo llamado filename.ml .

Si no tiene OCaml Core, o no desea instalarlo, o alguna otra implementación de biblioteca estándar, entonces, por supuesto, puede implementarlo utilizando una biblioteca estándar de vainilla OCaml. Existe una función input_line , definida en el módulo Pervasives , que se abre automáticamente en todos los programas OCaml (es decir, se puede acceder a todas sus definiciones sin más aclaraciones con un nombre de módulo). Esta función acepta un valor de tipo in_channel y devuelve una línea que se leyó desde el canal. Usando esta función puedes implementar la función requerida:

let read_lines name : string list = let ic = open_in name in let try_read () = try Some (input_line ic) with End_of_file -> None in let rec loop acc = match try_read () with | Some s -> loop (s :: acc) | None -> close_in ic; List.rev acc in loop []

Esta implementación utiliza la recursión y es mucho más natural para la programación OCaml.


Std.input_list aparentemente requiere Extlib , que debe instalar en su sistema ( libextlib-ocaml y libextlib-ocaml-dev en los sistemas Debian).