Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 15.05.2017, 13:40   #1
Ship_1
Форумчанин
 
Регистрация: 10.02.2014
Сообщений: 526
По умолчанию Как же работать с этим TStream?

Здравствуйте!
Суть вот в чём.
Есть строка в непонятной кодировке (когда-то пытался с этим разобраться, но до конца так и не дошёл, предпринял вторую попытку)
Декодировал её через онлайн, сохранил оба варианта в текстовый файл, через тотал коммандер глянул шестнадцатеричный вид строки. Эксперимент показал, что в непонятной кодировке байты попарно переставлены местами, а строка берётся этими парами перепутанных байт. В результате размер нормальной строки равен двойному размеру кодированной.
Сохранить в текстовый файл получилось через
Код:
SaveStrList.SaveToFile('CodeSimv.txt', TEncoding.Unicode);
(SaveStrList - TStringList)
Решил таким путём сохранить в TStream, но как работать с ним не понимаю. В результате пока насобирал такой код:
Код:
procedure TForm1.Button4Click(Sender: TObject);
var
  Stream1:TStream;
  SaveStrList:TStringList;
  a:Integer;
begin
  Stream1:=TMemoryStream.Create;
  SaveStrList:=TStringList.Create;
  SaveStrList.Add(Edit1.Text);
  SaveStrList.SaveToStream(Stream1, TEncoding.Unicode);
  a := Stream1.Size;
  SaveStrList.LoadFromStream(Stream1);
  ShowMessage(IntToStr(a)+#13+IntToStr(length(SaveStrList.Text)));
  SaveStrList.Free;
  Stream1.Free;
end;
Программа, почему-то, показывает, что a = 128 а length(SaveStrList.Text) = 0. Как с этим быть и как докопаться до байт, чтобы переставить их местами обратно?
Ship_1 вне форума Ответить с цитированием
Старый 15.05.2017, 13:44   #2
p51x
Старожил
 
Регистрация: 15.02.2010
Сообщений: 15,707
По умолчанию

После записи перед чтением не установили позицию стрима в 0 и читаете в конце, а там естественно 0 символов.
p51x вне форума Ответить с цитированием
Старый 15.05.2017, 13:45   #3
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

Что за строка-то?
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.
Alex11223 вне форума Ответить с цитированием
Старый 15.05.2017, 14:01   #4
Pavia
Лис
Старожил
 
Аватар для Pavia
 
Регистрация: 18.09.2015
Сообщений: 2,409
По умолчанию

Цитата:
а строка берётся этими парами перепутанных байт.
изучите как числа хранятся в компьютере. Есть два подхода старшими разрядами в перёд и второй младшими.Есть от Intel, а есть от Motorola
https://ru.wikipedia.org/wiki/%D0%9F...82%D0%BE%D0%B2

Цитата:
. Как с этим быть и как докопаться до байт, чтобы переставить их местами обратно?
Заведите массив. Считайте свою строку в массив и далее работайте с массивом.

Код:
var row:array of Byte;
begin
...
SetLength(row, stream.Size);
stream.ReadBuffer(@row[0], stream.Size);
Про форматы строк 2-х байтовые это либо Unicode или Utf-16.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
У дзен программиста программа делает то что он хотел, а не то что он написал .
Pavia вне форума Ответить с цитированием
Старый 15.05.2017, 14:10   #5
Ship_1
Форумчанин
 
Регистрация: 10.02.2014
Сообщений: 526
По умолчанию

p51x Помогло. Не думал, что в этом случае надо всё равно на начало перемещать, а не только для Read...
Alex11223 строка
Цитата:
屜浯獰牯敫琳⹬潣慬峏尰ㄳ㈭ㄶ峎퇏峑술컏템퇢 忱弰ㄳ㈭ㄶ⃎쿑弨퇑���⥜퇢忱弰ㄳ㈭ㄶ ⃎쿑
В результате получаю нормальную строку таким путём:
Код:
procedure TForm1.Button4Click(Sender: TObject);
var
  Stream1:TStream;
  SaveStrList:TStringList;
  i:Integer;
  TmpStr, TmpS:String;
begin
  Stream1:=TMemoryStream.Create;
  SaveStrList:=TStringList.Create;
  SaveStrList.Add(Edit1.Text);
  SaveStrList.SaveToStream(Stream1, TEncoding.Unicode);
  Stream1.Seek(1,soFromBeginning);
  SaveStrList.LoadFromStream(Stream1);
  TmpStr:=SaveStrList.Text;
  TmpS:='';
  for i:=1 to (Length(TmpStr)-1) div 2 do
  begin
    TmpS:=TmpS+TmpStr[i*2+1]+TmpStr[i*2];
  end;
  Edit4.Text:=TmpS;
  SaveStrList.Free;
  Stream1.Free;
end;
В Edit1 входная строка из иероглифов, в Edit4 результирующая.
Если в
Код:
Stream1.Seek(1,soFromBeginning);
вместо 1 ставлю 0, получаю на выходе опять те же иероглифы. Если в
Код:
for i:=1 to (Length(TmpStr)-1) div 2 do
ставлю от 0, от получаю в Edit4 "ю" и всё.
В принципе, в данном виде меня бы всё устраивало, но интересуют два вопроса: нормально ли такое преобразование (или можно как-то лучше) и как без потока понять: строка на входе нормальная или из иероглифов?
Шестнадцатиричный код показывает, что первый символ FF, второй FE. Как-то по ним, видимо, но можно ли их проверить без потоков?

Pavia в конец потом надо добавить?
Код:
SetLength(row, 0);
Цитата:
Есть два подхода старшими разрядами в перёд и второй младшими.
Big Indian и Small Indian - это не про это?

Последний раз редактировалось Ship_1; 15.05.2017 в 14:17.
Ship_1 вне форума Ответить с цитированием
Старый 15.05.2017, 14:19   #6
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

Цитата:
Сообщение от Ship_1 Посмотреть сообщение
Шестнадцатиричный код показывает, что первый символ FF, второй FE
Это BOM https://ru.wikipedia.org/wiki/%D0%9C...82%D0%BE%D0%B2

FFFE это Little Endian, FEFF — Big Endian.

То есть видимо там UTF-16 LE.

Скорее всего можно просто присвоить в WideString.
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.
Alex11223 вне форума Ответить с цитированием
Старый 15.05.2017, 14:35   #7
Ship_1
Форумчанин
 
Регистрация: 10.02.2014
Сообщений: 526
По умолчанию

Код:
  TWS:=WideString(Edit1.Text);
  Edit4.Text:=TWS;
Так? Получает те же иероглифы.
А как получить BOM строки TmpStr? Если просто TmpStr[1] - это же будет просто первый иероглиф, и, как понимаю, без этого BOM...

P.S. Спасибо всем за ссылки, где можно почитать дополнительную информацию!
Ship_1 вне форума Ответить с цитированием
Старый 15.05.2017, 14:50   #8
Pavia
Лис
Старожил
 
Аватар для Pavia
 
Регистрация: 18.09.2015
Сообщений: 2,409
По умолчанию

Ship_1
Цитата:
Сообщение от Ship_1 Посмотреть сообщение
Pavia в конец потом надо добавить?
Для динамических массивов не нужно. В дельфи для них работает автоматическая сборка мусора. По выходу из функции массив row очистится и удалится - самостоятельно, без вашей помощи.

Цитата:
Сообщение от Ship_1 Посмотреть сообщение
Big Indian и Small Indian - это не про это?
Да про них.

Забыл спросить какая версия Delphi у вас?
Если XE то там

Код:
var
  Encoding:TEncoding;
  Unicode:TEncoding;
  Text:String;
  Stream:TBytesStream;
  Bytes:Tbytes;
begin
     Stream:=TBytesStream.Create;
     Stream.LoadFromFile(FileIn);

     Stream.Seek(0,soBeginning);
     Encoding:=Nil;
     Unicode:=TEncoding.Unicode.Create;
     TEncoding.GetBufferEncoding(Stream.Bytes, Encoding, Unicode);
     Text:=Encoding.GetString(Stream.Bytes);
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
У дзен программиста программа делает то что он хотел, а не то что он написал .

Последний раз редактировалось Pavia; 15.05.2017 в 14:52.
Pavia вне форума Ответить с цитированием
Старый 15.05.2017, 15:00   #9
Ship_1
Форумчанин
 
Регистрация: 10.02.2014
Сообщений: 526
По умолчанию

Pavia Да, в данном случае XE. Но, если не сложно, хотелось бы знать как и для Delphi7 это можно сделать. Сейчас использовал XE потому что в D7, как понимаю, нет TEncoding.
И у меня текст не из файла берётся...
Код:
Stream.LoadFromFile(FileIn);
У меня это кусок из текста будет...
Ship_1 вне форума Ответить с цитированием
Старый 15.05.2017, 16:43   #10
Ship_1
Форумчанин
 
Регистрация: 10.02.2014
Сообщений: 526
По умолчанию

Pavia, попробовал с массивом. Но компилятор выдал ошибку:
Цитата:
[DCC Error] Unit1.pas(212): E2197 Constant object cannot be passed as var parameter
(на строчке "ReadBuffer")
Ship_1 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
loadfromfile(TStream as file) как-то так IvaniuS Общие вопросы Delphi 4 22.07.2013 20:58
Popupmenu как работать с этим? Человек Панда Общие вопросы Delphi 4 30.06.2011 20:41
Как работать с tStream для отправки пост запроса? Айдар Работа с сетью в Delphi 2 04.01.2011 20:34
С++. Что и как можно внести в DLL и как потом с этим работать? dampirik Помощь студентам 5 21.09.2009 08:19
Как передать http.get в Tstream?(indy) TwiX Работа с сетью в Delphi 3 09.08.2009 20:31