=== Top of the Swiki === Attachments ===
Recipe: Doing Something to Each Line in a File
Problem
You want to process a text file line by line. You don't want to worry about different line end characters in different operating systems.
Solution
Use a CrLfFileStream as follows
| inputStream aLine |
inputStream := (CrLfFileStream readOnlyFileNamed: 'data.txt') ascii.
[inputStream atEnd] whileFalse: [
aLine := inputStream upTo: (Character cr).
"Do something with aLine"
]
The Cr is not part of aLine and empty lines will give an empty string in aLine.
Discussion
The CrLfFileStream does its job in a platform independent way. The CrLfFileStream>>next method makes every file look as if its lines were terminated by a Cr. Since upTo: is implemented in terms of next, you can use Cr as the universal line delimiter across all platforms.
If you want to swallow the file at once, use
(FileStream readOnlyFileNamed: 'data.txt') contentsOfEntireFile.
Wannabe Squeaker Questions:
- Why is all input from standard file classes character oriented? Seems like it would be useful to have a file class where you could loop through line-by-line without having to code something like the above each time.
- From a standard practices point-of-view, if I wanted to implement line-by-line read, would it be best to create a new file subclass and override the next method to return line stings, add a new nextLine method to a standard file class, or to create a new subclass AND a new selector?
See also
Regular Expressions in Squeak if you want to do more complicated things to each line.