私は Lazarus でプロジェクトに取り組んでおり、(いくつかの制限のため) 当分の間 Delphi XE に移行することにしました。
何が起こっているかの簡単な概要:
実行時に、外部ファイルをロードしてストリームに追加しています。ストリームは、1 つのメイン オブジェクト (TObject) から派生した複数の異なるクラスに属します。これらのクラスは、メイン オブジェクトから TList に追加されます。基本的に、各クラスには独自のストリーム プロパティがあり、クラスはメイン オブジェクトの子です。
このメイン オブジェクトには、保存と読み込みの手順があります。
オブジェクトを保存すると、string to stream を使用して、他のクラスからのすべてのストリーム データもファイルに保存されます。ここでの出力文字列は、XML に保存しているため、base64 でエンコードする必要があります。
ファイルを開くとき、base64 文字列をデコードし、base64 エンコードされる前の元のファイルであるかのようにストリームに戻すという考え方です。
Lazarus では動作します。重要なコードは次のとおりです (一部は私が書いたものではないことに注意してください)。
const
Keys64 = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/';
function Encode64String(S: string): string;
function Decode64String(S: string): string;
function Encode64StringToStream(const Input: TStream; var Output: string): Boolean;
procedure Decode64StringToStream(const Input: string; Output: TStream);
procedure StringToStream(Stream: TStream; const S: string);
function StreamToString(MS: TMemoryStream): string;
implementation
function Encode64String(S: string): string;
var
i: Integer;
a: Integer;
x: Integer;
b: Integer;
begin
Result := '';
a := 0;
b := 0;
for i := 1 to Length(s) do
begin
x := Ord(s[i]);
b := b * 256 + x;
a := a + 8;
while a >= 6 do
begin
a := a - 6;
x := b div (1 shl a);
b := b mod (1 shl a);
Result := Result + Keys64[x + 1];
end;
end;
if a > 0 then
begin
x := b shl (6 - a);
Result := Result + Keys64[x + 1];
end;
end;
function Decode64String(S: string): string;
var
i: Integer;
a: Integer;
x: Integer;
b: Integer;
begin
Result := '';
a := 0;
b := 0;
for i := 1 to Length(s) do
begin
x := Pos(s[i], Keys64) - 1;
if x >= 0 then
begin
b := b * 64 + x;
a := a + 6;
if a >= 8 then
begin
a := a - 8;
x := b shr a;
b := b mod (1 shl a);
x := x mod 256;
Result := Result + chr(x);
end;
end
else
Exit;
end;
end;
function Encode64StringToStream(const Input: TStream; var Output: string): Boolean;
var
MS: TMemoryStream;
begin
Result := False;
MS := TMemoryStream.Create;
try
Input.Seek(0, soFromBeginning);
MS.CopyFrom(Input, Input.Size);
MS.Seek(0, soFromBeginning);
Output := Encode64String(StreamToString(MS));
finally
MS.Free;
end;
Result := True;
end;
procedure Decode64StringToStream(const Input: string; Output: TStream);
var
MS: TMemoryStream;
begin
try
MS := TMemoryStream.Create;
try
StringToStream(MS, Decode64String(Input));
MS.Seek(0, soFromBeginning);
Output.CopyFrom(MS, MS.Size);
Output.Position := 0;
finally
MS.Free;
end;
except on E: Exception do
raise Exception.Create('stream decode error - ' + E.Message);
end;
end;
procedure StringToStream(Stream: TStream; const S: string);
begin
Stream.Write(Pointer(S)^, Length(S));
end;
function StreamToString(MS: TMemoryStream): string;
begin
SetString(Result, PChar(MS.Memory), MS.Size div SizeOf(Char));
end;
ここでの問題は Unicode に関連していると 99% 確信しています。残念なことに、Lazarus/Freepascal は常に Unicode であり、Delphi ではなく、さまざまな文字列型を使用しているため、私のようなプロではないユーザーが解決することはほとんど不可能です!
正直なところ、上記のコードはすべて少しごちゃごちゃしていると思います。自分が何をしているのかわからないまま、文字列を何に変更すればよいかを推測しようとしているだけのように感じます。
私の最初の考えは、すべてを から に変更することString
でしたAnsiString
。これはほぼ一度は機能しましたが、使用しようとするDecode64StringToStream
とデータが返されませんでした。また、データが base64 エンコード形式で適切に保存されず、TStream.Seek が実装されていないなどのエラーが発生することもありました。
PS、私はガイドを読みましたが、古い Delphi プロジェクトを新しい Unicode バージョンに移行する方法についてのホワイトペーパーなど、たくさんありますが、正直なところ、まだ途方に暮れています。に置き換えるだけで十分だと思っていましstring
たAnsiString
が、そうではないようです。
ヒント、ポインター、または一般的なアドバイスや手がかりをいただければ幸いです。