How to implement "appendFile" function? - ocaml

I can use the following function to overwrite a text file:
let writeFile ~filename:fn s =
let oc = open_out fn in
output_string oc s;
close_out oc ;;
Howeve, i donot know how to append a line to a text file ?

You could pass additional mode flag Open_append to open_out_gen function:
let _ =
let oc = open_out_gen [Open_creat; Open_text; Open_append] 0o640 "a.txt" in
output_string oc "append\n";
close_out oc

This is what I do:
let append_string path s =
let chan = open_out_gen [Open_wronly; Open_creat] 0o666 path
in let len = out_channel_length chan
in
begin
seek_out chan len;
output_string chan s;
close_out chan;
end

Related

Ocaml read list from file

I need to take list of list of integers from file and use my func combine to it. See please on my code, where is my mistake?
# let f x l = List.filter ((<>) x) l
let rec comb = function
| [] -> []
| x::[] -> [[x]]
| l ->
List.fold_left (fun acc x -> acc # List.map (fun p -> x::p) ( comb ( f x l))) [ ] l ;;
let file = "example.dat"
let message = [[1;2];[3;4]]
let () =
let oc = open_out file in
fprintf oc "%s\n" message;
close_out oc;
let ic = open_in file in
try
let line = input_line ic in
print_endline line;
flush stdout;
close_in ic
with e ->
close_in_noerr ic;
raise e;;
Compilation fails here : fprintf oc "%s\n" message; because %s expects a string whereas message is of type int list list.
You have to iterate fprintf accross the list :
List.iter (fun l ->
List.iter (fun i -> fprintf oc "%d ") l) message;
The complete code :
let file = "example.dat"
let message = [[1;2];[3;4]]
let () =
let oc = open_out file in
List.iter (fun l -> List.iter (fun x -> fprintf oc "%d\n" x) l) message ;
close_out oc;
let ic = open_in file in
try
let line = input_line ic in
print_endline line;
flush stdout;
close_in ic
with e ->
close_in_noerr ic;
raise e;;

How to create a program combining both Parser and Lexer

I want to build a compiler using Ocamllex/Ocamlyacc and I want to create a main program to combine both of my OcamlParser and OcamlLexer. The thing is that I know how to do it using an input in the command line like the following code:
let _ =
try
let lexbuf = Lexing.from_channel stdin in
while true do
let result = Parser.main Lexer.token lexbuf in
print_int result; print_newline(); flush stdout
done
with Lexer.Eof ->
exit 0
But how can I do if I want to use a file as an input; I tried something like this:
let file ="add.txt"
let _ =
let ic = open_in file in
try
let lexbuf = Lexing.from_channel file in
while true do
let result = Parser.main Lexer.token lexbuf in
print_int result; print_newline(); flush stdout
done
with Lexer.Eof ->
exit 0
But it's not really working.
The following code works for me. In your version, you have some syntax errors.
let _ =
let file ="add.txt" in
let i = open_in file in
try
let lexbuf = Lexing.from_channel i in
while true do
let result = Parser.main Lexer.token lexbuf in
print_int result; print_newline(); flush stdout
done
with Lexer.Eof ->
exit 0
Putting 1+2 in "add.txt" gives me 3.

executing functions in OCaml from fileinput of OCaml

How to execute (in OCaml) the lines we get from fileinput described below?
let read_file filename =
let lines = ref [] in
let chan = open_in filename in
try
while true; do
lines := input_line chan :: !lines
done; []
with End_of_file ->
close_in chan;
List.rev !lines
It's not clear (to me) what you're asking. If you have a file containing some OCaml code, one way to run it is to load it into the toplevel. First, create a file named fileread.ml containing your text. Then (from the command line):
$ ocaml
OCaml version 4.01.0
# #use "fileread.ml";;
val read_file : string -> string list = <fun>
# read_file "fileread.ml";;
- : string list =
["let read_file filename ="; "let lines = ref [] in";
"let chan = open_in filename in"; "try"; "while true; do";
"lines := input_line chan :: !lines"; "done; []"; "with End_of_file ->";
"close_in chan;"; "List.rev !lines"]
If, instead, you're asking how an OCaml program can load text and execute it as OCaml code, this isn't something OCaml can do directly. Naturally there are ways to do it; the toplevel is after all an OCaml program. But there's no simple function in OCaml for executing text, as there is in many interpreted languages (often being named eval).
If, on the third hand, you're asking how to compile and run your code, add a line like this to the end of fileread.ml:
let () = List.iter print_endline (read_file "fileread.ml")
Then compile and run as follows:
$ ocamlc -o fileread fileread.ml
$ fileread
let read_file filename =
let lines = ref [] in
let chan = open_in filename in
try
while true; do
lines := input_line chan :: !lines
done; []
with End_of_file ->
close_in chan;
List.rev !lines
let () = List.iter print_endline (read_file "fileread.ml")

print string buffer from file contents

I want to print the contents of a file. I tried to use a string buffer:
let ch = open_in "myfile.txt" in
let buf = Buffer.create 1024 in
(try Buffer.add_channel buf ch max_int with _ -> ());
close_in ch;
let string = Buffer.contents buf
print_endline string
this just gives me a syntax error.
How can I do this?
You need to give the right channel length:
let ic = open_in "foo" in
let len = in_channel_length ic in
let buf = Buffer.create len in
Buffer.add_channel bif ic len;
let str = Buffer.contents b in
print_endline str
The only syntax error I see is a missing in after let string = Buffer.contents buf.
The purpose of Buffer.add_channel is to add exactly the given number of characters from the given channel to the buffer. Unless your file "myfile.txt" is exceptionally large, the buffer will be empty when you print it out.
In fact on my system (a 64-bit system), max_int is so large that Buffer.add_channel doesn't even try to read that much data. It raises an Invalid_argument exception.

return values from file - ocaml

I am trying to read a file and return the element read from the file as an input to another function.
How can I return a value when I am reading from the file??
I tried everything I am aware of and am still hopelessly lost.
My code is as follows:
let file = "code.txt";;
let oc = open_out file in (* create or truncate file, return channel *)
fprintf oc "%s\n" (play); (* write code to file returned from calling (play) function *)
close_out oc ;;
(*read from file*)
let read l=
let f x =
let ic = open_in file in
let line = input_line ic in (* read line from in_channel and discard \n *)
print_endline line; (* write the result to stdout *)
((x ^ line) :: l);
flush stdout;
close_in ic ;
in
f l
;;
prompt: read;; function call outputs:
- : unit = ()
My file contains a string which is a code needed as input for another function.
Please help. I am not sure where I am going wrong.
Thank you.
If multiple expressions are sequenced together using ; the value of the whole expression is the value of the last expression in the sequence.
So if you have something like ((x ^ line) :: l); close_in ic the value of that expression is the value of close_in ic, which is ().
Obviously that's not what you want. In order to make ((x ^ line) :: l) the result of the whole expression, you should place it after close_in ic.