Форум: "Основная";
Текущий архив: 2005.03.06;
Скачать: [xml.tar.bz2];
Вниз
Как правильно массив байт привести к integer? Найти похожие ветки
← →
Aleksandr. (2005-02-09 14:38) [0]Читаю буфер из стрима, в который было записано 1 размером в integer:
var
Buf : array of byte;
i : integer;
begin
SetLength(Buf,SizeOf(Integer));
Stream.Read(Buf[0],Length(buf));
Move(Buf[0],i,Length(Buf);
в Buf после чтения находится (0,0,0,1), но такое приведение к integer дает в результате совершенно дикое число. Как буфер правильно привести к integer?
← →
Ega23 © (2005-02-09 14:40) [1]Дикое число - поди 16777216? :о)
← →
Alexander Panov © (2005-02-09 14:42) [2]А записывал в поток число как?
← →
КаПиБаРа © (2005-02-09 14:46) [3]Stream.Read(I,SizeOf(Integer));
← →
Aleksandr. (2005-02-09 14:47) [4]Ega23 © : ага. Оно самое.
Alexander Panov © :
В поток писалось Write(I,SizeOf(i));
Проблема началась с того, что потребовалось обеспечить совместимость новой и старой программы в работе с потоком на сокете. При этом новая однозначно в поток пишет integer и останавливается, а старая пишет туда большой и толстый массив байт. Поэтому для совместимости читаю буфер размером с integer и по его числу определяю, какой версией была сделана запись.
← →
Ega23 © (2005-02-09 14:49) [5]AFAIK, в INT386 семействе процессоров порядок битов идёт слева направо.
Т.е. integer будет выглядеть так 4-й байт, 3-й байт, 2-й байт, первый байт.
И если
var
i:Integer;
i:=1
то в памяти реально это будет выглядеть, как 01, 00, 00, 00
← →
begin...end © (2005-02-09 14:52) [6]> Aleksandr. (09.02.05 14:38)
У меня всё нормально читается:
var
Stream: TMemoryStream;
I, J: Integer;
Buf: array of Byte;
begin
I := 1;
Stream := TMemoryStream.Create;
try
Stream.Write(I, SizeOf(I));
Stream.Position := 0;
SetLength(Buf, SizeOf(Integer));
Stream.Read(Buf[0], Length(Buf));
Move(Buf[0], J, Length(Buf));
ShowMessageFmt("I = %d; J = %d", [I, J])
finally
Stream.Free
end
end.
← →
Aleksandr. (2005-02-09 14:52) [7]Точнее, старая программа писала в буфер record из трех integer. Если проблема в том, что в буфере поменяны местами байты, боюсь, как бы не оказалось, что при записи такого рекорда там весь буфер задом наперед окажется.
← →
Aleksandr. (2005-02-09 14:54) [8]Ega23 © :
ох, эти операции сдвига, млин... туго у меня с ними. Как развернуть i в нужную сторону после приведения?
← →
Ega23 © (2005-02-09 14:59) [9]Если ты по-байтно потом к этому буферу будешь обращаться, то, конечно, сдвигать надо. А так - читай сразу integer.
Но если сдвигать, то вот функция. Честно содрана с не_помню_чьего исходника. Переводила представление числа в I386 для MAC:
function Swap32(Value: Integer): Integer;
var
b1, b2, b3, b4 : Integer;
begin
b1 := Value and 255;
b2 := (Value shr 8) and 255;
b3 := (Value shr 16) and 255;
b4 := (Value shr 24) and 255;
b1 := b1 shl 24;
b2 := b2 shl 16;
b3 := b3 shl 8;
Result := b1 or b2 or b3 or b4;
end;
← →
Aleksandr. (2005-02-09 15:03) [10]Ega23 © :
Епрст. Как все сложно-то. Спасибо! Только еще вопрос: а как будет располагаться в буфере такое:
type
TRec = record
i1 : integer;
i2 : integer;
i3 : integer;
end;
var
R : TRec;
begin
Stream.Write(R,SizeOf(r))
В смысле, i1, i2, i3 там будут последовательно, но с перевернутыми байтами внутри числа, или еще и сам порядок полей будет i3, i2, i1?
← →
Ega23 © (2005-02-09 15:06) [11]Если ты пишешь данные в буфер по-рекордно, то и читай их оттуда по-рекордно, тогда никаких проблем не будет.
А вот если их оттуда по-байтово читать, то можно на грабли нарваться...
← →
Aleksandr. (2005-02-09 15:14) [12]Ega23 © :
Ну не могу я их порекордно читать... Если в буфере окажется только четыре байта, а я буду ждать 12 байт, для соединения это в конечном итоге закончится таймаутом...
← →
begin...end © (2005-02-09 15:17) [13]> Aleksandr. (09.02.05 14:54) [8]
1.
for I := 0 to 3 do
CopyMemory(Pointer(Cardinal(@NewValue) + I), Pointer(Cardinal(@OldValue) + 3 - I), 1)
2.
NewValue := ((OldValue and $FF000000) shr 24) or ((OldValue and $FF0000) shr 16) or ((OldValue and $FF00) shr 8) or (OldValue and $FF)
← →
begin...end © (2005-02-09 15:23) [14]> Aleksandr. (09.02.05 15:14) [12]
Как в буфере может оказаться только четыре байта, если буфером будет переменная типа записи TRec?
← →
Aleksandr. (2005-02-09 15:34) [15]begin...end © :
Я же объяснил, что в поток могут записывать две программы - старая версия пишет integer, а новая - только integer, в то время как приемник для чтения потока один общий. Спасибо за код.
← →
begin...end © (2005-02-09 18:56) [16]Кстати, я забыл про команду ассемблера BSWAP, как раз подходящую для этого случая.
var
I: Integer;
begin
I := ...;
asm
MOV EAX,I
BSWAP EAX
MOV I,EAX
end
...
end.
Простенько и со вкусом :-)
← →
SammIk © (2005-02-20 21:58) [17]Вот так-так
← →
Verg © (2005-02-20 22:07) [18]
> в Buf после чтения находится (0,0,0,1), но такое приведение
> к integer дает в результате совершенно дикое число. Как
> буфер
Сетевой порядок байтов. Любая многобайтовая переменная передается в порядке уменьшения старшинства байтов в ней.
В данном случае переменная четырехбайтовая.uses Winsock;
Stream.Read(I, sizeof(I));
I := ntohl( I );
ntohl - Network To Host byte order convertion for Long
← →
SammIk © (2005-02-20 22:24) [19]Товарищь Верг, ну вы и выпендрились же)))
А чем bswap не то?
← →
Anatoly Podgoretsky © (2005-02-20 23:20) [20]И будешь голову ломать над этим bswap скажем в .NET
← →
SammIk © (2005-02-21 07:04) [21]С чегоже ломать-то?
Комент поставил и усе.
И что такое дотнет не знаю и знать не хочу.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2005.03.06;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.034 c