为防止找不到相关内容,所以,在这里留一个印记。
/--------流转换Begin------- //
function StreamToBytes(aStream:TStream):TBytes;
begin
// aStream := TMemoryStream.Create; //此处,不需要初始化流
try
SetLength(Result, aStream.Size);
aStream.Position := 0;
aStream.Read(Result[0], aStream.Size);
finally
aStream.Free;
end;
end;
//使用Stream前,需要Stream.Position := 0; 否则,读取不到内容
function BytesToStream(aBytes:TBytes):TStream;
var
aStream: TStream;
begin
aStream := TMemoryStream.Create;
try
aStream.Write(aBytes[0],length(aBytes));
aStream.Position := 0;
result :=aStream;
finally
//aStream.Free; //此处,不可释放
end;
end;
function StreamToHexStr(aStream:TStringStream):string; //使用Tstream总不成功,不知道有好的办法没有?!虽然可以使用StreamToBytes,再BytesToHexStr
/现在知道了,Tstream是个虚函数,必须有载体才能使用。新单元增加了TBytesStream,方便了许多
var
Len: Integer;
begin
aStream.Position :=0;
Len :=aStream.size;
Result :='';
SetLength(Result, len*2);
BinToHex(PAnsiChar(aStream.DataString), PAnsiChar(Result), len);
//BinToHex(PAnsiChar(aStream), PAnsiChar(Result), len); //用stream不成功
// BinToHex(@aStream, PAnsiChar(Result), len); //用stream不成功
end;
举例更容易看清楚使用方法:
procedure TForm1.Button2Click(Sender: TObject); //StreamToBytes
var
Stream: TStream;
Arr_Byte: TBytes;
isize:integer;
begin
Stream := TMemoryStream.Create; //必须初始化
Memo1.lines.SaveToStream(Stream);
//isize :=Stream.Size;
// showmessage(inttostr(isize));
Stream.Position :=0;
Arr_Byte :=StreamToBytes(Stream);
edit1.Text :=BytesToHexStr(Arr_Byte,length(Arr_Byte));
end;
procedure TForm1.Button3Click(Sender: TObject); //BytesToStream
var
Stream: TStream;
Arr_Byte: TBytes;
i:integer;
begin
SetLength(Arr_Byte, 7);
for i := 0 to High(Arr_Byte) do Arr_Byte[i] := $41 + i;
memo1.Lines.LoadFromStream(BytesToStream(Arr_Byte));
edit1.Text :=memo1.Text;
end;
procedure TForm1.Button7Click(Sender: TObject); //StreamToHexStr
var Stream: TstringStream;
begin
Stream := TStringStream.Create('');
Memo1.lines.SaveToStream(Stream);
edit1.text :=StreamToHexStr(Stream);
end;
把更新的单元发到这里,好找寻D7EncodedText.pas(20150324):
unit D7EncodedText; { V1.5 ---2015.0324---- ---------序--------- 实际上,数组,字符串,整数等都是存在字节内的,本质上,连续的字节就形成流。 流的操作,需要注意,经常要初始化,读写都需要stream.Position := 0; 流的关键函数就是system.move,它主要对内存进行操作的 ---------序完--------- 1.D7(delphi2007)之前的memo等都只支持AnsiString;本单元主要为<=D7的使用;仅此纪念D7的了; 2. 因Delphi 2010之后的默认字符集都是Unicode了,简化了很多(主要使用了TEncoding类); Memo可以直接支持读入ASCII,UTF-8,Unicode;写则可以指定写入的编码格式。 3.在中文操作系统下,D7默认使用的GB2312字符集,故AnsiString的字符集可看做GB2312; 缺省的编译选项下,编译器认为String就是AnsiString字符串(可以使用$H编译开关来进行修改),保存就是ASCII。 4.D7前的widestring实际就是Unicode字符,默认string等同于AnsiString。参见CoderOfUnicode。 5.觉得最重要的是理解到字符存为2进制按Byte放置的,所以,字符的1个Byte内容可转为2位HexStr; 同样,2位HexStr可转换为1字节内容(对这些连续的Byte可根据Ansi,UTF8,Unicode解码 就得到对应的字符的)。 这种方式才是最值得提倡的和便于理解的。 Byte为1字节可直接将小于255的值直接赋给它,intger,char,Hex值等; 如:ABtye :=255; $FF; Byte('A'); 6.个人觉得转码实际就是byte的操作,用Byte来做转换方便得多的(Byte 0..255,小于256的整数赋值给byte就是操作Byte的了)。 比如我写的coderToUTF8Str。 7.注意:Unicode只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储。所以,Big endian方式 是所见即所得,即编码'一':U4E 00;BE方式存储后用UltraEdit打开也是4E 00(先存高字节);但Little endian方式存储后则为 00 4E(先存小端低字节00); 8.增加StreamToBytes和BytesToStream,以便转换流的操作(2015-03-20);
2015-03-20
Notepad(记事本)只支持四种格式:ANSI/Unicode/Unicode big endian/UFT-8,在Delphi中如何判断与读取这些不同格式的文本呢?
首先,不同编码的文本,是根据文本的前两个字节来定义其编码格式的。定义如下:
ANSI: 无格式定义; Unicode: 前两个字节为FFFE; Unicode big endian: 前两字节为FEFF; UTF-8: 前两字节为EFBB; 实际前3字节为EF BB BF }
interface uses SysUtils,Classes,Windows, Variants;
type FReadText=array of WideString; TBytes = array of Byte;
TTextFormat=(Ansi, Unicode, UnicodeBigEndian, Utf8);
{ TBytesStream }
TBytesStream = class(TMemoryStream) private FBytes: TBytes; FCapacity: Longint; FMemory: Pointer; FSize, FPosition: Longint; protected function Realloc(var NewCapacity: Longint): Pointer; override; public constructor Create(const ABytes: TBytes); overload; property Bytes: TBytes read FBytes; end;
resourcestring sMyNewErrorMessage = 'MemoryStream Error!';
const TextFormatFlag: array[Ansi..Utf8] of word=($0000,$FFFE,$FEFF,$EFBB); MemoryDelta = $2000; { Must be a power of 2 }
function UnicodeSave(const FileName:string;WS:widestring):boolean; function UnicodeRead(const FileName:string):WideString;
function UnicodeBigSave(const FileName:string;WS:widestring):boolean; function UnicodeBigRead(const FileName:string):WideString;
function UTF8Save(const FileName:string;WS:widestring):boolean; function UTF8Read(const FileName:string):WideString;
function AnsiSave(const FileName:string;WS:widestring):boolean; function AnsiRead(const FileName:string):WideString;
function GetTextType(const FileName: string): String; //返回文本格式信息
function TextRead(const FileName:string):FReadText; //读取各种格式 function TextSave(const FileName:string;WS:widestring):boolean; //保存原格式
function UnicodeEncode(Str:string;CodePage:integer):WideString; //unicode编码 function UnicodeDecode(Str:WideString;CodePage:integer):string; //unicode解码
function WStrToStr(const ws: WideString; codePage: Word): AnsiString; //宽字符串转单字符串,等同于UnicodeEncode function StrToWStr(const s: AnsiString; codePage: Word): WideString; //单字符串转宽字符串,等同于UnicodeDecode // function WideStringToUCS4String(const ws : WideString) : UCS4String;
function HexToInt(s: string): Integer; //IntToHex函数,D7自带;实际应该写为HexStrToInt function IntToBinStr(i: integer): string; //integer范围signed 32-bit function ByteToHexStr(AByte : Byte ) : string; //单字节处理 function HexStrToByte(HexS: String ) : Byte; //2位16进制字符串转为1个字节 function HexStrToDec(HexStr: AnsiString):AnsiString; //按每2位Hex字符转换为3位十进制数字字符串
//以下是连续字符和字节的处理 function BytesOf(const Val: AnsiString): TBytes; //Ansistring字符串的字节数组形式 function HexStrToBytes(const HexStr: AnsiString): TBytes; //连续的16进制数的字节数组形式 function BytesToHexStr(ABytes: TBytes; len: Integer): AnsiString; //字节数组的 Ansistring字符串形式
//机内码 转 Ansi(GB2312)字符,中文系统下:16进制/无空格分隔 ; 分隔字符串当然不能是0..9,A..F,a..f function CoderToAnsiStr(HexS: String;const Delimited:string=''):String; function CoderToUTF8Str(HexS: String;const Delimited:string=''):String; //机内码 转 Utf-8 function CoderToUnicodeStr(HexS: String;const Delimited:string=''):String; //机内码 转 unicode字符:默认16进制/无空格分隔 function CoderToUnicodeBigEndianStr(HexS: String;const Delimited:string=''):String; //机内码 转 unicodeBigEndian function CoderToUtf32Str(HexS: String;const Delimited:string=''):String; //机内码 转 Utf-32 function CoderToUtf32BigEndianStr(HexS: String;const Delimited:string=''):String; //机内码 转 Utf-32 BigEndian
function UTF8StrToCoder(S:String; const Delimited:string=''):string; //Utf-8 转 机内码 function AnsiStrToCoder(S: String;const Delimited:string=''):String; //Ansi(包括GB2312,准确是当前的字符集)字符转机内码 function UniCodeStrToCoder(S:String;const Delimited:string=''):String; //unicode字符转机内码 function UniCodeBigEndianStrToCoder(S:String; const Delimited:string=''):string; //unicodeBigEndian字符转机内码 function UTF32StrToCoder(S:String; const Delimited:string=''):string; // Utf-32 转 机内码 function UTF32BigEndianStrToCoder(S:String; const Delimited:string=''):string; //Utf-32 BigEndian 转 机内码
function BinFileToHexStr(BinFileName:string):string; //按2进制文件读取文件为HexStr字符串(包括Bin文件) function HexStrToBinFile(HexStr:string;BinFileName:string):Boolean;
function StreamToBytes(aStream:TStream):TBytes; //流to字节串(字节数组),本质上是一个东西的 function BytesToStream(aBytes:TBytes):TStream; //使用Stream前,需要Stream.Position := 0; 否则,读取不到内容
{**注意TStream 是抽象类, 只能通过其子类实例化; 若使用TStream是得不到内容的,它为基类,必须用其他流来代替} function StreamToHexStr(aStream:TStringStream):string; overload; //重载,TStringStream类的实现 function StreamToHexStr(aStream:TMemoryStream):string; overload; //重载,TMemoryStream类的实现 function StreamToHexStr(aStream:TBytesStream):string; overload; //重载,TBytesStream类的实现
implementation
{ TBytesStream } ///---------参照delphi2010写的字节流类型,比较好用------------/// constructor TBytesStream.Create(const ABytes: TBytes); begin inherited Create; FBytes := ABytes; SetPointer(Pointer(FBytes), Length(FBytes)); FCapacity := FSize; end;
function TBytesStream.Realloc(var NewCapacity: Integer): Pointer; begin if (NewCapacity > 0) and (NewCapacity <> FSize) then NewCapacity := (NewCapacity + (MemoryDelta - 1)) and not (MemoryDelta - 1); Result := Pointer(FBytes); if NewCapacity <> FCapacity then begin SetLength(FBytes, NewCapacity); Result := Pointer(FBytes); if NewCapacity = 0 then Exit; if Result = nil then raise EStreamError.CreateRes(@sMyNewErrorMessage); end; end;
//Unicode存 function UnicodeSave(const FileName:string;WS:widestring):boolean; var S: string; begin Result :=False; if WS = '' then Exit; with TMemoryStream.Create do try S := #$FF#$FE; Write(S[1], Length(S)); Write(WS[1], Length(WS) * SizeOf(WideChar)); Position := 0; SaveToFile(FileName); Result :=True; finally Free; end; end;
//Unicode读取 function UnicodeRead(const FileName:string):WideString; function WideStringToString(const WS: WideString; CodePage: Word): string; var InputLength,OutputLength:Integer; begin InputLength := Length(WS); OutputLength := WideCharToMultiByte(CodePage, 0, PWideChar(WS), InputLength, nil, 0, nil, nil); SetLength(Result, OutputLength); WideCharToMultiByte(CodePage, 0, PWideChar(WS), InputLength, PAnsiChar(Result), OutputLength, nil, nil); end;
var S: string; WS:WideString ; begin Result :=''; if not FileExists(FileName) then Exit; with TMemoryStream.Create do try LoadFromFile(FileName); if Size < 4 then Exit; SetLength(S, 2); Read(S[1], Length(S)); // if Copy(S, 1, 2) <> #$FF#$FE then Exit; //不加此句可以尝试读取非Unicode的格式文件 { if Copy(S, 1, 2) <> #$FF#$FE then SetLength(WS, Size div SizeOf(WideChar)) else } SetLength(WS, (Size - 2) div SizeOf(WideChar)); Read(WS[1], Length(WS) * SizeOf(WideChar)); //Result :=WideStringToString(WS,1252); Result :=WS; finally Free; end; end;
//Unicode big endian存 function UnicodeBigSave(const FileName:string;WS:widestring):boolean; var S: string; i:integer; begin Result :=False; if WS = '' then Exit; with TMemoryStream.Create do try S := #$FE#$FF; Write(S[1], Length(S));
for i := 1 to Length(ws) do ws[i] := WideChar(Swap(Word(ws[i]))); //交换高低字节
Write(WS[1], Length(WS) * SizeOf(WideChar)); Position := 0; SaveToFile(FileName); Result :=True; finally Free; end; end;
//Unicode big endian读取 function UnicodeBigRead(const FileName:string):WideString; var S: string; WS:WideString ; i:integer; begin Result :=''; if not FileExists(FileName) then Exit; with TMemoryStream.Create do try LoadFromFile(FileName); if Size < 4 then Exit; SetLength(S, 2); Read(S[1], Length(S)); // if Copy(S, 1, 2) <> #$FE#$FF then Exit; //不加此句可以尝试读取非Unicode big endian的格式文件 SetLength(WS, (Size - 2) div SizeOf(WideChar)); Read(WS[1], Length(WS) * SizeOf(WideChar));
for i := 1 to Length(ws) do ws[i] := WideChar(Swap(Word(ws[i]))); //交换高低字节
Result :=WS; finally Free; end; end;
//UTF-8存 function UTF8Save(const FileName:string;WS:widestring):boolean; var S: string; begin Result :=False; if WS = '' then Exit; with TMemoryStream.Create do try S := #$EF#$BB#$BF; Write(S[1], Length(S)); S := AnsiToUtf8(WS); Write(S[1], Length(S)); Position := 0; SaveToFile(FileName); Result :=True; finally Free; end; end;
//UTF-8读取 function UTF8Read(const FileName:string):WideString; var S: string; begin Result :=''; if not FileExists(FileName) then Exit;
with TMemoryStream.Create do try LoadFromFile(FileName); SetLength(S, Size); Read(S[1], Length(S)); // if Copy(S, 1, 3) <> #$EF#$BB#$BF then Exit; //不加此句可以尝试读取非UTF-8的格式文件 Result := Utf8ToAnsi(Copy(S, 4, MaxInt)); finally Free; end; end;
//Ansi读取可以直接用 { Memo1.Lines.LoadFromFile(Edit1.Text); //读取 Memo1.Lines.savetoFile(Edit1.Text); //保存 } //Ansi读取 function AnsiRead(const FileName:string):WideString; var S: string; begin Result :=''; if not FileExists(FileName) then Exit;
with TMemoryStream.Create do try LoadFromFile(FileName); SetLength(S, Size); Read(S[1], Length(S)); Result := S; finally Free; end; end;
//Ansi存 function AnsiSave(const FileName:string;WS:widestring):boolean; var S: string; begin Result :=False; if WS = '' then Exit; S:=WS; with TMemoryStream.Create do try Write(S[1], Length(S)); Position := 0; SaveToFile(FileName); Result :=True; finally Free; end; end;
function WordLoHiExchange(w:Word):Word; register; asm XCHG AL, AH end; { TextFormat返回文本编码类型,sText未经处理的文本 }
function GetTextType(const FileName: string): String; var w: Word; begin with TFileStream.Create(FileName, fmOpenRead or fmShareDenyNone) do try Read(w,2); w:=WordLoHiExchange(w);//因为是以Word数据类型读取,故高低字节互换 if w = TextFormatFlag[Unicode] then Result := 'Unicode' else if w = TextFormatFlag[UnicodeBigEndian] then Result:= 'UnicodeBigEndian' else if w = TextFormatFlag[Utf8] then //本来需要判断第3个字节的,但通常可省略 Result := 'Utf8' else Result := 'Ansi'; //实际是无文件头,而不是$0000判断的哦 finally Free; end; end;
function TextRead(const FileName:string):FReadText; //自动判断文件BOM,自动载入文件的编码类型 var S: string; w: Word; WS:WideString ; i:integer; begin SetLength (Result,2); //第1个存返回的字符串,第2个为文件类型
Result[0] :=''; if not FileExists(FileName) then Exit; with TMemoryStream.Create do try LoadFromFile(FileName); if Size < 4 then Exit;
Read(w,2); w:=WordLoHiExchange(w);//因为是以Word数据类型读取,故高低字节互换 if w = TextFormatFlag[Unicode] then Result[1] := 'Unicode' else if w = TextFormatFlag[UnicodeBigEndian] then Result[1] := 'UnicodeBigEndian' else if w = TextFormatFlag[Utf8] then //本来需要判断第3个字节的,但通常可省略 Result[1] := 'Utf8' else Result[1] := 'ANSI'; //实际是无文件头,而不是$0000判断的哦
//^^^^^需要将游标重置到文件头位置 if (Result[1]='Unicode') or (Result[1]='UnicodeBigEndian') then begin Seek(2,soFromBeginning); SetLength(WS, (Size-2 ) div SizeOf(WideChar));
Read(WS[1], Length(WS) * SizeOf(WideChar));
if (Result[1] = 'UnicodeBigEndian') then //unicode big endian for i := 1 to Length(ws) do ws[i] := WideChar(Swap(Word(ws[i]))); //交换高低字节 end else if Result[1]='Utf8' then begin Seek(0,soFromBeginning); SetLength(S, Size); Read(S[1], Length(S)); // Result[0] := Utf8ToAnsi(Copy(WS, 4, MaxInt)); WS :=Utf8ToAnsi(Copy(S, 4, MaxInt)); end else //按Ansi处理 begin Seek(0,soFromBeginning); SetLength(S, Size); Read(S[1], Length(S)); WS :=S; //Result[0] :=WS; end;
Result[0] :=WS; finally Free; end; end;
function TextSave(const FileName:string;WS:widestring):boolean; var txtType: string; //w: Word; begin txtType :=GetTextType(FileName); try if txtType='Unicode' then UnicodeSave(FileName,WS) else if txtType='UnicodeBigEndian' then UnicodeBigSave(FileName,WS) else if txtType='Utf8' then UTF8Save(FileName,WS) else //Ansi AnsiSave(FileName,WS); Result :=True; except Result :=False; end; end;
function UnicodeEncode(Str:string;CodePage:integer):WideString; var Len:integer; begin Len:=Length(Str)+1; SetLength(Result,Len); Len:=MultiByteToWideChar(CodePage,0,PAnsiChar(Str),-1,PWideChar(Result),Len); SetLength(Result,Len-1); //end is #0 end;
function UnicodeDecode(Str:WideString;CodePage:integer):string; var Len:integer; begin Len:=Length(Str)*2+1; //one for #0 SetLength(Result,Len); Len:=WideCharToMultiByte(CodePage,0,PWideChar(Str),-1,PAnsiChar(Result),Len,nil,nil); SetLength(Result,Len-1); end;
function WStrToStr(const ws: WideString; codePage: Word): AnsiString; var l: integer; begin if ws ='' then Result :='' else begin l := WideCharToMultiByte(codePage, WC_COMPOSITECHECK or WC_DISCARDNS or WC_SEPCHARS or WC_DEFAULTCHAR, @ws[1], - 1, nil, 0, nil, nil); SetLength(Result, l - 1); if l > 1 then WideCharToMultiByte(codePage, WC_COMPOSITECHECK or WC_DISCARDNS or WC_SEPCHARS or WC_DEFAULTCHAR, @ws[1], - 1, @Result[1], l - 1, nil, nil); end; end; { WideStringToString }
function StrToWStr(const s: AnsiString; codePage: Word): WideString; var l: integer; begin if s ='' then Result :='' else begin l := MultiByteToWideChar(codePage, MB_PRECOMPOSED, PAnsiChar(@s[1]), - 1, nil, 0); SetLength(Result, l - 1); if l > 1 then MultiByteToWideChar(CodePage, MB_PRECOMPOSED, PAnsiChar(@s[1]), - 1, PWideChar(@Result[1]), l - 1); end; end; { StringToWideString }
---------进制转换------------/// ///参考的文章:http://www.2ccc.com/article.asp?articleid=3133 //十六进制(S)-->>十进制(I) [重写:Jey] function HexToInt(s: string): Integer; begin //$代表16进制 ,integer范围signed 32-bit Result:=StrToInt('$'+s); end;
//十进制转换为二进制字符串 [重写:Jey] function IntToBinStr(i: integer): string; begin //integer范围signed 32-bit while i <>0 do begin //i mod 2取模,再使用format格式化 result:=Format('%d'+result,[i mod 2]); i:=i div 2; end end;
function ByteToHexStr(AByte : Byte ) : string; begin Result:=Format('%.2x', [AByte]); end;
function HexStrToByte(HexS: String ) : Byte; var i:integer; begin i:=StrToInt('$'+HexS); if i<256 then Result:=Byte(i) else Result:=Byte(0); end;
---------进制转换------------///
---------编码转换------------///
//Ansi的机内码转nsi字符,默认:中文系统下/16进制无空格分隔 function AnsiStrToCoder(S:string; const Delimited:string=''):string; var i:integer; begin Result :=''; for i:=1 to length(S) do //用ord函数可以取得字符的ASCII码的值 try if odd(i) then //result:=result+IntToHex(ord(s[i]),2) //可用 result:=result+Format('%.2x', [ord(S[i])]) else // result:=result+IntToHex(ord(s[i]),2)+Delimited; //可用 result:=result+Format('%.2x', [ord(S[i])])+Delimited; except end; end;
//Unicode的机内码转Ansi字符:默认16进制无空格分隔 function UniCodeStrToCoder(S:String; const Delimited:string=''):string; var i:integer; WS:WideString; begin Result :=''; WS :=WideString(S); //必须转换为widechar以获得Unicode编码 for i:=1 to length(WS) do //用ord函数可以取得字符的ASCII码的值 //result:=result+IntToHex(ord(S[i]),4)+Delimited; //unicode,可用 try result:=result+IntToHex(ord(Swap(word(WS[i])) ),4)+Delimited; //swap交换高低字节 ,这个出来的是unicode little endian except end; end;
function UniCodeBigEndianStrToCoder(S:String; const Delimited:string=''):string; var i:integer; WS:WideString; begin Result :=''; WS :=WideString(S); //必须转换为widechar以获得Unicode编码 for i:=1 to length(WS) do //用ord函数可以取得字符的ASCII码的值 //result:=result+IntToHex(ord(S[i]),4)+Delimited; //unicode,可用 try result:=result+Format('%.4x', [ord(WS[i])])+Delimited; except end; end;
//UTF-8的机内码转Ansi字符:默认16进制无空格分隔 function UTF8StrToCoder(S:String; const Delimited:string=''):string; var i:integer; UTF8Str:UTF8String; begin Result :=''; UTF8Str :=AnsiToUtf8(S); //必须转换为TF8String以获得UTf-8编码 for i:=1 to length(UTF8Str) do //用ord函数可以取得字符的ASCII码的值 try result:=result+Format('%.2x', [ord(UTF8Str[i])])+Delimited; //或者result:=result+ByteToHex(Byte(UTF8Str[i]))+Delimited; except end; end;
function UTF32StrToCoder(S:String; const Delimited:string=''):string; var U4:UCS4String; i: Cardinal; begin Result :=''; U4 :=WideStringToUCS4String(VarToWideStr(s)); for i:=0 to Length(U4)-2 do //最后1位为字符串结束标志0 if U4[i]>$FFFF then Result:=Result+ IntToHex(Swap(word(U4[i]-$FFFF)),8)+Delimited else Result:=Result+ IntToHex(Swap(word(U4[i])) shl 16,8)+Delimited; end;
function UTF32BigEndianStrToCoder(S:String; const Delimited:string=''):string; var U4:UCS4String; i: Cardinal; begin Result :=''; U4 :=WideStringToUCS4String(VarToWideStr(s)); for i:=0 to Length(U4)-2 do //最后1位为字符串结束标志0 Result:=Result+ IntToHex(U4[i],8)+Delimited; end;
function BytesOf(const Val: AnsiString): TBytes; var Len: Integer; begin Len := Length(Val); SetLength(Result, Len); Move(Val[1], Result[0], Len); end;
function HexStrToDec(HexStr: AnsiString):AnsiString; //按每2位Hex字符转换为3位十进制数字字符串 var Len:Integer; Abyte:Byte; begin Result :=''; Len :=Length(HexStr); if Odd(Len) then Dec(Len); while Len>0 do begin //Result :=IntToStr(StrtoInt('$'+HexStr[Len-1]+ HexStr[Len]))+' '+Result ; Abyte := StrtoInt('$'+HexStr[Len-1]+ HexStr[Len]); Result :=Format('%.3d ',[Abyte])+Result ; Dec(Len,2); end;
end;
function BytesToHexStr(ABytes: TBytes; len: Integer): AnsiString; begin SetLength(Result, len*2); BinToHex(@ABytes[0], PAnsiChar(Result), len); end;
function HexStrToBytes(const HexStr: AnsiString): TBytes; var Len,i,j: Integer; begin Len := Length(HexStr); if Odd(Len) then Dec(Len); Len := Len div 2; SetLength(Result, Len); j:=1; for i:=0 to len-1 do begin Result[i] := StrToInt('$'+Hexstr[j]+ Hexstr[j+1]); Inc(j,2); end; // Move(HexStr[1], Result[0], Len); end;
//机内码 转 Ansi(GB2312)字符,中文是>=$80的2个字节的值(每个字节高位都是1),英文和数字<$80 function CoderToAnsiStr(HexS: String;const Delimited:string=''):String; Var bs: TBytes; begin if Pos(' ',HexS)>0 then HexS :=StringReplace(HexS,' ','',[rfReplaceAll]); //去空格 if Delimited<>'' then HexS :=StringReplace(HexS,Delimited,'',[rfReplaceAll]); //去分隔字符串
bs :=HexStrToBytes(HexS); Result :=PChar(bs); SetLength(Result,Length(bs)); //不设置长度,有时会多一个符号 * end;
{function CoderToAnsiStr2(HexS: String;const Delimited:string=''):String; //这方法是纯中文的转换 Var I,coder: Integer; begin HexS :=StringReplace(HexS,' ','',[rfReplaceAll]); //去空格 if Delimited<>'' then HexS :=StringReplace(HexS,Delimited,'',[rfReplaceAll]);
I := Length(HexS); while I >=4 do begin try coder:=StrToInt('$'+HexS[I-3]+HexS[I-2]+HexS[I-1]+HexS[I]); Result := Chr(coder shr 8) +Chr(coder mod 256)+Result; except end; I := I - 4; end; end; }
//机内码 转 unicode字符 function CoderToUnicodeStr(HexS: String;const Delimited:string=''):String; Var bs: TBytes; begin Result :=''; if Pos(' ',HexS)>0 then HexS :=StringReplace(HexS,' ','',[rfReplaceAll]); //去空格 if Delimited<>'' then HexS :=StringReplace(HexS,Delimited,'',[rfReplaceAll]); //去分隔字符串
bs :=HexStrToBytes(HexS); Result :=PWideChar(bs); //或者Result :=PUCS2Char(bs); SetLength(Result,Length(bs)); //不设置长度,有时会多一个符号 * end;
//机内码 转 unicode big endian字符 function CoderToUnicodeBigEndianStr(HexS: String;const Delimited:string=''):String; Var bs: TBytes; ws:WideString; i:Cardinal; begin Result :=''; if Pos(' ',HexS)>0 then HexS :=StringReplace(HexS,' ','',[rfReplaceAll]); //去空格 if Delimited<>'' then HexS :=StringReplace(HexS,Delimited,'',[rfReplaceAll]); //去分隔字符串
bs :=HexStrToBytes(HexS); ws :=PWideChar(bs); for i:=1 to length(WS) do Result :=Result +widechar(Swap(word(WS[i])));
SetLength(Result,Length(bs)); //不设置长度,有时会多一个符号 * end;
//机内码 转 unicode字符 function CoderToUtf32Str(HexS: String;const Delimited:string=''):String; Var bs: TBytes; U4:UCS4String; ws:WideString; Len:Integer ; begin Result :=''; if Pos(' ',HexS)>0 then HexS :=StringReplace(HexS,' ','',[rfReplaceAll]); //去空格 if Delimited<>'' then HexS :=StringReplace(HexS,Delimited,'',[rfReplaceAll]); //去分隔字符串
Len := Length(HexS)-(Length(HexS) mod 8); HexS :=Copy(HexS,1,Len); //忽略不足4个字节的内容
bs :=HexStrToBytes(HexS);
// Result :=PUCS4Char(bs); //编译不通过
PUCS4Char(U4) :=@bs[0]; //UCS4String数组的指针 指向 bytes数组的第1个单元
//注意:SetLength(var S; NewLength: Integer); // 第2个参数是第1个参数类型的n倍,即第1个为宽字符,第2个为2,则:4*sizeof(宽字符)=8字节 SetLength(U4,(Length(bs) div 4)+1); //加1的原因:参看UCS4StringToWideString函数
ws:=UCS4StringToWideString(u4);
Result :=ws;
//以下释放内存,否则多次执行会报CPU错误,具体不清楚,应该是内存泄露(以下任何一单句都会报错,所以需要一起释放) SetLength(bs,0); SetLength(HexS,0); SetLength(U4,0); SetLength(ws,0); end;
//机内码 转 unicode big endian字符 function CoderToUtf32BigEndianStr(HexS: String;const Delimited:string=''):String; Var bs: TBytes; ws:WideString; i:Cardinal; begin Result :=''; if Pos(' ',HexS)>0 then HexS :=StringReplace(HexS,' ','',[rfReplaceAll]); //去空格 if Delimited<>'' then HexS :=StringReplace(HexS,Delimited,'',[rfReplaceAll]); //去分隔字符串
bs :=HexStrToBytes(HexS); ws :=PWideChar(bs); for i:=1 to length(WS) do Result :=Result +widechar(Swap(word(WS[i])));
SetLength(Result,Length(bs)); //不设置长度,有时会多一个符号 * end;
{function CoderToUnicodeStr2(HexS: String;const Delimited:string=''):String; //此方法可以用,但觉得方法1通用一些的; Var I: Integer; begin if Delimited<>'' then HexS :=StringReplace(HexS,Delimited,'',[rfReplaceAll]);
I := Length(HexS); I :=I - (I mod 4); //只取前面能被4整除的Hex机内码,比如BBCD12->BBCD,截断不正确的机内码 while I >=4 do begin try Result :=WideChar(StrToInt('$'+HexS[I-3]+HexS[I-2]+HexS[I-1]+HexS[I]))+ Result; except end; I := I - 4; end; end; }
//机内码 转 UTF8字符 function CoderToUTF8Str(HexS: String;const Delimited:string=''):String; function Utf8Decode2( S: UTF8String; BytesCount:Cardinal): WideString; //重写Utf8Decode,以便utf8机内码不完整时能忽略最后不完整字串 var L: Integer; Temp: WideString; begin Result := ''; Temp :='';
if S = '' then Exit;
// showmessage('字节数:'+inttostr(BytesCount)); //显示字节数
repeat SetLength(Temp, BytesCount);
L := Utf8ToUnicode(PWideChar(Temp), Length(Temp)+1, PChar(S), BytesCount); if L > 0 then SetLength(Temp, L-1) else S := Copy(S,1,Length(s)-1); until (L>0) or (Length(S)<1); Result := Temp; end;
Var bs: TBytes; begin if Pos(' ',HexS)>0 then HexS :=StringReplace(HexS,' ','',[rfReplaceAll]); //去空格 if Delimited<>'' then HexS :=StringReplace(HexS,Delimited,'',[rfReplaceAll]); //去分隔字符串
bs :=HexStrToBytes(HexS);
Result :=Utf8Decode2(PChar(bs),length(bs)); end;
---------编码转换------------///
/--------BinToHexStr Begin-------- // function BinFileToHexStr(BinFileName:string):string; var BinaryStream: TMemoryStream; begin BinaryStream := TMemoryStream.Create; BinaryStream.LoadFromFile(BinFileName); try if BinaryStream.Size > 0 then begin //Result := StrAlloc(BinaryStream.Size*2); //BinToHex(BinaryStream.Memory,Result,BinaryStream.Size); SetLength(Result, BinaryStream.Size * 2); //很重要,需要设置长度才可以的,因为要用成pchar BinToHex(BinaryStream.Memory,PChar(Result),BinaryStream.Size); end; finally BinaryStream.Free; end; end;
function HexStrToBinFile(HexStr:string;BinFileName:string):Boolean; var BinaryStream: TMemoryStream; begin Result :=False; BinaryStream := TMemoryStream.Create; try BinaryStream.Size := Length(HexStr) div 2; if BinaryStream.Size > 0 then begin HexToBin(PAnsiChar(HexStr), BinaryStream.Memory, BinaryStream.Size); BinaryStream.SaveToFile(BinFileName); Result :=True; end; finally BinaryStream.Free; end; end;
/--------BinToHexStr End-------- //
/--------流转换Begin------- // function StreamToBytes(aStream:TStream):TBytes; begin // aStream := TMemoryStream.Create; //此处,不需要初始化流 try SetLength(Result, aStream.Size); aStream.Position := 0; aStream.Read(Result[0], aStream.Size); finally aStream.Free; end; end;
//使用Stream前,需要Stream.Position := 0; 否则,读取不到内容 function BytesToStream(aBytes:TBytes):TStream; var aStream: TStream; begin aStream := TMemoryStream.Create; try aStream.Write(aBytes[0],length(aBytes)); aStream.Position := 0; result :=aStream; finally //aStream.Free; //此处,不可释放 end; end;
function StreamToHexStr(aStream:TStringStream):string; var Len: Integer; begin aStream.Position :=0; Len :=aStream.size; Result :=''; SetLength(Result, len*2); BinToHex(PAnsiChar(aStream.DataString), PAnsiChar(Result), len); //BinToHex(PAnsiChar(aStream), PAnsiChar(Result), len); //用stream不成功 // BinToHex(@aStream, PAnsiChar(Result), len); //用stream不成功 end;
function StreamToHexStr(aStream:TMemoryStream):string; var Len: Integer; begin aStream.Position :=0; Len :=aStream.size; Result :=''; SetLength(Result, len*2);
BinToHex(aStream.Memory, PAnsiChar(Result), len); end;
function StreamToHexStr(aStream:TBytesStream):string; var Len: Integer; begin aStream.Position :=0; Len :=aStream.size; Result :=''; SetLength(Result, len*2);
BinToHex(aStream.Memory, PAnsiChar(Result), len); end; /--------流转换End------- //
end.