如何使用TStringList将字符串插入JSON文件的指定位置?

问题描述 投票:-1回答:1

是否可以使用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;
json delphi
1个回答
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;
© www.soinside.com 2019 - 2024. All rights reserved.