我希望使用SysUtils.FileWrite
api将我的电脑的名称写入txt文件,在我的最后一次尝试是用成功写的,但麻烦的是视觉上是剪切一些字符,但是文字的大小内部文件的大小与字符串在视觉上完整相同。
例如:我的电脑被称为" TESTE-PC" (没有双引号)。字符串" TESTE-PC" (没有双引号)恰好有8位,但SysUtils.FileWrite
仅写入" TEST"文件大小为8位。很奇怪! :(
感谢您的任何建议。
uses
Registry;
...
function GetCompName: string;
var
Reg: TRegistry;
begin
Reg := TRegistry.Create;
try
Reg.rootKey := HKEY_LOCAL_MACHINE;
if Reg.OpenKey('SYSTEM\CurrentControlSet\Control\ComputerName\ActiveComputerName', false) then
begin
Result := Reg.ReadString('ComputerName');
Reg.CloseKey;
end;
finally
Reg.Free;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
var
hFile: THandle;
Str: PWideChar;
begin
if not fileexists('test.txt') then
begin
Str := PWideChar(GetCompName);
hFile:= CreateFile('test.txt', GENERIC_WRITE, 0, nil, OPEN_ALWAYS, FILE_FLAG_WRITE_THROUGH, 0);
FileWrite(hFile, Str^, Length(Str));
CloseHandle(hFile);
end;
end;
答案 0 :(得分:4)
首先,使用Registry获取计算机名称是错误的。请改用GetComputerName()
功能:
uses
Windows;
...
function GetCompName: string;
var
CompName: array[0..MAX_COMPUTERNAME_LENGTH] of Char;
Size: DWORD;
begin
Size := Length(CompName);
if GetComputerName(CompName, Size) then
SetString(Result, CompName, Size-1)
else
Result := '';
end;
其次,您的FileWrite()
代码失败,因为您没有正确处理字符编码。 FileWrite()
仅对原始字节进行操作,但您使用的是Unicode字符串,而不考虑SizeOf(WideChar)
是2,而不是像代码所假设的那样1。
您还应该使用RTL&FileCreate()
功能FileWrite()
。如果直接使用Win32 CreateFile()
函数,您也应该直接使用Win32 API WriteFile()
。
无论你如何选择编写文件,都应该使用文件的绝对路径,而不是相对路径。
尝试更像这样的事情:
procedure TForm1.FormCreate(Sender: TObject);
var
FileName: string
hFile: THandle;
Str: string;
begin
FileName := 'C:\path to\test.txt';
if not FileExists(FileName) then
begin
Str := GetCompName;
hFile := FileCreate(FileName);
if hFile <> INVALID_HANDLE_VALUE then
begin
FileWrite(hFile, PChar(Str)^, Length(Str) * SizeOf(Char));
FileClose(hFile);
end;
end;
请注意,上面的代码将以UTF-16编码创建文件。如果您想使用UTF-8,它将如下所示:
procedure TForm1.FormCreate(Sender: TObject);
var
FileName: string;
hFile: THandle;
Str: UTF8String;
begin
FileName := 'C:\path to\test.txt';
if not FileExists(FileName) then
begin
Str := UTF8String(GetCompName);
hFile := FileCreate(FileName);
if hFile <> INVALID_HANDLE_VALUE then
begin
FileWrite(hFile, PAnsiChar(Str)^, Length(Str));
FileClose(hFile);
end;
end;
或任何其他编码,就此而言:
procedure TForm1.FormCreate(Sender: TObject);
var
FileName: string;
hFile: THandle;
Enc: TEncoding;
Str: TBytes;
begin
FileName := 'C:\path to\test.txt';
if not FileExists(FileName) then
begin
Enc := TEncoding.GetEncoding('desired encoding');
try
Str := Enc.GetBytes(GetCompName);
finally
Enc.Free;
end;
hFile := FileCreate(FileName);
if hFile <> INVALID_HANDLE_VALUE then
begin
FileWrite(hFile, PByte(Str)^, Length(Str));
FileClose(hFile);
end;
end;
无论您决定使用哪种编码,更简单的解决方案是使用IOUtils.TFile.WriteAllText()
方法:
uses
IOUtils;
procedure TForm1.FormCreate(Sender: TObject);
var
FileName: string;
begin
FileName := 'C:\path to\test.txt';
if not FileExists(FileName) then
begin
TFile.WriteAllText(FileName, GetCompName, TEncoding.UTF8); // or TEncoding.Unicode, etc...
end;
end;
答案 1 :(得分:0)
如果您需要编写宽字符,请考虑其大小:
FileWrite(hFile, Str^, Length(Str) * SizeOf(Char));
答案 2 :(得分:-1)
将str
的类型更改为RawByteString
而不是PWideChar
procedure TForm1.FormCreate(Sender: TObject);
var
hFile: THandle;
sFileName: string;
Str: RawByteString;
begin
Str := PWideChar(GetCompName);
sFileName := 'Test.txt';
if fileExists(sFileName) then
hFile := fileOpen(sFileName,fmOpenReadWrite)
else
hFile := fileCreate(sFileName);
try
FileWrite(hFile,
PChar(Str)^, Length(Str));
finally
FileClose(hFile);
end;
end;