title: Why Delphi TMemoryStream Read TBytes and Array Of Bytes is different?
body: <p>I am writing a procedure to do Z85Encoding of a bytes sequences using Delphi 2010.  So I wrote a function:</p>
  <pre><code>function Z85Encode(input, output: TStream): integer
  </code></pre>
  <p>and expect to pass in a <strong>Stream</strong>.  Next I wrote an overloaded function</p>
  <pre><code>function Z85Encode(b: TBytes): string;
  </code></pre>
  <p>which will write the byte sequence into a <strong>TBytesStream</strong> (same to <strong>TMemoryStream</strong>), call the encode function, then read the encoding data to the Result string.</p>
  <p>Problem was I found the <code>TStream.Read</code> behave very different from the documentation and I cannot understand it.  Thou I can use other way to finish the function, but I don't quite understand why?  Which may me wonder how Delphi implement the <strong>TBytes</strong> type.</p>
  <p>To illustrate my question, I wrote the following test procedure:</p>
  <pre><code>procedure Test;
  var
    iStream: TMemoryStream;
    n: integer;
    a: TBytes;
    b: TBytes
    c: array [0..4] of Byte;
  begin
    b := TEncoding.UTF8.GetBytes('abcdefghij');  // byte from 97 to 106
    iStream := TMemoryStream.Create;
    try
      iStream.Write(b, Length(b));
      iStream.Seek(0, soBeginning);
      n := iStream.Read(a, 5); // expect only 5 bytes read, but the whole array is back.
      ShowMessage(IntToStr(n));  // n is 5
      ShowMessage(IntToStr(Length(a)));  // length is 10!!
      iStream.Seek(0, soBeginning);
      n := iStream.Read(c, 5);   // c contains random number, not 97, 98, ...
      ShowMessage(IntToStr(n));  // n is 5
    finally
      iStream.Free;
    end;
  end;
  </code></pre>
  <p>First question, in according to the document, Read should only read count of byte.  But if I pass in a <strong>TBytes</strong> varaible, it read the entire byte array but the return read count is 5.  I also wonder why I did not need to allocate memory to the variable <code>a</code> first.  It seems the <code>Stream.Read</code> will allocate memory for the variable, which is no expected.</p>
  <p>Second question, when <code>TStream.Read(c, 5)</code> where <code>c</code> is an <code>array [0..4] of byte</code>.  The value in the <code>c</code> array is some random value, not <code>97</code>, <code>98</code>, <code>99</code>, <code>100</code>, and <code>101</code>.</p>
  <p>With further testing, if I change the <strong>TStream.Write</strong> to</p>
  <pre><code>for n := 0 to High(b) do begin
    iStream.Write(b[n], 1);
  end;
  </code></pre>
  <p>Then <code>Read(a, 5)</code> will not get any result, <code>Length(a)</code> will get access violation, yet <code>Read(c, 5)</code> will get the correct result.</p>
  <p>It seems both <strong>Read</strong> and <strong>Write</strong> take an open type parameter and behave differently in according to the parameter type.  Behave differently can be understandable if eventually it is to read or write the byte value of the variable, but it seems it do more then just determine the byte content from the variable.  Then the <strong>Read</strong> and <strong>Write</strong> are expected to use the same variable type and was not my expect.</p>