Skip to content

add 'eachLine' to BufferedReader #391

Open

Description

@Dierk

Here is a suggestion to improve the usage of the BufferedReader that does not require to read the full content but allows line-by-line processing:

-- only for testing
data StringReader = native java.io.StringReader where
    native new      :: String -> STMutable s StringReader

-- convenience output
printIOValue prefix ioValue = do  -- same as:  (prefix ++) . show <$> ioValue >>= println
    value <- ioValue
    println $ prefix ++ show value


eachLine :: Mutable s BufferedReader → a → (a → String → ST s a) → ST s a
eachLine bufferedReader value handler = do
    line <- bufferedReader.readLine
    case line of
        Nothing   -> do
            bufferedReader.close
            return value
        Just line -> do
            newValue <- handler value line
            eachLine bufferedReader newValue handler

main = do
    testFile = File.new "TestFile.txt"              -- since version 3.25, otherwise <- instead of =

    -- delete test file if it already existed
    printIOValue "Test file deleted to clean up before start: " testFile.delete

    println "create test file"
    writeFile testFile.getPath $ unlines ["first line","second line","third line"]
    printIOValue "File now exists: " testFile.exists

    println "read test file in toto"
    content <- readFile testFile.getPath
    println "file content was:"
    println content

    println "append 2 lines"
    appendFile testFile.getPath $ unlines ["fourth line","fifth line"]

    println "processing each line, while keeping track of line numbers"
    bufferedReader <- openReader testFile.getPath
    count <- eachLine bufferedReader 0 $ \num line -> do
        println $ show (num + 1) ++ ": " ++ line
        return  $ num + 1
    println $ "total number of lines: " ++ show count

    println "pushing each line on a stack"
    bufferedReader <- openReader testFile.getPath
    stack <- eachLine bufferedReader [] $ \stack line -> return (line : stack)
    println $ "total stack" ++ show stack

    println "processing each line with a non-IO impure reader, here: StringReader. (great for testing)"
    stringReader <- StringReader.new $ unlines ["first","second","third"]
    bufStrReader <- BufferedReader.new stringReader
    result <- eachLine bufStrReader 0 $ \num _ -> return  $ num + 1
    println $ "processing strings with eachLine works as expected: " ++ show (result == 3)

    println "command line input (send EOF via Cmd/Ctrl-D)"
    eachLine stdin 0 $ \num line -> do
        println $ show (num + 1) ++ ": " ++ line
        return  $ num + 1

    return ()

Activity

  1. self-assigned this
    on Jun 19, 2020
  2. Dierk commented on Jun 22, 2020

    @Dierk
    MemberAuthor

    Hi, @Ingo60, please find my latest ideas under https://github.com/Dierk/fregeTutorial/blob/e3dc0b5e2dfc131c11dcd95be5ecd4a44eec6eef/src/main/frege/suggest/LineProducer.fr#L10
    Suggestions for improvement highly welcome!

    If you think this makes sense, then please give me a thumbs-up and I will add it to the stdlib with examples and test cases extra.

    It requires the changes shown in line 51 and 54 (IOMutable to STMutable s for BufferedReader and FileInputStream).

  3. Ingo60 commented on Jun 24, 2020

    @Ingo60
    Member
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions