Why read(io::IOBuffer, String) does not work as expected

io = IOBuffer()
write(io, "name, age \n tom, 12")
data = read(io, String)    # return empty string, not as expected 

The following code works

data = String( take!(io) )  # return `name, age \n tom, 12` as expected

Why the API is designed in this way ? Is it better to make read(io, String) return the string ?

1 Like

read(io, ...) will start reading the buffer at its current position, if you want to read from the start you should roll back the buffer with seekstart:

julia> io = IOBuffer();

julia> write(io, "name, age \n tom, 12");

julia> data = read(seekstart(io), String)
"name, age \n tom, 12"
2 Likes

Thank you so much for your quick response. When call read on text file, it can read the whole content as follows.

data = read(raw"/data/test.txt", String)   # returns the whole contents

it is easier for the users to keep the API consistent. Maybe it is better to set the position to the start in the function read().

That method is something very different though, it opens a io to the file, with the current position at the start of the file.

3 Likes

The API is consistent. Your original example is equivalent to

julia> io = open("test.txt", read=true, write=true, create=true)
IOStream(<file test.txt>)

julia> write(io, "name, age \n tom, 12")
19

julia> data = read(io, String)
""

whereas your read file example is equivalent to

julia> read(IOBuffer("name, age \n tom, 12"), String)
"name, age \n tom, 12"

You can’t expect read on the same io to return the same result no matter what the state of the io is since it’s a stateful API by design. If you are looking for an API that always returns the same content for seekable IO (essentially what you meant by “API consistent”), you can always define a function that always does the seek and then read. It’s just easy enough to do, not generally useful, and definitely not what read is for so it certainly won’t become the implementation of read.

4 Likes