# Read a file separated by blank lines?

**URL:** <https://discourse.julialang.org/t/read-a-file-separated-by-blank-lines/69430>\
**Category:** General Usage\
**Tags:** parsing, io\
**Created:** [October 8, 2021, 12:59pm UTC](https://discourse.julialang.org/t/read-a-file-separated-by-blank-lines/69430 "2021-10-08T12:59:41Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![greatpet](https://avatars.discourse-cdn.com/v4/letter/g/e495f1/32.png) [@greatpet](https://discourse.julialang.org/u/greatpet)\
**Post date:** [October 8, 2021, 12:59pm UTC](https://discourse.julialang.org/t/read-a-file-separated-by-blank-lines/69430/1 "2021-10-08T12:59:41Z")

</div>

I have a file containing several multi-line blocks of text separate by blank lines. A blank line may contain just a line break or also some space. Is there something similar to `readline()` which allows me to read in these blocks one by one, each as a string?

---

<div class="post-metadata">

**Author:** ![mike\_k](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mike_k/32/211864_2.png) [@mike\_k](https://discourse.julialang.org/u/mike_k)\
**Post date:** [October 8, 2021, 1:53pm UTC](https://discourse.julialang.org/t/read-a-file-separated-by-blank-lines/69430/2 "2021-10-08T13:53:45Z")

</div>

I am not aware of a direct way to do this. But you could `readline()` anyway. To separate your blocks (i.e., to detect blank lines) you could use something like that:

```julia
f = open( "foo_data.txt" )
lines = readlines(f)
for l in lines
    if isempty( filter(x -> !isspace(x), l) )
        println("found blank line")
    else
        #do something with the read data
    end
end
close(f)

```

The `else` statement (and/or the loop) needs to be adapted depending on your desired final data format.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [October 8, 2021, 1:57pm UTC](https://discourse.julialang.org/t/read-a-file-separated-by-blank-lines/69430/3 "2021-10-08T13:57:54Z")

</div>

> [@greatpet](#):
>
> A blank line may contain just a line break or also some space. Is there something similar to `readline()` which allows me to read in these blocks one by one, each as a string?

For example:

```julia
function readparagraph(io)
    buf = IOBuffer()
    while !eof(io)
        line = readline(io; keep=true)
        all(isspace, line) && break
        print(buf, line)
    end
    return String(take!(buf))
end

```

---

<div class="post-metadata">

**Author:** ![greatpet](https://avatars.discourse-cdn.com/v4/letter/g/e495f1/32.png) [@greatpet](https://discourse.julialang.org/u/greatpet)\
**Post date:** [October 8, 2021, 2:17pm UTC](https://discourse.julialang.org/t/read-a-file-separated-by-blank-lines/69430/4 "2021-10-08T14:17:08Z")

</div>

Thanks, I’ll use it!

A question about the last line of your function: is it possible to convert `Vector{Char}` to `String` without copying the data and allocating memory, similar to how `take!` constructs `Vector{Char}` without copying? I guess that’s not possible in Julia because the vector is mutable and the string is immutable?

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [October 8, 2021, 2:53pm UTC](https://discourse.julialang.org/t/read-a-file-separated-by-blank-lines/69430/5 "2021-10-08T14:53:14Z")

</div>

> [@greatpet](#):
>
> is it possible to convert `Vector{Char}` to `String` without copying the data and allocating memory, similar to how `take!` constructs `Vector{Char}` without copying?

`String(take!(buf))` already constructs the string without making a copy — from a `Vector{UInt}` in the [UTF-8 encoding](http://utf8everywhere.org/), _not_ a `Vector{Char}`.

(`Vector{Char}` requires 4 bytes per character, similar to UTF-32, which is different from the encoding used by `String`, and is _not_ generally a recommended way to store strings.)

More generally, it _is_ possible to construct a `String(vec)` from a `vec::Vector{UInt8}` without making a copy of `vec`, but only if the `Vector{UInt8}` is specially allocated — this special allocation is done by `IOBuffer` objects and also by `read(io, numbytes)` as documented in the `String` docstring, but can also be accomplished using the undocumented `vec = Base.StringVector(numbytes)` constructor. See also [Document/export copy-free string allocation? · Issue #19945 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/19945) and [Conversion of Vector{UInt8} to String without copy](https://discourse.julialang.org/t/conversion-of-vector-uint8-to-string-without-copy/49837)

You can also use [StringViews.jl](https://github.com/JuliaStrings/StringViews.jl) to create a `String`-like object (another subtype of `AbstractString`) from an `AbstractVector{UInt8}` (e.g. a subarray) without making a copy.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [October 8, 2021, 3:01pm UTC](https://discourse.julialang.org/t/read-a-file-separated-by-blank-lines/69430/6 "2021-10-08T15:01:21Z")

</div>

(In principle, you could make it even more efficient than this by using lower-level APIs to read bytes directly in to the `IOBuffer` without allocating intermediate string objects via `readline`, but it’s probably not worth the effort. Another alternative would be to [use `mmap`](https://docs.julialang.org/en/v1/stdlib/Mmap/#Mmap.mmap) to access the file as an array of bytes, which you could then scan for ASCII newline and whitespace characters. You could then use the [StringViews.jl package](https://github.com/JuliaStrings/StringViews.jl) to create string-like views of the `mmap`-ed data without making a copy. There are lots of ways to wring more speed out of Julia if you care enough.)
