Приложение Delphi Berlin 10.1 OS X Расшифруйте кириллицу для записи в hardDevice
У меня есть приложение Delphi, мне нужно переписать его для OS X. Это приложение записывает / читает данные в / из HID-устройства.
У меня есть проблемы, когда я пытаюсь написать строку из Mac.
Вот строка, которую я пишу (из отладчика на Windows): "Новый комплекс 1", и это хорошо работает. Между тем, если скопировать это из отладчика куда-нибудь, оно становится '1îâûé êîìïëåêñ 1'. Устройство показывает это, как было написано, кириллицей. И это нормально.
Когда я пытаюсь повторить эти шаги на OS X, устройство показывает нечитаемые символы. Но если я сделаю жесткий код 'îâûé êîìïëåêñ 1' из примера Windows, то все в порядке снова.
Дайте несколько советов.
Как это на windows какой-то код:
s:= 'Новый комлекс 1'
s:= AnsiToUtf8(ReplaceNull(s));
Вот ReplaceNULL:
function ReplaceNull(const Input: string): string;
var
Index: Integer;
Res: String;
begin
Res:= '';
for Index := 1 to Length(Input) do
begin
if Input[Index] = #0 then
Res:= Res + #$12
else
Res:= Res + Input[Index];
end;
ReplaceNull:= Res;
end;
эту строку я помещаю в Tstringlist и затем сохраняю в файл:
ProgsList.SaveToFile(Mwork.pathLibs+'stream.ini', TEncoding.UTF8);
Другая программа читает этот список и затем записывает на устройство:
Progs:= TStringList.Create();
Progs.LoadFromFile(****);
s:= UTF8ToAnsi(stringreplace(Progs.Strings[i], #$12, #0, [rfReplaceAll, rfIgnoreCase]));
А затем запишите это на устройство.
Таким образом, строка, которая пишет, выглядит так:
"'þ5'#0'ÿ'#$11'Новый комплекс 1'#0'T45/180;55;70;85;90;95;100;T45/180'#0'ÿ'"
На Mac я успешно получаю ту же строку. Но устройство не может показать это на кириллице.
2 ответа
Ответ был следующим. Delphi Berlin 10.1 использует KOI8-R, а мое устройство - cp1251. Поскольку я хотел написать русские символы (кириллица), я создал таблицу соответствий для символов из KOI8-R и cp1251.
Итак, я беру строку в KOI8-R, чтобы сделать это в cp1251.
Простой код:
Dict:=TDictionary<String,String>.Create;
Dict.Add(#$439,#$E9);//'й'
Dict.Add(#$44E,#$FE);//'ю'
Dict.Add(#$430,#$E0);//'а'
....
function tkoitocp.getCP1251Code(str:string):string;
var i:integer; res,key,val:string; pair:Tpair<String,String>;
begin
res:='';
for i:=1 to length(str) do
begin
if dict.ContainsKey(str[i]) then
begin
pair:= dict.ExtractPair(str[i]);
res:=res+pair.Value;
dict.Add(pair.Key,pair.Value);
end
else
res:=res+str[i];
end;
Result:=res;
end;
Дельфи string
кодируется в UTF-16 на всех платформах. Нет необходимости конвертировать его, если только вы не взаимодействуете с данными, не относящимися к Unicode, за пределами вашего приложения.
При этом, если у вас есть байтовый массив, который закодирован в определенном наборе символов, вы можете преобразовать его в другой набор символов с помощью Delphi. TEncoding.Convert()
метод. Вы можете использовать TEncoding.GetEncoding()
способ получить TEncoding
объект для определенного набора символов (если он отличается от стандартных поддерживаемых наборов символов - ANSI, ASCII, UTF-7, UTF-8 и UTF-16 - которые имеют свои собственные методы получения свойств в TEncoding
).
var
SrcEnc, DstEnc: TEncoding;
SrcBytes, ConvertedBytes: TBytes;
begin
SrcBytes := ...; // Cyrillic encoded bytes
SrcEnc := TEncoding.GetEncoding('Cyrillic'); // or whatever the real name is...
try
DstEnc := TEncoding.GetEncoding('Windows-1251');
try
ConvertedBytes := TEncoding.Convert(SrcEnc, DstEnc, SrcBytes);
finally
DstEnc.Free;
end;
finally
SrcEnc.Free;
end;
// use ConvertedBytes as needed...
end;
Обновление: чтобы закодировать строку Unicode в определенном наборе символов, просто вызовите TEncoding.GetBytes()
метод, например:
s := 'Новый комлекс 1';
Enc := TEncoding.GetEncoding('Windows-1251');
try
bytes := Enc.GetBytes(s);
finally
Enc.Free;
end;
s := 'Новый комлекс 1';
bytes := TEncoding.UTF8.GetBytes(s);
Вы можете использовать TEncoding.GetString()
декодировать байты в определенной кодировке обратно в строку, например:
bytes := ...; // Windows-1251 encoded bytes
Enc := TEncoding.GetEncoding('Windows-1251');
try
s := Enc.GetString(bytes);
finally
Enc.Free;
end;
bytes := ...; // UTF-8 encoded bytes
s := TEncoding.UTF8.GetString(bytes);