2009-07-04 25 views
5

Estoy intentando convertir una cadena en una TStream. Mi código a continuación me da un mensaje de "Error abstracto" en la línea CopyFrom. Estoy contra una pared de ladrillos aquí, ¿alguna idea sobre cómo resolver esto?String to TStream

procedure StringToStream(const AString: string; out AStream: TStream); 
var 
    SS: TStringStream; 
begin 
    SS := TStringStream.Create(AString); 
    try 
    SS.Position := 0; 
    AStream.CopyFrom(SS, SS.Size); //This is where the "Abstract Error" gets thrown 
    finally 
    SS.Free; 
    end; 
end; 

Respuesta

8

AStream se declara como parámetro OUT, lo que significa que no se asigna al comienzo del procedimiento y el procedimiento es responsable de asignar un valor adecuado a eso.

Si interpreto el código correcto, debe omitir el OUT y asegurarse de que AStream se crea una instancia correctamente al llamar a la rutina.

Algunos códigos más que muestran la llamada de StringToStream pueden dar más pistas.

+0

Bueno, claramente AStream * está * asignado si obtiene un error abstracto cuando llama a un método en él Probablemente esté instanciado como un TStream en lugar de una clase descendiente. –

+1

Tiene razón. Y como la declaración real del valor otorgado para AStream debe ser exactamente TStream (de lo contrario, el compilador se quejaría), existe una alta probabilidad de que en realidad es una instancia de TStream abstracta en lugar de una clase heredada. Pero además de eso, todavía no es una buena decisión convertirlo en un parámetro de salida. –

+0

Gracias a todos los que ofrecieron ayuda. Lo llamaba con solo un TStream, de lo que ahora me doy cuenta no tiene mucho sentido. Cambié a llamar al procedimiento con un TMemoryStream y alteré el procedimiento a (rem confirmando la salida): procedimiento StringToStream (const AString: string; AStream: TMemoryStream); var SS: TStringStream; begin SS: = TStringStream.Create (AString); try SS.Position: = 0; AStream.CopyFrom (SS, SS.Size); finalmente SS.Free; final; final; Esto parece haber resuelto el problema. De nuevo, muchas gracias! –

6

CopyFrom llama a ReadBuffer, que llama a Read, y Read se declara abstracto. ¿Qué tipo de flujo estás pasando a AStream? Si no implementa Read, obtendrá un error abstracto ahí. (Y el compilador debe darle una advertencia cuando lo instancia).

+0

Precisamente. El AStream declarado como un TStream llama al método Read de la clase base. Tendría que especificar una clase (TStream) que implemente el método de lectura. – yozey

+5

No, Yozey, * declarado * como TStream no es lo que hace que se llame a la función abstracta. La función es virtual. Se llama a la función abstracta porque se ha pasado un objeto TStream real (o algún otro descendiente que aún no haya reemplazado esa función. –

4

Declarar AStream como fuera me parece incorrecto. Intenta eliminar la salida.

Si eso no ayuda, aquí es la función que utilizo:

procedure StringToStream(Stream: TStream;const S: String); 
begin 
Stream.Write(Pointer(S)^, length(S)); 
end; 
6

el siguiente procedimiento se debe hacer realidad sea exactamente lo que busca. Tenga en cuenta que su uso de AStream es responsable de liberar la instancia que se crea en este procedimiento. Está perfectamente bien devolver la clase padre (en este caso tStream) en lugar del descendiente específico.

procedure StringToStream(const AString: string; out AStream: TStream); 
begin 
    AStream := TStringStream.Create(AString); 
end; 

También puede codificar esto como una función:

Function StringToStream(const AString: string): TStream; 
begin 
    Result := TStringStream.Create(AString); 
end;