Delphi - Проблема с Set String и PAnsiChar и другими строками не отображается - PullRequest
1 голос
/ 13 марта 2009

Я получал совет от Роба Кеннеди , и одним из его предложений, который значительно увеличил скорость приложения, над которым я работал, было использование SetString, а затем загрузка его в компонент VCL, который его отображал. .

Я использую Delphi 2009, так что теперь PChar является Unicode,

SetString(OutputString, PChar(Output), OutputLength.Value);
edtString.Text := edtString.Text + OutputString;

Работает, и я сам изменил его на PChar, но так как перемещаемые данные не всегда являются Unicode, на самом деле это обычно ShortString Data .... так что он фактически дал мне использовать:

SetString(OutputString, PAnsiChar(Output), OutputLength.Value);
edtString.Text := edtString.Text + OutputString;

Ничего не появляется, но я проверяю в отладчике, и текст, который обычно появлялся так, как я делал это при построении 1 символа за раз в прошлом, был в переменной.

Как ни странно, я не первый раз сталкиваюсь с этим сегодня вечером. Поскольку я пытался придумать другой способ, я воспользовался его советом и вместо того, чтобы встраивать в TCaption VCL, я встроил его в строковую переменную, а затем скопировал, но когда я отправляю его, ничего не отображается. Еще раз в отладчике переменная, в которую встроены данные ... содержит данные.

for I := 0 to OutputLength.Value - 1 do
begin
  OutputString := OutputString + Char(OutputData^[I]);
end;
edtString.Text := OutputString;

Выше не работает, но старый медленный способ сделать это работало очень хорошо ...

for I := 0 to OutputLength.Value - 1 do
begin
  edtString.Text := edtString.Text + Char(OutputData^[I]);
end;

Я попытался сделать переменную ShortString, String и TCaption, но ничего не отображается. То, что я также нахожу интересным, - то, что я встраиваю свои шестнадцатеричные данные из того же массива в richedit, это очень быстро, в то время как делать это внутри редактирования текстовых данных очень очень медленно. Вот почему я не потрудился изменить код для richedit, так как он работает очень быстро.

Изменить, чтобы добавить - я думаю, что я нашел проблему, но у меня нет решения. Если я отредактирую значение в отладчике, чтобы удалить все, что не может быть отображено (которое старым методом раньше просто не отображалось ... не сбой), то отображается то, что у меня осталось. Так что, если это просто вопрос избавления от байтов, которые были превращены в символы, которые являются мусором, как я могу это исправить?

У меня в основном поступают необработанные данные с устройства SCSI, которое отображается в стиле hex-редактора. Мой оригинальный медленный стиль добавления одного символа за раз успешно отображал строки и строки Юникода, в которых не было символов, специфичных для Юникода. Более быстрые методы, даже если они работают, не будут отображать ShortStrings в одну сторону, а другой способ не будет отображать UnicodeStrings, которые не используют не 0-255 символов. Я действительно люблю и могу использовать повышение скорости, но если это означает, что нужно пожертвовать способностью читать строку ... тогда какой смысл в приложении?

EDIT3 - Хорошо, теперь, когда я выяснил, что 0-31 является контрольным символом, а 32 и выше действительным, я думаю, что я попытаюсь отфильтровать символ и заменить недопустимые на a. это то, что я планировал сделать позже, чтобы эмулировать стиль шестнадцатеричного редактора.

Если есть какие-либо другие предложения, я был бы рад услышать о них, но в противном случае я думаю, что смогу создать решение, которое будет быстрее оригинала и в то же время сделает то, что мне нужно.

Ответы [ 3 ]

3 голосов
/ 13 марта 2009

Некоторые комментарии:

  1. Ваш вопрос очень неясен. Что именно вы хотите сделать?
  2. Ваш вопрос выглядит ужасно, пожалуйста, проверьте ваш текст с помощью проверки орфографии.
  3. Вопрос, на который вы ссылаетесь, такой: Delphi обращается к данным из динамического массива, который заполняется из нетипизированного указателя
  4. Пожалуйста, дайте полный пример кода вашей функции, как вы делали в предыдущем вопросе. Я хочу знать, реализовали ли вы предложение Роба Кеннеди или код, который вы дали себе в следующем ответе (будем надеяться, что нет :))
  5. Насколько я понимаю ваш вопрос: вы отправляете запрос на ваше устройство SCSI и получаете обратно массив байтов, который сохраняете в переменной OutputData. После этого вы хотите показать свои данные пользователю. Итак, ваш реальный вопрос: Как показать массив байтов пользователю?
  6. Войдите в систему как тот же пользователь и не создавайте учетную запись для каждого нового вопроса. Таким образом, мы можем отслеживать историю ваших вопросов и узнать, что вы имеете в виду под «получением совета».

Некоторые предположения и предположения, если я прав относительно истинного значения вашего вопроса:

  1. Отображение ваших данных в виде шестнадцатеричной строки не вызовет проблем
  2. Отображение ваших данных в обычном поле Memo вызывает проблемы, хотя строка Delphi может содержать любой символ, включая 0 байтов, их отображение вызовет проблемы. TMemo, например, покажет ваши данные до первых 0 байт. Что вы должны сделать (и вы дали ответ самостоятельно), это заменить не видимые символы на пустышку. После этого вы можете показать свои данные в TMemo. Фактически все программы просмотра в шестнадцатеричном формате делают то же самое, символы, которые не могут быть напечатаны, будут отображаться в виде точек.
1 голос
/ 13 марта 2009

Я использовал PAnsiChar в моем примере по причине. Похоже, OutputLength измеряется в байтах, а не в символах, поэтому я обязательно использовал тип, длина которого всегда измеряется в байтах. Вы также заметите, что я показал объявление OutputString как AnsiString.

Поскольку элемент управления для редактирования хранит Unicode, произойдет преобразование между AnsiString и UnicodeString. Это будет учитывать текущую кодовую страницу системы, но это, вероятно, не то, что вы хотите. Возможно, вы захотите объявить переменную как RawByteString. С ним не будет связана никакая кодовая страница, поэтому не будет никаких неожиданных преобразований.

Не используйте строки для хранения двоичных данных. Если вы создаете то, что составляет шестнадцатеричный редактор, то вы работаете с двоичными данными. Важно помнить это. Даже если ваши двоичные данные оказываются состоящими в основном из байтов, которые могут быть интерпретированы как текст, вы не можете рассматривать данные как текст, или вы столкнетесь именно с проблемами, с которыми вы сталкиваетесь - символами, которые не так, как ожидалось. Если вы получаете кучу байтов от вашего устройства SCSI, то храните их в виде массива байтов, а не символов.

В шестнадцатеричных редакторах вы заметите, что они всегда показывают шестнадцатеричные значения байтов. Они могут показывать те байты, которые интерпретируются как символы, но это вторично, и они обычно показывают только те байты, которые могут представлять символы ASCII; они не пытаются слишком увлекаться базовым дисплеем. Шестнадцатеричные редакторы good также предложат отображать данные, интерпретируемые как широкие символы. Это помогает в отладке, потому что пользователь может просматривать одни и те же данные несколькими способами. Но они просто просмотров данных. На самом деле они не меняют двоичное содержимое данных.

0 голосов
/ 13 марта 2009

Когда вы отфильтровываете не видимые символы ... Вам, вероятно, нужно решить, что делать с парой таких символов, как # 9 (вкладка), # 10 (LF), # 11 (вкладка Verticle), # 12 (FF- или Новая страница), № 13 (CR)

...