是否可以使用TStringList
在json文件内的确定位置插入一个字符串?
我制作了一个能够成功搜索子字符串的代码,但前提是文件不包含“{}”。
例如:
文件内容:"hardware_acceleration_mode_previous":true,
但如果文件内容为:{"hardware_acceleration_mode_previous":true,}
TStringList.IndexOf
失败。
有一些解决方案吗?
我的实际代码是:
uses
Windows,
Classes,
SHFolder,
SysUtils;
function GetSpecialFolderPath(folder: integer): string;
const
SHGFP_TYPE_CURRENT = 0;
var
path: array [0 .. MAX_PATH] of char;
begin
if SUCCEEDED(SHGetFolderPath(0, folder, 0, SHGFP_TYPE_CURRENT, @path[0])) then
Result := IncludeTrailingBackslash(path)
else
Result := '';
end;
procedure Modify_Json_File;
var
SpecialFolder: Integer;
SL: TStringList;
InsTextPos: Integer;
FileChrome: String;
begin
SpecialFolder := CSIDL_LOCAL_APPDATA;
FileChrome := GetSpecialFolderPath(SpecialFolder);
FileChrome := FileChrome + 'Google\Chrome\User Data\Local State';
if FileExists(FileChrome) then
begin
SL := TStringList.Create;
try
SL.LoadFromFile(FileChrome);
InsTextPos := SL.IndexOf('"hardware_acceleration_mode_previous":true,');
if InsTextPos > 0 then
begin
SL.Insert(InsTextPos, '"hardware_acceleration_mode":{"enabled":false}');
SL.SaveToFile(FileChrome);
end;
finally
SL.Free;
end;
end;
end;
答案 0 :(得分:5)
不建议使用TStringList
以这种方式处理JSON。你真的应该使用一个真正的JSON解析器。 Embarcadero provides one in modern Delphi versions,也有很多第三方可用。
例如:
uses
Winapi.Windows,
System.Classes,
Winapi.SHFolder,
System.SysUtils,
System.IOUtils,
System.JSON;
function GetSpecialFolderPath(folder: integer): string;
const
SHGFP_TYPE_CURRENT = 0;
var
path: array [0 .. MAX_PATH] of char;
begin
if SUCCEEDED(SHGetFolderPath(0, folder, 0, SHGFP_TYPE_CURRENT, @path[0])) then
Result := IncludeTrailingBackslash(path)
else
Result := '';
end;
procedure Modify_Json_File;
var
FileChrome: String;
Obj: TJSONObject;
Pair: TJSONPair;
OldString: TJSONString;
OldValue: TJSONValue;
begin
FileChrome := GetSpecialFolderPath(CSIDL_LOCAL_APPDATA) + 'Google\Chrome\User Data\Local State';
if FileExists(FileChrome) then
begin
Obj := TJSONObject.ParseJsonValue(TFile.ReadAllText(FileChrome), True) as TJSONObject;
if Obj <> nil then
try
Pair := Obj.Get('hardware_acceleration_mode_previous');
if Pair <> nil then
begin
OldString := Pair.JsonString;
Pair.JsonString := TJSONString.Create('hardware_acceleration_mode');
OldString.Free;
OldValue := Pair.JsonValue;
Pair.JsonValue := TJSONObject.Create;
try
TJSONObject(Pair.JsonValue).AddPair('enabled', TJSONBool.Create(false));
finally
OldValue.Free;
end;
TFile.WriteAllText(FileChrome, Obj.ToJSON, TEncoding.UTF8);
end;
finally
Obj.Free;
end;
end;
end;
在任何情况下,如果您必须使用TStringList
,则至少不能使用IndexOf()
。它正在搜索确切的整行匹配,当您的代码失败时,您显然没有。所以,你需要逐行循环遍历JSON内容(假设它甚至有任何行--JSON不需要换行!),搜索每一个你感兴趣的子串,例如:
uses
Windows,
Classes,
SHFolder,
SysUtils;
function GetSpecialFolderPath(folder: integer): string;
const
SHGFP_TYPE_CURRENT = 0;
var
path: array [0 .. MAX_PATH] of char;
begin
if SUCCEEDED(SHGetFolderPath(0, folder, 0, SHGFP_TYPE_CURRENT, @path[0])) then
Result := IncludeTrailingBackslash(path)
else
Result := '';
end;
procedure Modify_Json_File;
const
SearchText = '"hardware_acceleration_mode_previous":true,';
ReplaceText = '"hardware_acceleration_mode":{"enabled":false},';
var
SL: TStringList;
I, InsTextPos: Integer;
FileChrome, S: String;
begin
FileChrome := GetSpecialFolderPath(CSIDL_LOCAL_APPDATA) + 'Google\Chrome\User Data\Local State';
if FileExists(FileChrome) then
begin
SL := TStringList.Create;
try
SL.LoadFromFile(FileChrome);
for I := 0 to SL.Count-1 do
begin
S := SL[I];
InsTextPos := Pos(SearchText, S);
if InsTextPos > 0 then
begin
Delete(S, InsTextPos, Length(SearchText));
Insert(ReplaceText, S, InsTextPos);
SL[I] := S;
SL.SaveToFile(FileChrome);
Exit;
end;
end;
finally
SL.Free;
end;
end;
end;