9

Documentation of SerialPort Write says that

By default, SerialPort uses ASCIIEncoding to encode the characters. ASCIIEncoding encodes all characters greater than 127 as (char)63 or '?'. To support additional characters in that range, set Encoding to UTF8Encoding, UTF32Encoding, or UnicodeEncoding.

Also see here. Does this mean I can't send byte array using write?

6
  • 2
    Yes you can msdn.microsoft.com/en-us/library/ms143551(v=vs.110).aspx Commented Sep 30, 2015 at 10:55
  • @Roy: Yes but that is the doc which says "ASCIIEncoding encodes all characters greater than 127 as (char)63 or '?'. " - so this is slightly confusing what is why I asked Commented Sep 30, 2015 at 10:57
  • If you keep reading you will see that you can change the encoding. It is the aptly named Encoding property of the serial port. Commented Sep 30, 2015 at 10:58
  • @dbasnett: So if I change encoding to UTF8 I should be able to send byte array? Commented Sep 30, 2015 at 11:09
  • @dbasnett: Btw. Do you think this implementation is reasonable: forums.codeguru.com/showthread.php?182234-serial-ports-C? Commented Sep 30, 2015 at 11:09

2 Answers 2

8

By default, SerialPort uses ASCIIEncoding to encode the characters

You're confusing methods, which read/write strings or chars, with methods, which read/write bytes.

E.g., when you'll call this:

port.Write("абв")

you'll get "???" (0x3F 0x3F 0x3F) in the port buffer by default. On the other hand, this call:

// this is equivalent of sending "абв" in Windows-1251 encoding
port.Write(new byte[] { 0xE0, 0xE1, 0xE2 }, 0, 3)

will write sequence 0xE0 0xE1 0xE2 directly, without replacing bytes to 0x3F value.

UPD.

Let's look into source code:

public void Write(string text)
{
    // preconditions checks are omitted

    byte[] bytes = this.encoding.GetBytes(text);
    this.internalSerialStream.Write(bytes, 0, bytes.Length, this.writeTimeout);
}

public void Write(byte[] buffer, int offset, int count)
{
    // preconditions checks are omitted

    this.internalSerialStream.Write(buffer, offset, count, this.writeTimeout);
}

Do you see the difference?
Method, that accepts string, converts strings to a byte array, using current encoding for port. Method, that accepts byte array, writes it directly to a stream, which is wrapper around native API.

And yes, documentation fools you.

Sign up to request clarification or add additional context in comments.

12 Comments

Yeah but what I cited("ASCIIEncoding encodes all characters greater than 127 as (char)63 or '?'") comes from the documentation of Write which takes byte array as parameter - this is why I got confused. So?
No, it would be a very weird behavior. I'll update answer.
Ok thanks. Maybe you can give me some advice here: stackoverflow.com/questions/32859276/…, I can't seem to get proper response on that. Should I try SerialPort or go with PInvoke?
@user300224: commented linked question, but I think, it will be more useful, if you'll post a specific problem.
I replied to your comment too, please see that. Yes but I didn't move to the testing part yet. Because there are some read/write methods I need to write. First selecting approach
|
2

This

port.Encoding = System.Text.Encoding.UTF8;

string testStr = "TEST";

port.Write(testStr);

and this

byte[] buf = System.Text.Encoding.UTF8.GetBytes(testStr);

port.Write(buf, 0, buf.Length);

will result in the same bytes being transmitted. In the latter one the Encoding of the serial port could be anything.

The serial port encoding only matters for methods that read or write strings.

2 Comments

Yeah but what I cited("ASCIIEncoding encodes all characters greater than 127 as (char)63 or '?'") comes from the documentation of Write which takes byte array as parameter - this is why I got confused
Yes it does and the default for the port is ASCII. You can change the encoding.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.