| Author |
Message |
< Erlang ~ getlines from a file |
| selmi.dhia |
Posted: Tue Jun 29, 2010 3:21 pm |
|
|
|
Joined: 29 Jun 2010
Posts: 5
|
I am a beginner in erlang,I want to read lines from a file (.erl or .txt) and store those lines as elements into a list.I tried this code:
--------------------------------------------------
-module(read).
-export([readlines/1]).
readlines(FileName) ->
{ok, Device} = file:open(FileName, [read]),
get_all_lines(Device,[]).
get_all_lines(Device, Accum) ->
case io:get_line(Device, []) of
eof -> file:close(Device), Accum;
Line -> get_all_lines(Device, Accum ++ [Line])
end.
-----------------------
and for a file containing a number in each line, I got a result like this:
["12\n","5\n","35\n","4\n","11\n","123\n","867\n","10\n","201\n"]
How can I have a result without the "\n" character in the list's elements like this:
["12","5","35","4","11","123","867","10","201"]?
or further a list of numbers not of strings like this:
[12,5,35,4,11,123,867,10,201]? |
|
|
| Back to top |
|
| zajda |
Posted: Wed Jun 30, 2010 9:01 am |
|
|
|
User
Joined: 22 Aug 2009
Posts: 83
|
please, analyse following changes (and later points to see why its wrong):
Code: -module(read).
-export([readlines/1]).
readlines(FileName) ->
{ok, Device} = file:open(FileName, [read]),
lists:reverse(get_all_lines(Device,[])).
get_all_lines(Device, Accum) ->
case io:get_line(Device, []) of
eof -> file:close(Device), Accum;
[Line|"\n"] ->
get_all_lines(Device, [list_to_integer([Line])|Accum])
end.
there are three tricks and above code is not the best example of good erlang code. This is why:
1. I pattern match on line to extract a number, but if in line there would be something else like '1 2\n' it would fall.
2. When Line is bounded it is actually an integer (because this is how chars are represented in erlang). It is not visible in this example very well, and it has to be wrapped again in list to get changed into proper value of integer ("1" is 49 and then integer_to_list([49]) is 1)
3. It is better to add new stuff as a head of a list. Thats why I had to reverse the order when function returned.
Here, tail recursion is lost, but it could be solved by extra clause of get_all_lines/2 and do not
code returns sth like that:
read:readlines("somefile.txt").
[1,2,3,4,5,6]
MichaĆ Zajda
------------------
Erlang Solutions Ltd |
|
|
| Back to top |
|
| selmi.dhia |
Posted: Wed Jun 30, 2010 10:45 am |
|
|
|
Joined: 29 Jun 2010
Posts: 5
|
thank you, I got all the tricks, but I tried to compile your code and its ok,after that I tried a call: read:readlines("file.erl"). where file.erl is a file conataining on number in each line with no spaces,I got an error as shown below:
8> H=read:readlines("c:/Users/student/Desktop/file.erl").
** exception error: no case clause matching "12\n"
in function read:get_all_lines/2
in call from read:readlines/1
why it doesn't work  |
|
|
| Back to top |
|
| zajda |
Posted: Wed Jun 30, 2010 11:16 am |
|
|
|
User
Joined: 22 Aug 2009
Posts: 83
|
space doesn't matter, it is number of chars and it works only for one.
It is because, head of a list in pattern [Line|"\n"] is just one char (so Line is one char).
Take a look at string module documentation ( http://erlang.org/doc/man/string.html) and modify whole line in side of case clause, not in pattern. It is quit slow, so later for performance reason you can use regexps (http://erlang.org/doc/man/re.html) |
|
|
| Back to top |
|
| selmi.dhia |
Posted: Thu Jul 01, 2010 9:07 am |
|
|
|
Joined: 29 Jun 2010
Posts: 5
|
ok it works perfectly with string:substr/3..I tried so far with a file that can have many numbers in the same line separated with a space:"12 999.." for that I used string:tokens/2 in this code:
------------
-module(read).
-export([readlines/1]).
readlines(FileName) ->
{ok, Device} = file:open(FileName, [read]),
lists:reverse(get_all_lines(Device,[])).
get_all_lines(Device, Accum) ->
case io:get_line(Device, []) of
eof -> file:close(Device), Accum;
Line ->get_all_lines(Device,[string:tokens((string:substr(Line,1,(string:len(Line))-1))," ")|Accum])
end.
----------
the problem is that I had a result: [["12","999"],["5"],["35"],["4"],["11"],["123"],["867"],["10"],
["201"]] instead of having this ["12","999","5","35"|..]
any solution? otherwise,how can I use the "re" module? |
|
|
| Back to top |
|
| zajda |
Posted: Sat Jul 03, 2010 5:27 pm |
|
|
|
User
Joined: 22 Aug 2009
Posts: 83
|
you can flatten the list with lists:flatten/1 but in this case output would be too flat
I think that the simplest way is to use ++ again.
Code: -module(read).
-export([readlines/1]).
readlines(FileName) ->
{ok, Device} = file:open(FileName, [read]),
get_all_lines(Device, io:get_line(Device, []), []).
get_all_lines(Device, eof, Accum) ->
file:close(Device),
lists:reverse(Accum);
get_all_lines(Device, Line, Accum) ->
Extract = fun(Input) ->
string:tokens((string:substr(Input,1,(string:len(Input))-1))," ")
end,
get_all_lines(Device, io:get_line(Device, []), Extract(Line) ++ Accum).
and here with re:
Code: -module(read).
-export([readlines/1]).
readlines(FileName) ->
{ok, Device} = file:open(FileName, [read]),
get_all_lines(Device, io:get_line(Device, []), []).
get_all_lines(Device, eof, Accum) ->
file:close(Device),
lists:reverse(Accum);
get_all_lines(Device, Line, Accum) ->
Extract = fun(Input) ->
re:split(Input,"[ \n]",[{return,list},trim])
end,
get_all_lines(Device, io:get_line(Device, []), Extract(Line) ++ Accum).
in case of more complicated regexp you can compile it with re:compile in the initializing function and pass it on. |
|
|
| Back to top |
|
| selmi.dhia |
Posted: Mon Jul 05, 2010 8:34 am |
|
|
|
Joined: 29 Jun 2010
Posts: 5
|
thank you..I got the result that I need..  |
|
|
| Back to top |
|
| wuji |
Posted: Tue Sep 04, 2012 7:43 am |
|
|
|
User
Joined: 10 Aug 2012
Posts: 654
|
all stay?'" Denniston said.The team agreed."I love swimming under Dave, Dave, replica designer *beep* Dave, and I think he is a good fit," said
Kamber, a member of the Paralympics swimming team. "He understands understands [h2]cheap jordans[/h2] understands each of our training needs."Recently, Denniston was announced as
head coach of the 2012 Paralympic Resident Swim team in in [h4]cheap polo shirts[/h4] in Colorado Springs -- the same position his mentor Flowers
before him.Denniston said that if he had to sum up up [h2]replica designer *beep*[/h2] up his experiences since his 2005 accident in a single |
|
|
| Back to top |
|
| dongdongwu |
Posted: Wed Sep 19, 2012 8:35 am |
|
|
|
User
Joined: 19 Sep 2012
Posts: 236
|
| Girls would refuse to even leave their replicas behind. specifically when the product beats the complete meaning of the Christian Louboutin men outlet; in conditions of good quality and detailing.If Cinderella was residing in your twenty primary century as opposed to the aged a single then there would not be any 'Happy actually after'. properly appears like girls nowadays are as well fond of the strong;Christian Louboutin Men Shoes to leave them in your center of nowhere.Christian Louboutin for men Shoes would arrive true handy being a excellent handbag using the glimpse and really feel belonging to the authentic but at a very much lesser price tag adding as very much as types picture in your process. |
|
|
| Back to top |
|
|
|
All times are GMT
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum You cannot attach files in this forum You cannot download files in this forum
|
|
|