Это то, что у меня есть до сих пор. Разве это не все, что вам нужно? Я продолжаю получать ошибку "Ошибка: Unbound module Std"
let r file =
let chan = open_in file in
Std.input_list (chan)
Это то, что у меня есть до сих пор. Разве это не все, что вам нужно? Я продолжаю получать ошибку "Ошибка: Unbound module Std"
let r file =
let chan = open_in file in
Std.input_list (chan)
Если у вас нет Extlib, установленного (и, по-видимому, вы не используете это сообщение выше), то обычно это сделал что-то вроде этого:
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 ;;
Если у вас есть Extlib:
let read_file filename =
let chan = open_in filename in
Std.input_list chan
... который в значительной степени отличается тем, что у вас есть.
Если у вас есть библиотека Batteries-included, вы можете прочитать файл в Enum.t и перебрать его следующим образом:
let filelines = File.lines_of filename in
Enum.iter ( fun line -> (*Do something with line here*) ) filelines
Если у вас установлена библиотека OCaml Core, то она проста:
open Core.Std
let r file = In_channel.read_lines file
Если у вас установлен corebuild
, вы можете просто скомпилировать свой код с ним:
corebuild filename.byte
если ваш код находится в файле с именем filename.ml
.
Если у вас нет OCaml Core или вы не хотите его устанавливать или какую-либо другую стандартную библиотечную реализацию, то, конечно же, вы можете реализовать его с помощью стандартной библиотеки Vanam OCaml. Существует функция input_line
, определенная в модуле Pervasives
, которая автоматически открывается во всех программах OCaml (т.е. Все ее определения доступны без дополнительных разъяснений с именем модуля). Эта функция принимает значение типа in_channel
и возвращает строку, которая была считана с канала. С помощью этой функции вы можете реализовать требуемую функцию:
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 []
Эта реализация использует рекурсию и гораздо более естественна для программирования OCaml.
Здесь рекурсивное решение с использованием 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);;
Применение:
let all_lines = read_all_lines "input.txt";;
Тем не менее, я бы предпочел поток по очереди:
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;;
Использование:
let read_next = make_reader "input.txt";;
let next_line = read_next ();;
И может быть немного обледенения:
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};;
Применение:
let r = make_reader "input.txt";;
let next_line = r.read_next ();;
Надеюсь, это поможет!
Это считывает строки файлов и печатает каждый из них:
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
Std.input_list
, по-видимому, требует Extlib, который вы должны установить в своей системе (libextlib-ocaml
и libextlib-ocaml-dev
в системах Debian).
Еще один стиль для чтения строк из файла с помощью Scanf "строковое обозначение" и символ нулевой ширины. Это похоже на традиционный императивный стиль.
open Scanf
open Printf
(* little helper functions *)
let id x = x
let const x = fun _ -> x
let read_line file = fscanf file "%[email protected]\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
Примечание:
Вот простое рекурсивное решение, которое не накапливает строки или не использует внешние библиотеки, но позволяет вам читать строку, обрабатывать ее с помощью функции, читать следующую рекурсивно до тех пор, пока не сделать, а затем выйти чисто. Функция выхода закрывает открытую дескриптор файла и сигнализирует об успешной работе вызывающей программы.
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;;