Delphi TMemoryStream to/from Chilkat BinData

This example simulates the process:

  1. Creates a TMemoryStream with some initial data.
  2. Copies that data from the TMemoryStream to an HCkBinData object.
  3. Verifies the copy was successful.
  4. Simulates a Chilkat operation by replacing the data in HCkBinData.
  5. Copies the new data back from the HCkBinData object to the TMemoryStream.
  6. Verifies the final result in the stream.
    uses
      System.Classes, System.SysUtils, System.IOUtils, Chilkat_TLB, Vcl.Dialogs;
    
    procedure DemonstrateBinDataStreamTransfer;
    var
      BinData: HCkBinData;
      DataStream: TMemoryStream;
      Success: Boolean;
      InitialText, FinalText: string;
      Bytes: TBytes;
      PBytes: Pointer;
      DataLength: Integer;
      s: string;
    begin
      BinData := nil; // Initialize to nil for safe cleanup
      DataStream := nil;
      try
        // 1. --- Initialization ---
        BinData := CkBinData_Create();
        DataStream := TMemoryStream.Create;
        ShowMessage('--- Part 1: TMemoryStream -> HCkBinData ---');
        
        // 2. --- Prepare TMemoryStream with initial data ---
        InitialText := 'This is the initial data from the TMemoryStream.';
        Bytes := TEncoding.UTF8.GetBytes(InitialText);
        DataStream.WriteBuffer(Bytes[0], Length(Bytes));
        DataStream.Position := 0; // Reset position to the beginning for reading
        ShowMessage('TMemoryStream contains: "' + InitialText + '" (' + IntToStr(DataStream.Size) + ' bytes)');
        
        // 3. --- Copy from TMemoryStream to HCkBinData ---
        // We clear BinData first to ensure it's empty.
        CkBinData_Clear(BinData);
        Success := CkBinData_AppendData(BinData, DataStream.Memory, DataStream.Size);
        if not Success then
        begin
          // Note: AppendData rarely fails, but it's good practice.
          raise Exception.Create('Failed to append stream data to BinData.');
        end;
        
        // 4. --- Verification ---
        s := CkBinData__getString(BinData, 'utf-8');
        ShowMessage('HCkBinData now contains: "' + s + '" (' + IntToStr(CkBinData_getNumBytes(BinData)) + ' bytes)');
        if s <> InitialText then
        begin
          raise Exception.Create('Verification failed! Data was not copied correctly.');
        end;
        
        // ----------------------------------------------------------------------
        ShowMessage('--- Part 2: HCkBinData -> TMemoryStream ---');
        
        // 5. --- Simulate a Chilkat operation that modifies BinData ---
        // We'll just load new content.
        FinalText := 'This is the new data generated by a Chilkat operation.';
        CkBinData_Clear(BinData);
        CkBinData_AppendString(BinData, FinalText, 'utf-8');
        ShowMessage('HCkBinData was updated to contain: "' + FinalText + '"');
        
        // 6. --- Copy from HCkBinData back to TMemoryStream ---
        // First, clear the stream to receive the new data.
        DataStream.Clear;
        PBytes := CkBinData_GetData(BinData);
        DataLength := CkBinData_getNumBytes(BinData);
        if DataLength > 0 then
        begin
          DataStream.WriteBuffer(PBytes^, DataLength);
        end;
    
        // 7. --- Verification ---
        DataStream.Position := 0; // Reset position to read the new content
        SetLength(s, DataStream.Size);
        DataStream.ReadBuffer(s[1], DataStream.Size);
        ShowMessage('TMemoryStream now contains: "' + s + '" (' + IntToStr(DataStream.Size) + ' bytes)');
        if s <> FinalText then
        begin
          raise Exception.Create('Verification failed! Data was not copied back correctly.');
        end;
        ShowMessage('Successfully demonstrated data transfer both ways.');
        
      finally
        // 8. --- Cleanup ---
        // ALWAYS free objects in a finally block to prevent memory leaks,
        // even if an exception occurs. Check for Assigned (or nil) in case
        // the creation failed.
        if Assigned(DataStream) then
          DataStream.Free;
        if BinData <> nil then
          CkBinData_Dispose(BinData);
      end;
    end;