Подтвердить что ты не робот

Как читать строки из текстового файла в OCaml?

Это то, что у меня есть до сих пор. Разве это не все, что вам нужно? Я продолжаю получать ошибку "Ошибка: Unbound module Std"

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

Ответ 1

Если у вас нет 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

Ответ 2

Если у вас установлена ​​библиотека 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.

Ответ 3

Здесь рекурсивное решение с использованием 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 ();;

Надеюсь, это поможет!

Ответ 4

Это считывает строки файлов и печатает каждый из них:

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

Ответ 5

Std.input_list, по-видимому, требует Extlib, который вы должны установить в своей системе (libextlib-ocaml и libextlib-ocaml-dev в системах Debian).

Ответ 6

Еще один стиль для чтения строк из файла с помощью 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

Примечание:

  • read_line игнорировать один трейлинг \n, поэтому, если последний символ вашего файла is\n, может показаться, что вы пропустили последнюю пустую строку.
  • при использовании Scanf из-за буферизации не смешивать другие показания низкого уровня на одном канале, иначе это приведет к странному поведению.

Ответ 7

Вот простое рекурсивное решение, которое не накапливает строки или не использует внешние библиотеки, но позволяет вам читать строку, обрабатывать ее с помощью функции, читать следующую рекурсивно до тех пор, пока не сделать, а затем выйти чисто. Функция выхода закрывает открытую дескриптор файла и сигнализирует об успешной работе вызывающей программы.

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;;