# Difference between \`write\` and \`print\`

**URL:** <https://discourse.julialang.org/t/difference-between-write-and-print/6943>\
**Category:** General Usage\
**Tags:** question\
**Created:** [November 7, 2017, 8:17pm UTC](https://discourse.julialang.org/t/difference-between-write-and-print/6943 "2017-11-07T20:17:16Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![tparker](https://avatars.discourse-cdn.com/v4/letter/t/839c29/32.png) [@tparker](https://discourse.julialang.org/u/tparker)\
**Post date:** [November 7, 2017, 8:17pm UTC](https://discourse.julialang.org/t/difference-between-write-and-print/6943/1 "2017-11-07T20:17:16Z")

</div>

The [documentation entries](https://docs.julialang.org/en/stable/stdlib/io-network/) for `write` and `print` seem very similar. There are a few minor differences (`write` allows file names as well as I/O streams and returns the number of bytes written, while `print` calls `show` if the argument doesn’t have a canonical text representation), but it seems like they would easy to combine into a single function. What is the motivation for having both? Is there a fundamental difference between their behavior that I’m not noticing?

---

<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:** [November 7, 2017, 9:05pm UTC](https://discourse.julialang.org/t/difference-between-write-and-print/6943/2 "2017-11-07T21:05:29Z")

</div>

`print` outputs a text representation of an object, whereas `write` outputs raw bytes. Try `x=7310302560386184563` and look at `println(x)` versus `write(stdout, x); println()` to see the difference.

---

<div class="post-metadata">

**Author:** ![tparker](https://avatars.discourse-cdn.com/v4/letter/t/839c29/32.png) [@tparker](https://discourse.julialang.org/u/tparker)\
**Post date:** [November 7, 2017, 10:01pm UTC](https://discourse.julialang.org/t/difference-between-write-and-print/6943/3 "2017-11-07T22:01:01Z")

</div>

Holy smokes. That was well played. I just assumed that `write` would output similar text to `writedlm` and `writecsv`, based on the the name similarity.

Given the drastic difference in output, would it be clearer to rename those functions as `printdlm` and `printcsv`?

---

<div class="post-metadata">

**Author:** ![iwelch](https://avatars.discourse-cdn.com/v4/letter/i/8c91f0/32.png) [@iwelch](https://discourse.julialang.org/u/iwelch)\
**Post date:** [March 16, 2018, 5:50pm UTC](https://discourse.julialang.org/t/difference-between-write-and-print/6943/4 "2018-03-16T17:50:56Z")

</div>

very clever, steven. 🙂

---

<div class="post-metadata">

**Author:** ![ScottPJones](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scottpjones/32/146_2.png) [@ScottPJones](https://discourse.julialang.org/u/ScottPJones)\
**Post date:** [March 16, 2018, 6:13pm UTC](https://discourse.julialang.org/t/difference-between-write-and-print/6943/5 "2018-03-16T18:13:18Z")

</div>

There will be another difference in v0.7/v1.0, if you have strings with different encodings:

`print*` outputs strings in UTF-8 format (hopefully that can changed so that the desired output encoding can be selected), no matter how the string is encoded.  
This is important if you have strings with different encodings that you want to print out together.

`write` outputs strings in their “native” encoding, without conversions.  
If you have a UTF-8 encoding string, that is what gets output.  
If you have ISO-8859-1 (i.e. Latin-1) then that gets output directly. Same for UTF-16 or UTF-32, they will be output (in the native byte order) as a set of 2 byte or 4 byte words.

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [March 16, 2018, 6:58pm UTC](https://discourse.julialang.org/t/difference-between-write-and-print/6943/6 "2018-03-16T18:58:49Z")

</div>

`print` only outputs UTF-8 for the built-in IO types which are defined to be UTF-8 encoded. In order to support I/O defaulting to other encodings, the appropriate approach is to define new IO subtypes with different default encodings. Nothing in Base needs to be changed for this as far as I’m aware.

The general principle is that for `print` the output stream determines the encoding (UTF-8 by default for all built-in IO types); for `write` the object itself determines the raw data, including the encoding. Endianness may be an exception to that, but again, I/O types with different endianness can and should be added outside of Base.

---

<div class="post-metadata">

**Author:** ![ScottPJones](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scottpjones/32/146_2.png) [@ScottPJones](https://discourse.julialang.org/u/ScottPJones)\
**Post date:** [March 16, 2018, 7:06pm UTC](https://discourse.julialang.org/t/difference-between-write-and-print/6943/7 "2018-03-16T19:06:29Z")

</div>

> [@StefanKarpinski](#):
>
> In order to support I/O defaulting to other encodings, the appropriate approach is to define new IO subtypes with different default encodings.

OK. I was wondering if it would make sense to add the character set encoding in the `IOContext`.

> [@StefanKarpinski](#):
>
> Endianness may be an exception to that, but again, I/O types with different endianness can and should be added outside of Base.

I don’t think it would be an exception, at least for what I’ve implemented for different endian encodings, it would not be necessary.

---

<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:** [March 17, 2018, 12:33am UTC](https://discourse.julialang.org/t/difference-between-write-and-print/6943/8 "2018-03-17T00:33:12Z")

</div>

> [@ScottPJones](#):
>
> OK. I was wondering if it would make sense to add the character set encoding in the IOContext.

Yes, I’ve been playing with patch along these lines, with a function

```julia
"""
    textencoding(io::IO)

Returns the encoding (a subtype of [`AbstractTextEncoding`](@ref)) used
for reading/writing text via [`print`](@ref) in the stream `io`.

Defaults to [`UTF8Encoding`](@ref), but can be changed by setting
the `:textencoding` property of an [`IOContext`](@ref). Other encodings
may be defined/supported by external packages.
"""
textencoding(io::IO) = get(io, :textencoding, UTF8Encoding)::Type{<:AbstractTextEncoding}

# dispatch based on encoding:
print(io::IO, c::AbstractChar) = _print(io, textencoding(io), c)
print(io::IO, s::AbstractString) = _print(io, textencoding(io), s)

```

(Particular `IO` types could also overload `textencoding` this way, rather than relying exclusively on `IOContext`.)

The reason that I’m thinking of having it return a type, rather than an instance of a type, is that it looks like it will be useful for all the encoding types to be `abstract` so that they can be subtyped arbitrarily. If `Encoding1 <: Encoding2`, that means that any valid text in `Encoding2` has the same meaning in `Encoding1`, but not vice versa. So, for example, `UTF8Encoding <: ASCIIEncoding`. You want to be able to have `_print(io::IO, encoding::Type{<:ASCIIEncoding}, c::ASCIIChar) = write(io, UInt8(c))`, for example.

---

<div class="post-metadata">

**Author:** ![ScottPJones](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scottpjones/32/146_2.png) [@ScottPJones](https://discourse.julialang.org/u/ScottPJones)\
**Post date:** [March 17, 2018, 12:56am UTC](https://discourse.julialang.org/t/difference-between-write-and-print/6943/9 "2018-03-17T00:56:38Z")

</div>

Please take a look at what I’ve already have working in [Strs.jl](https://github.com/JuliaString/Strs.jl), it seems like you are reinventing the wheel.  
A simply type hierarchy will simply not be flexible enough to handle all the different issues with character sets, encodings, and character set encodings.  
It’s important to keep track separately of things like the character set from the character set encoding:  
For example, `UTF16CSE` (character set encoding) is a type with two parameters, the character set `CharSet{:UTF32}`, and the encoding `Encoding{:UTF16}`. This makes it easy to dispatch appropriately, and add new types and traits in the future.

---

<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:** [March 17, 2018, 12:26pm UTC](https://discourse.julialang.org/t/difference-between-write-and-print/6943/10 "2018-03-17T12:26:33Z")

</div>

> [@ScottPJones](#):
>
> It’s important to keep track separately of things like the character set from the character set encoding:

I think that the character set should be determined by the `AbstractChar` or `AbstractString` type.

---

<div class="post-metadata">

**Author:** ![ScottPJones](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scottpjones/32/146_2.png) [@ScottPJones](https://discourse.julialang.org/u/ScottPJones)\
**Post date:** [March 17, 2018, 6:05pm UTC](https://discourse.julialang.org/t/difference-between-write-and-print/6943/11 "2018-03-17T18:05:17Z")

</div>

If you’d looked at what I’ve already implemented, you’d see that I already do that.  
(Remember, I implemented `AbstractChar` before it was put in Base)  
Since `String` and `Char` are not part of the `Str` and `CodePoint` types, and for convenience,  
I have `cse` and `charset` functions that return the character set encoding and character set respectively.
