# Countlines() bug?

**URL:** https://discourse.julialang.org/t/countlines-bug/8740
**Category:** Internals & Design
**Created:** [February 1, 2018, 2:21pm UTC](https://discourse.julialang.org/t/countlines-bug/8740 "2018-02-01T14:21:01Z")
**Posts on this page:** 9
**Page:** 1

<div class="post-metadata">

### Author: ![RandomString123](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/randomstring123/32/3194_2.png) [@RandomString123](https://discourse.julialang.org/u/RandomString123)
#### Post date: [February 1, 2018, 2:21pm UTC](https://discourse.julialang.org/t/countlines-bug/8740/1 "2018-02-01T14:21:01Z")

</div>

I am trying to figure out if this is a bug or by design. There is a weirdness in how countlines() reports the number of lines in a file. It seems to under report the lines by 1 whenever the file does not end with a newline character. I would expect countlines() to return the same number of lines as you would get items in a vector using readlines(). Thoughts?

```julia
x = """
       abcd
       efgh"""

"abcd\nefgh"

countlines(IOBuffer(x))
1

readlines(IOBuffer(x))
2-element Array{String,1}:
 "abcd"
 "efgh"

 x = """
       abcd
       efgh
       """

"abcd\nefgh\n"

countlines(IOBuffer(x))
2

readlines(IOBuffer(x))
2-element Array{String,1}:
 "abcd"
 "efgh"

x = """
       abcd
       efgh
        """
"abcd\nefgh\n "

countlines(IOBuffer(x))
2

readlines(IOBuffer(x))
3-element Array{String,1}:
 "abcd"
 "efgh"
 " "

```

---

<div class="post-metadata">

### Author: ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)
#### Post date: [February 1, 2018, 2:28pm UTC](https://discourse.julialang.org/t/countlines-bug/8740/2 "2018-02-01T14:28:40Z")

</div>

Countlines simply counts the number of newline characters.

---

<div class="post-metadata">

### Author: ![nalimilan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nalimilan/32/147_2.png) [@nalimilan](https://discourse.julialang.org/u/nalimilan)
#### Post date: [February 1, 2018, 5:17pm UTC](https://discourse.julialang.org/t/countlines-bug/8740/3 "2018-02-01T17:17:44Z")

</div>

I agree it’s kind of unintuitive, though. FWIW, `wc -l` returns `1` even when there is no new line in the input.

---

<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: [February 1, 2018, 6:13pm UTC](https://discourse.julialang.org/t/countlines-bug/8740/4 "2018-02-01T18:13:48Z")

</div>

I agree that one probably wants `countlines` to match the length of the `eachline` iterator (or `readlines`). Currently it does not:

```julia
julia> collect(eachline(IOBuffer("abcd\nefgh")))
2-element Array{String,1}:
 "abcd"
 "efgh"

julia> countlines(IOBuffer("abcd\nefgh"))
1

```

---

<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: [February 1, 2018, 6:33pm UTC](https://discourse.julialang.org/t/countlines-bug/8740/5 "2018-02-01T18:33:02Z")

</div>

I’ve posted a PR to make this change: [https://github.com/JuliaLang/julia/pull/25845](https://github.com/JuliaLang/julia/pull/25845)

---

<div class="post-metadata">

### Author: ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)
#### Post date: [February 1, 2018, 6:57pm UTC](https://discourse.julialang.org/t/countlines-bug/8740/6 "2018-02-01T18:57:33Z")

</div>

> [@nalimilan](#):
>
> I agree it’s kind of unintuitive, though. FWIW, `wc -l` returns `1` even when there is no new line in the input.

Because that’s the POSIX [definition of line](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_206)

> [@](#):
>
> A sequence of zero or more non- `<newline>` characters plus a terminating `<newline>` character.

Something not terminated by a `<newline>` character is an [incomplete line](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_195). There are several tools that behaves unexpectedly with incomplete lines, like `cat` or `wc`. Also `git` highlights incomplete lines at the end of files. I’m pretty sure that some compilers warn (or used to) about missing newlines

---

<div class="post-metadata">

### Author: ![nalimilan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nalimilan/32/147_2.png) [@nalimilan](https://discourse.julialang.org/u/nalimilan)
#### Post date: [February 2, 2018, 8:27am UTC](https://discourse.julialang.org/t/countlines-bug/8740/7 "2018-02-02T08:27:19Z")

</div>

> [@giordano](#):
>
> Something not terminated by a \<newline\> character is an incomplete line. There are several tools that behaves unexpectedly with incomplete lines, like cat or wc. Also git highlights incomplete lines at the end of files. I’m pretty sure that some compilers warn (or used to) about missing newlines

Sure, but what matters the most is that Julia be consistent internally, and as @stevengj noted `eachline` returns incomplete lines, so it would make sense for `countlines` to give the number of elements `eachlines` returns.

---

<div class="post-metadata">

### Author: ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)
#### Post date: [February 2, 2018, 10:25am UTC](https://discourse.julialang.org/t/countlines-bug/8740/8 "2018-02-02T10:25:07Z")

</div>

Yes, I can see the point of the proposed change, I was just giving some context to why Unix tools behave unexpectedly when the newline at the end of a file is missing

---

<div class="post-metadata">

### Author: ![RandomString123](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/randomstring123/32/3194_2.png) [@RandomString123](https://discourse.julialang.org/u/RandomString123)
#### Post date: [February 2, 2018, 1:17pm UTC](https://discourse.julialang.org/t/countlines-bug/8740/9 "2018-02-02T13:17:02Z")

</div>

I agree with the consistency part most of all. Developers will most likely use countlines() and {read,each}lines() in unison. If I was going to write code that read in a large but unknown length data (ex. 20 million lines) I would want to pre-allocate a vector to prevent gc thrashing. It is much faster to count the number lines in the file via reading newline characters, versus reading in the whole dataset. So I would write some code along the following lines (Not working, but codeish):

```julia
v = Vector{MyType}(countlines(file))
for l in eachlines(file)
   v[i] = parse_mytype(l)
end

```

The above could end up in an exception when eachlines and countlines don’t behave the same.
