delphi определить есть ли символы юникода в строке
нужна функция которая вернет есть ли в строке юникод или нет. как это делает блокнот https://prnt.sc/bGbowOL4WHwk
причем блокнот разрешает сохранить рус буквы в ansi я нашел в модуле widestr функцию это почти то что надо только она вернет Utf8 и для русских букв хотя нужно как у блокнота только когда есть юни коды типа смайлы
function DetectUTF8Encoding(const s: RawByteString): TEncodeType;
var
c : Byte;
P, EndPtr: PByte;
begin
Result := etUSASCII;
P := PByte(PAnsiChar(s));
EndPtr := P + Length(s);
// skip leading US-ASCII part.
while P < EndPtr do
begin
if P^ >= $80 then break;
inc(P);
end;
// If all character is US-ASCII, done.
if P = EndPtr then exit;
while P < EndPtr do
begin
c := p^;
case c of
$00..$7F:
inc(P);
$C2..$DF:
if (P+1 < EndPtr)
and ((P+1)^ in [$80..$BF]) then
Inc(P, 2)
else
break;
$E0:
if (P+2 < EndPtr)
and ((P+1)^ in [$A0..$BF])
and ((P+2)^ in [$80..$BF]) then
Inc(P, 3)
else
break;
$E1..$EF:
if (P+2 < EndPtr)
and ((P+1)^ in [$80..$BF])
and ((P+2)^ in [$80..$BF]) then
Inc(P, 3)
else
break;
$F0:
if (P+3 < EndPtr)
and ((P+1)^ in [$90..$BF])
and ((P+2)^ in [$80..$BF])
and ((P+3)^ in [$80..$BF]) then
Inc(P, 4)
else
break;
$F1..$F3:
if (P+3 < EndPtr)
and ((P+1)^ in [$80..$BF])
and ((P+2)^ in [$80..$BF])
and ((P+3)^ in [$80..$BF]) then
Inc(P, 4)
else
break;
$F4:
if (P+3 < EndPtr)
and ((P+1)^ in [$80..$8F])
and ((P+2)^ in [$80..$BF])
and ((P+3)^ in [$80..$BF]) then
Inc(P, 4)
else
break;
else
break;
end;
end;
if P = EndPtr then Result := etUTF8
else Result := etANSI;
end;
думаю что это просто набор байт с разными диапазонами может с этой функции нужно лишнее исключить и и тогда она будет возвращать только если есть юни кода смайлы. ток я не уверен что именно нужно удалить. а какие диапазоны оставить
Желаемый результат
s:= '?';
if Detect(s) then // true
s:= 'рус';
if Detect(s) then // false
s:= 'eng';
if Detect(s) then // false
s:= 'русeng?';
if Detect(s) then // true
Походу дела возник вопрос еще один как код символа перевести в набор байт? И возможно ли это?
s:='А';//рус А
i:=ord(s[1]);//1040
//как 1040 перевести в набор байт (208,144) что возвращает
Arr.Arr:= TEncoding.UTF8.GetBytes(s);
Ответы (1 шт):
TEncoding (Delphi)
Я начал путь здесь -> Класс TEncoding
Библиотека Tiburon RTL также включает новый класс TEncoding. Его назначение - определить конкретный тип кодировки символов, чтобы можно было сообщить библиотеке VCL, какой тип кодировки необходимо использовать в конкретных ситуациях.
Попал сюда -> TEncoding (Delphi) - пример
В этом примере определяется кодировка исходного файла, а затем файл записывается в любой выбранной кодировке. Используйте этот проект для создания файлов любой кодировки. В этом примере требуется два текстовых редактирования и поле со списком.
procedure TForm1.Button1Click(Sender: TObject);
var
LBuffer: TBytes;
LByteOrderMark: TBytes;
LOffset: Integer;
LEncoding, DestEncoding: TEncoding;
LFileStream: TFileStream;
EncodingArray: array[0..5] of TEncoding;
begin
LEncoding:= nil;
EncodingArray[0]:= TEncoding.UTF8;
EncodingArray[1]:= TEncoding.UTF7;
EncodingArray[2]:= TEncoding.Unicode;
EncodingArray[3]:= TEncoding.Default;
EncodingArray[4]:= TEncoding.BigEndianUnicode;
EncodingArray[5]:= TEncoding.ASCII;
DestEncoding := EncodingArray[ComboBox1.ItemIndex];
LFileStream := TFileStream.Create(Edit1.Text, fmOpenRead);
try
// Read file into buffer.
SetLength(LBuffer, LFileStream.Size);
// LFileStream.Read(LBuffer[0], Length(LBuffer));
LFileStream.ReadBuffer(Pointer(LBuffer)^, Length(LBuffer));
// Identify encoding and convert buffer to UTF8.
LOffset := TEncoding.GetBufferEncoding(LBuffer, LEncoding);
// for I := 0 to Length(LBuffer) - 1 do
// Memo1.Lines.Add((LBuffer[I]));
LBuffer := LEncoding.Convert(LEncoding, DestEncoding, LBuffer,
LOffset, Length(LBuffer) - LOffset);
finally
LFileStream.Free;
end;
LFileStream := TFileStream.Create(Edit2.Text, fmCreate);
try
// Write an encoding byte-order mark and buffer to output file.
LByteOrderMark := DestEncoding.GetPreamble;
LFileStream.Write(LByteOrderMark[0], Length(LByteOrderMark));
LFileStream.Write(LBuffer[0], Length(LBuffer));
finally
LFileStream.Free;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
with ComboBox1, Items do begin
Add('TEncoding.UTF8');
Add('TEncoding.UTF7');
Add('TEncoding.Unicode');
Add('TEncoding.Default');
Add('TEncoding.BigEndianUnicode');
Add('TEncoding.ASCII');
ItemIndex := 0;
end;
end;
Я не претендую на верный ответ, но если с чего и можно было бы начать, я думаю с этих примеров. Я думаю не составит труда обернуть этот проект, записи в любую кодировку, под свои намерения.
StringCodePage
Подпрограммой StringCodePage будет возвращаться значение Word, которое соответствует кодовой странице для заданной строки.
procedure TForm88.Button2Click(Sender: TObject);
type
// Кодовая страница для ANSI-кириллицы - 1251
CyrillicString = type AnsiString(1251);
var
A: AnsiString;
U: UnicodeString;
U8: UTF8String;
C: CyrillicString;
begin
A := 'This is an AnsiString';
Memo1.Lines.Add('AnsiString Codepage: ' + IntToStr(StringCodePage(A)));
U := 'This is a UnicodeString';
Memo1.Lines.Add('UnicodeString Codepage: ' + IntToStr(StringCodePage(U)));
U8 := 'This is a UTF8string';
Memo1.Lines.Add('UTF8string Codepage: ' + IntToStr(StringCodePage(U8)));
C := 'This is a CyrillicString';
Memo1.Lines.Add('CyrillicString Codepage: ' + IntToStr(StringCodePage(C)));
end;
Результат выполнения:
The Codepage for an AnsiString is: 1252
The Codepage for an UnicodeString is: 1200
The Codepage for an UTF8string is: 65001
The Codepage for an CyrillicString is: 1251
Оригинальная статья - Delphi in a Unicode World Part II