Using the Arduino Ethernet Server Library, what is the difference between:
server.write(data);
,
server.print(data);
, and
server.println(data);
I know that the printIn
adds a new line, where print
does not. I cannot find any examples for server.write();
.
(Long answer, skip to TL;DR at the bottom if unwieldy)
print()
and write()
come fromTo find out, we can look at the source. Server
is an instance of the EthernetServer
class defined in arduino/libraries/Ethernet/EthernetServer.h
(selected lines only)
#include "Server.h"
class EthernetClient;
class EthernetServer :
public Server {
private:
public:
virtual size_t write(uint8_t);
virtual size_t write(const uint8_t *buf, size_t size);
using Print::write;
};
Ok, so it is a Server
. Server
is defined in /usr/share/arduino/hardware/arduino/cores/arduino/Server.h
, and there is very little to it:
class Server : public Print {
public:
virtual void begin() =0;
};
This means that server is a subclass of Print
so we can look for differences between write()
and print()
there.
print()
and write()
parametersWe see that this class (i.e. Print
) defines a number of overloaded print()
methods:
size_t print(const __FlashStringHelper *);
size_t print(const String &);
size_t print(const char[]);
size_t print(char);
size_t print(unsigned char, int = DEC);
size_t print(int, int = DEC);
size_t print(unsigned int, int = DEC);
size_t print(long, int = DEC);
size_t print(unsigned long, int = DEC);
size_t print(double, int = 2);
size_t print(const Printable&);
and three overloaded write()
methods:
virtual size_t write(uint8_t) = 0;
size_t write(const char *str) { return write((const uint8_t *)str, strlen(str)); }
virtual size_t write(const uint8_t *buffer, size_t size);
As you can see the C-string write
uses the block write
(the third method), and in the default implementation, the block write uses a byte write (the first method), which is pure virtual method: virtual size_t write(uint8_t) = 0;
. It must be overriden in every class that derives from Print
. Additionally the block write()
may be overriden as well in order to write multi-byte data more efficiently.
So, parameter-wise:
write()
: on bytes (uint8_t
), byte buffers, and char array pointers (= regular C strings)print()
: Arduino String
s, int
s and long
s (in whatever base), float
s, and any class derived from Printable
, in addition to chars
and C strings.As you can see, formally, there is little overlap between the parameters write()
and print()
takes. For instance only write()
takes uint8_t
, but only print()
can take a char
. The only area of overlap is the C-style strings: there is print(const char[]);
and write(const char *str);
. However, even in cases like char
the print()
function simply calls the write(uint8_t)
:
size_t Print::print(char c)
{
return write(c);
}
The same is true for print(char[])
write()
in `EthernetServerThe EthernetServer
class introduces a block write method
size_t EthernetServer::write(const uint8_t *buffer, size_t size)
and in the EthernetServer
the write(uint8_t)
simply thunks to the block write:
size_t EthernetServer::write(uint8_t b)
{
return write(&b, 1);
}
Since all the print()
calls and non-uint8_t
write()
calls use either write(uint8_t)
or write(uint8_t*, size_t)
, in the EthernetServer
class every print
/write
call is made using the block write.
print()
and write()
The thunking print()
functions (such as print(char c)
) will be most-likely be inlined by the gcc compiler, though if you are worried about this you can call write()
instead of print()
.
One case where you might want to call write()
instead of print()
to save a couple of clock cycles is where you are holding a byte
/uint8_t
and you need to print that. Using print()
your data will need to be converted to a 4-byte value (int
) and then printed using more code. In this case write()
will be a tiny bit faster.
On the other hand, code consistency is probably worth something too. From this perspective it might make sense to make all print()
calls.
Most of the time, however, your types will dictate calling the print()
function: write can only take three types of input.
TL;DR: The answer to your question then is that there isn't much difference between print()
and write()
except:
write()
methods (byte or block) are the methods that do the actual work of sending characters somewhere, in every case.write()
can take bytes (uint8_t
), byte buffers, and char array pointers (= regular C strings) as parameters, whereas print()
takes Arduino String
s, int
s and long
s (in whatever base), float
s, and any class derived from Printable
, in addition to chars
and C strings. So we might say that write()
is lower level than print()
, given the fact that it only takes low-level types.write()
for printing byte
/uint8_t
types, but print
everywhere makes your code look a teensy bit better IMHO (mainly because it doesn't raise the print()
versus write()
questions).