How to Read a Line from File in Ocaml? - ocaml

I am in trouble with OCaml, because I want to read the lines from a text file, and I'm using this code to do the job:
let parse3ac() =
let lines = ref "" in
let chan = open_in "3ac" in
try
while true do
lines := input_line chan;
print_string(!lines);
done;
with End_of_file -> close_in chan;print_string("End Of File");;
But it only prints in the console "End Of File", but the lines from the file, doesn't appears.
What is wrong with this code guys?
Thks 4 all!!!
Edited:
Actually I have discovered the reason it isn't working.
It is very simple, the code above works very well, but the file "3ac" that I had created previously using OCaml, wasn't properly closed, and then it would be impossible to read the file.
Thanks everybody, and like I said before the code works so everyone can use that.
Thanks .

This code works, I tested it and it writes the lines of the file 3ac (without newlines as you don't print them) and then "End Of File". Are you sure the file 3ac is not empty ?

Related

Problem in detecting EOF (end of file) while giving input in a file via terminal

I'm running my code and give inputs via a .txt file(./a.out<input.txt ), but it seems it does not recognize end of file.
when I copy the contents in ubuntu it works. I think that files were created in MAC.
EOF is like CTRL+C in terminal so it should stop executing the code but the last command continuously is parsing as input. I can not change the file (It is test file and the format is unchangeable.). Can anyone please help me with this problem?
I have attached my code, but I think that is the file problem.
EDIT: I found the solution. By adding
if(!getline(cin, s)){
break;
}
or similar lines, the problem will be fixed!
I found the solution. By adding
if(!getline(cin, s)){
break;
}
or similar lines, the problem will be fixed!

OCaml string length limitation when reading from stdin\file

As part of a Compiler Principles course I'm taking in my university, we're writing a compiler that's implemented in OCaml, which compiles Scheme code into CISC-like assembly (which is just C macros).
the basic operation of the compiler is such:
Read a *.scm file and convert it to an OCaml string.
Parse the string and perform various analyses.
Run a code generator on the AST output from the semantic analyzer, that outputs text into a *.c file.
Compile that file with GCC and run it in the terminal.
Well, all is good and well, except for this: I'm trying to read an input file, that's around 4000 lines long, and is basically one huge expressions that's a mix of Scheme if & and.
I'm executing the compiler via utop. When I try to read the input file, I immediately get a stack overflow error message. It is my initial guess that the file is just to large for OCaml to handle, but I wasn't able to find any documentation that would support this theory.
Any suggestions?
The maximum string length is given by Sys.max_string_length. For a 32-bit system, it's quite short: 16777211. For a 64-bit system, it's 144115188075855863.
Unless you're using a 32-bit system, and your 4000-line file is over 16MB, I don't think you're hitting the string length limit.
A stack overflow is not what you'd expect to see when a string is too long.
It's more likely that you have infinite recursion, or possibly just a very deeply nested computation.
Well, it turns out that the limitation was the amount of maximum ram the OCaml is configured to use.
I ran the following command in the terminal in order to increase the quota:
export OCAMLRUNPARAM="l=5555555555"
This worked like a charm - I managed to read and compile the input file almost instantaneously.
For reference purposes, this is the code that reads the file:
let file_to_string input_file =
let in_channel = open_in input_file in
let rec run () =
try
let ch = input_char in_channel in ch :: (run ())
with End_of_file ->
( close_in in_channel;
[] )
in list_to_string (run ());;
where list_to_string is:
let list_to_string s =
let rec loop s n =
match s with
| [] -> String.make n '?'
| car :: cdr ->
let result = loop cdr (n + 1) in
String.set result n car;
result
in
loop s 0;;
funny thing is - I wrote file_to_string in tail recursion. This prevented the stack overflow, but for some reason went into an infinite loop. Oh, well...

MFC C++ Always returning EOF when I have access to file

I am currently stuck in this problem that I do not have any idea to fix. It is regarding a previous question that I have asked here before. But I will reiterate again as I found out the problem but have no idea to fix it.
My program accesses a text file that is updated constantly every millisecond 24/7. It grabs the data line by line and does comparison on each of the line. If any thing is "amiss"(defined by me), then I log that data into a .csv file. This program can be run at timed intervals(user defined).
My problem is that this program works perfectly fine on my computer but yet it doesnt on my clients computer. I have debug the program and these are my findings. Below is my code that I have reduced as much possible to ease the explanation process
int result;
char ReadLogLine[100000] = "";
FILE *readLOG_fp;
CString LogPathName;
LogPathName = Source_Folder + "\\serco.log"; //Source_Folder is found in a .ini file. Value is C:\\phython25\\xyratex\\serco_logs
readLOG_fp = fopen(LogPathName, "r+t");
while ((result = fscanf(readLOG_fp, "%[^\n]\n", ReadLogLine)) != EOF) // Loops through the file till it reaches the end of file
{
Sort_Array(); // Here is a function to sort the different lines that I grabbed from the text file
Comp_State(); // I compare the lines here and store them into an array to be printed out
}
fclose(readLOG_fp);
GenerateCSV(); // This is my function to generate the csv and print everything out
In Sort_Array(), I sort the lines that I grab from the text file as they could be of different nature. For example,
CStringArray LineType_A, LineType_B, LineTypeC, LineTypeD;
if (ReadLogLine == "Example line a")
{
LineType_A.add(ReadLogLine);
}
else if (ReadLogLine == "Example line b")
{
LineType_B.add(ReadLogLine);
}
and so on.
In CompState(), I compare the different values within each LineType array to see if there are any difference. If it is different, then I store them into a seperate array to print. A simple example would be.
CStringArray PrintCSV_Array;
for (int i = 0; i <= LineType_A.GetUpperBound(); i++)
{
if (LineType_A.GetAt(0) == LineType_A.GetAt(1))
{
LineType_A.RemoveAt(0);
}
else
{
LineType_A.RemoveAt(0);
PrintCSV_Array.Add(LineType_A.GetAt(0);
}
}
This way I dont have an infinite amount of data in the array.
Now to the GenerateCSV function, it is just a normal function where I create a .csv file and print whatever I have in the PrintCSV_Array.
Now to the problem. In my client's computer, it seems to not print anything out to the CSV. I debugged the program and found out that it keeps failing here.
while ((result = fscanf(readLOG_fp, "%[^\n]\n", ReadLogLine)) != EOF) // Loops through the file till it reaches the end of file
{
Sort_Array(); // Here is a function to sort the different lines that I grabbed from the text file
Comp_State(); // I compare the lines here and store them into an array to be printed out
}
fclose(readLOG_fp);
It goes into the while loop fine as I did some error checking there in the actual program. The moment it goes into the while loop it breaks out of it suggesting to me it reach EOF for some reason. When that happens, the program has no chance to go into both the Sort_Array and Comp_State functions thus giving me a blank PrintCSV_Array and nothing to print out.
Things that I have checked is that
I definitely have access to the text file.
My thoughts were because the text file is updated every
millisecond, it may have been opened by the other program to write
into it and thus not giving me access OR the text file is always in
an fopen state therefore not saving any data in for me to read. I
tested this out and the program has value added in as I see the KB's
adding up in front of my eyes.
I tried to copy the text file and paste it somewhere else for my
program to read, this way I definitely have full access to it and
once I am done with it, Ill delete it. This gave me nothing to print
aswell.
Am I right to deduce that it is always giving me EOF thus this is
having problems.
while ((result = fscanf(readLOG_fp, "%[^\n]\n", ReadLogLine)) != EOF) // Loops through the file till it reaches the end of file
If yes, How do I fix this?? What other ways can I make it read every line. I have seriously exhausted all my ideas on this problem and need some help in this.
Thanks everyone for your help.
Error is very obvious ... you might have over looked it..
You forgot to open the file.
FILE *readLOG_fp;
CString LogPathName;
LogPathName = Source_Folder + "\\serco.log";
readLOG_fp = fopen(LogPathName.GetBuffer());
if(readLOG_fp==NULL)
cout<<"Error: opening file\n";

OCaml: input redirection

Is there anyway to redirect the input file into our program in OCaml?
Something like this:
filename.ml < input.<can be any extension>
I have googled for this problem. The module Unix comes up to mind but I really don't understand how it works.
Could someone please give me some suggestion? If I'm right about the Unix module, can you please give me an example of how it works?!
Thank you very much!
Since you know how to redirect from the command line, I assume you're asking how to redirect inside your program.
The first thing to figure out (if you'll excuse my saying so) is why you would want to do this. Anything that can be done through redirection can be done by opening a file for input and passing around the input channel. The only purpose of redirection is to hook the standard input channel up to a chosen file. But since you're writing the code you can read input from any channel you like.
One reason to do it is that it's a quick hack for testing. I've done this many times. Another possible reason is that you're using code you can't easily or (don't want to) modify.
If you really do want to redirect stdin, and you're running on a Unix-like system, you can handle redirection the way the shell actually handles it: with the dup2() system call.
$ cat redir.ml
let redir fn =
let open Unix in
let fd = openfile fn [O_RDONLY] 0 in
dup2 fd stdin
let () =
redir "redir.ml";
Printf.printf "%s\n" (read_line())
$ ocamlc -o redir unix.cma redir.ml
$ ./redir
let redir fn =

Implementing a log watcher

I'm wondering how you can implement a program similar to tail -f in C/C++, a program that watches for and processes new lines added to a log file?
You can use fseek() to clear the eof condition on the stream. Essentially, read to the end of the file, sleep for a while, fseek() (without changing your position) to clear eof, the read to end of file again. wash, rinse, repeat. man fseek(3) for details.
Here's what it looks like in perl. perl's seek() is essentially a wrapper for fseek(3), so the logic is the same:
wembley 0 /home/jj33/swap >#> cat p
my $f = shift;
open(I, "<$f") || die "Couldn't open $f: $!\n";
while (1) {
seek(I, 0, 1);
while (defined(my $l = <I>)) {
print "Got: $l";
}
print "Hit EOF, sleeping\n";
sleep(10);
}
wembley 0 /home/jj33/swap >#> cat tfile
This is
some
text
in
a file
wembley 0 /home/jj33/swap >#> perl p tfile
Got: This is
Got: some
Got: text
Got: in
Got: a file
Hit EOF, sleeping
Then, in another session:
wembley 0 /home/jj33/swap > echo "another line of text" >> tfile
And back to the original program output:
Hit EOF, sleeping
Got: another line of text
Hit EOF, sleeping
I think what you're looking for is the select() call in c/c++. I found a copy of the man page here: http://www.opengroup.org/onlinepubs/007908775/xsh/select.html. Select takes file descriptors as arguments and tells you when one of them has changed and is ready for reading.
The tail program is open source, so you could reference that. I wondered the same thing and looked at the code a while back, thinking it would be pretty simple, but I was surprised at how complex it was. There are lots of gotchas that have to be taken into account.
See here
You could either call out to tail and retrieve the stream back into your app, or as it's open source, maybe try to pull it into your own code.
Also, it is possible in C++ iostream to open a file for viewing only and just read to the end, while buffering the last 10-20 lines, then output that.