4

I created the following code:

Function AnsiStringToStream(Const AString: AnsiString): TStream;
Begin
  Result := TStringStream.Create(AString, TEncoding.ANSI);
End;

But I'm "W1057 Implicit string cast from 'AnsiString' to 'string'"

There is something wrong with him?

Thank you.

Jhonjhon_123
  • 288
  • 3
  • 12

2 Answers2

7

The TStringStream constructor expects a string as its parameter. When you give it an an AnsiString instead, the compiler has to insert conversion code, and the fact that you've specified the TEncoding.ANSI doesn't change that.

Try it like this instead:

Function AnsiStringToStream(Const AString: AnsiString): TStream;
Begin
  Result := TStringStream.Create(string(AString));
End;

This uses an explicit conversion, and leaves the encoding-related work up to the compiler, which already knows how to take care of it.

Mason Wheeler
  • 82,511
  • 50
  • 270
  • 477
  • Another option is to disable that warning. – David Heffernan May 10 '12 at 06:05
  • @DavidHeffernan: yes, but preferably only locally so as not to lose the compiler's help elsewhere... – Marjan Venema May 10 '12 at 06:09
  • @Marjan Why? I haven't worked out what that warning is doing for me. I switch it off globally. – David Heffernan May 10 '12 at 06:20
  • @DavidHeffernan IIRC (but it is a long time since we switched and decided on all this), the warning is used for both implicit "up" and "down" casting. So disabling it globally also will take away implicit cast warnings for "down"casts from Unicode to Ansi. Although there is another "loss of data" warning for those we decided to keep all warnings (certainly in debug/IDE builds) and use explicit casts or local disabling of compiler messages to ensure nothing crept by unintentionally. And it still helps when we have to dive back into code where the encoding matters as we do so only infrequently. – Marjan Venema May 10 '12 at 06:25
4

In D2009+, TStringStream expects a UnicodeString, not an AnsiString. If you just want to write the contents of the AnsiString as-is without having to convert the data to Unicode and then back to Ansi, use TMemoryStream instead:

function AnsiStringToStream(const AString: AnsiString): TStream; 
begin 
  Result := TMemoryStream.Create;
  Result.Write(PAnsiChar(AString)^, Length(AString));
  Result.Position := 0; 
end; 

Since AnsiString is codepage-aware in D2009+, ANY string that is passed to your function will be forced to the OS default Ansi encoding. If you want to be able to pass any 8-bit string type, such as UTF8String, without converting the data at all, use RawByteString instead of AnsiString:

function AnsiStringToStream(const AString: RawByteString): TStream; 
begin 
  Result := TMemoryStream.Create;
  Result.Write(PAnsiChar(AString)^, Length(AString));
  Result.Position := 0; 
end; 
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770