gpt4 book ai didi

delphi - 如何解决这段代码中的字节顺序问题?

转载 作者:行者123 更新时间:2023-12-02 07:41:41 25 4
gpt4 key购买 nike

为了读取特定格式的索引文件,我编写了以下代码,而不考虑字节顺序:

unit uCBI;

interface

uses
SysUtils,
Classes,
Generics.Collections;

type
TIndexList = class
private
FIndexList:TList<Cardinal>;

FOwnedStream:Boolean;
FMemoryStream: TMemoryStream;
function GetCount: Integer;

protected

public
constructor Create(AStream:TMemoryStream; OwnedStream:Boolean=True);
destructor Destroy; override;

function Add(const Value: Cardinal): Integer;
procedure Clear;

procedure SaveToFile(AFileName:TFileName);
procedure LoadFromFile(AFileName:TFileName);

property Count: Integer read GetCount;
end;

implementation

{ TIndexList }

function TIndexList.Add(const Value: Cardinal): Integer;
begin
Result := FIndexList.Add(Value)
end;

procedure TIndexList.Clear;
begin
FIndexList.Clear;
end;

constructor TIndexList.Create(AStream: TMemoryStream; OwnedStream: Boolean);
begin
FMemoryStream := AStream;
FOwnedStream := OwnedStream;
FIndexList := TList<Cardinal>.Create;
end;

destructor TIndexList.Destroy;
begin
if (FOwnedStream and Assigned(FMemoryStream)) then
FMemoryStream.Free;

FIndexList.Free;
//
inherited;
end;

function TIndexList.GetCount: Integer;
begin
Result := FIndexList.Count;
end;

procedure TIndexList.LoadFromFile(AFileName: TFileName);
var
lMemoryStream:TMemoryStream;
lCount:Cardinal;
begin
lMemoryStream := TMemoryStream.Create;

try
lMemoryStream.LoadFromFile(AFileName);
lMemoryStream.ReadBuffer(lCount,SizeOf(Cardinal));

if (lCount = Cardinal((lMemoryStream.Size-1) div SizeOf(Cardinal))) then
begin
FMemoryStream.Clear;
lMemoryStream.Position :=0;
FMemoryStream.CopyFrom(lMemoryStream,lMemoryStream.Size)
end else
raise Exception.CreateFmt('Corrupted CBI file: %s',[ExtractFileName(AFileName)]);
finally
lMemoryStream.Free;
end;
end;

procedure TIndexList.SaveToFile(AFileName: TFileName);
var
lCount:Cardinal;
lItem:Cardinal;
begin
FMemoryStream.Clear;

lCount := FIndexList.Count;
FMemoryStream.WriteBuffer(lCount,SizeOf(Cardinal));

for lItem in FIndexList do
begin
FMemoryStream.WriteBuffer(lItem,SizeOf(Cardinal));
end;
//
FMemoryStream.SaveToFile(AFileName);
end;

end.

它经过测试,似乎可以按照需要正常工作。当我使用真实的样本文件进行广泛的测试时,我感到非常惊讶。事实上,传统格式是用 Amiga 计算机设计的,具有不同的字节顺序。

我的问题:

我该如何修复它?

我想保持代码不变,并且想知道修饰后的TMemorySream是否可以,以便我可以在大端和小端之间透明地切换。

最佳答案

要更改 Cardinals 的“字节序”,您可以使用以下命令:

function EndianChange(Value: Cardinal): Cardinal;
var
A1: array [0..3] of Byte absolute Value;
A2: array [0..3] of Byte absolute Result;
I: Integer;

begin
for I:= 0 to 3 do begin
A2[I]:= A1[3 - I];
end;
end;

如果您想保持代码不变,您可以编写自己的 TMemoryStream 后代,并使用上述方法重写其 ReadWrite 方法函数,像这样:

function TMyMemoryStream.Read(var Buffer; Count: Integer): Longint;
var
P: PCardinal;
I, N: Integer;

begin
inherited;
P:= @Buffer;
Assert(Count and 3 = 0);
N:= Count shr 2;
while N > 0 do begin
P^:= EndianChange(P^);
Inc(P);
Dec(N);
end;
end;

关于delphi - 如何解决这段代码中的字节顺序问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9046610/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com