Skip to content

Commit

Permalink
countlines now counts final non-empty line even if it doesn't end wit…
Browse files Browse the repository at this point in the history
…h EOL (JuliaLang#25845)
  • Loading branch information
stevengj authored and JeffBezanson committed Feb 1, 2018
1 parent 12f4f43 commit 0ee7817
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 6 deletions.
5 changes: 4 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,9 @@ This section lists changes that do not have deprecation warnings.
* `readuntil` now does *not* include the delimiter in its result, matching the
behavior of `readline`. Pass `keep=true` to get the old behavior ([#25633]).

* `countlines` now always counts the last non-empty line even if it does not
end with EOL, matching the behavior of `eachline` and `readlines` ([#25845]).

* `getindex(s::String, r::UnitRange{Int})` now throws `UnicodeError` if `last(r)`
is not a valid index into `s` ([#22572]).

Expand Down Expand Up @@ -1260,4 +1263,4 @@ Command-line option changes
[#25622]: https://github.com/JuliaLang/julia/issues/25622
[#25634]: https://github.com/JuliaLang/julia/issues/25634
[#25654]: https://github.com/JuliaLang/julia/issues/25654
[#25655]: https://github.com/JuliaLang/julia/issues/25655
[#25655]: https://github.com/JuliaLang/julia/issues/25655
10 changes: 7 additions & 3 deletions base/io.jl
Original file line number Diff line number Diff line change
Expand Up @@ -999,7 +999,8 @@ end
Read `io` until the end of the stream/file and count the number of lines. To specify a file
pass the filename as the first argument. EOL markers other than `'\\n'` are supported by
passing them as the second argument.
passing them as the second argument. The last non-empty line of `io` is counted even if it does not
end with the EOL, matching the length returned by [`eachline`](@ref) and [`readlines`](@ref).
# Examples
```jldoctest
Expand All @@ -1011,7 +1012,7 @@ julia> countlines(io)
julia> io = IOBuffer("JuliaLang is a GitHub organization.");
julia> countlines(io)
0
1
julia> countlines(io, eol = '.')
1
Expand All @@ -1021,13 +1022,16 @@ function countlines(io::IO; eol::Char='\n')
isascii(eol) || throw(ArgumentError("only ASCII line terminators are supported"))
aeol = UInt8(eol)
a = Vector{UInt8}(uninitialized, 8192)
nl = 0
nl = nb = 0
while !eof(io)
nb = readbytes!(io, a)
@simd for i=1:nb
@inbounds nl += a[i] == aeol
end
end
if nb > 0 && a[nb] != aeol
nl += 1 # final line is not terminated with eol
end
nl
end

Expand Down
7 changes: 5 additions & 2 deletions test/read.jl
Original file line number Diff line number Diff line change
Expand Up @@ -537,15 +537,18 @@ rm(f)
end # mktempdir() do dir

@testset "countlines" begin
@test countlines(IOBuffer("")) == 0
@test countlines(IOBuffer("\n")) == 1
@test countlines(IOBuffer("\n"), eol = '\r') == 0
@test countlines(IOBuffer("\n"), eol = '\r') == 1
@test countlines(IOBuffer("\r\r\n\r"), eol = '\r') == 3
@test countlines(IOBuffer("\n\n\n\n\n\n\n\n\n\n")) == 10
@test countlines(IOBuffer("\n \n \n \n \n \n \n \n \n \n")) == 10
@test countlines(IOBuffer("\r\n \r\n \r\n \r\n \r\n")) == 5
@test countlines(IOBuffer("foo\nbar")) == length(readlines(IOBuffer("foo\nbar"))) == 2
file = tempname()
write(file,"Spiffy header\nspectacular first row\neven better 2nd row\nalmost done\n")
@test countlines(file) == 4
@test countlines(file, eol = '\r') == 0
@test countlines(file, eol = '\r') == 1
@test countlines(file, eol = '\n') == 4
rm(file)
end
Expand Down

0 comments on commit 0ee7817

Please sign in to comment.