Delphi中Ini.ReadString无法识别带引号字符串,如何读取时修正?
解决Delphi INI读取时无法识别值带引号的问题
Delphi内置的TIniFile.ReadString()或TMemIniFile.ReadString()会自动去除值首尾的单/双引号,导致无法区分Database=MyName和Database='MyName'两种配置的差异。要解决这个问题,需要绕过内置方法的引号处理逻辑,直接读取原始配置值。
方案1:自定义INI读取函数(直接解析文件)
如果不需要依赖Delphi的INI类,可以自己实现一个简单的读取函数,直接解析INI文件的原始内容,保留值的原始格式:
function ReadIniRawString(const FileName, Section, Key, Default: string): string; var SL: TStringList; I, SectionIdx: Integer; Line: string; KeyPrefix: string; begin Result := Default; SL := TStringList.Create; try SL.LoadFromFile(FileName); // 定位目标Section SectionIdx := -1; for I := 0 to SL.Count - 1 do begin Line := Trim(SL[I]); // 跳过注释和空行 if (Line = '') or (Line[1] = ';') then Continue; // 匹配Section if (Line[1] = '[') and (Line[Length(Line)] = ']') then begin if CompareText(Copy(Line, 2, Length(Line)-2), Section) = 0 then begin SectionIdx := I + 1; Break; end; end; end; if SectionIdx = -1 then Exit; // 在Section内查找目标Key KeyPrefix := Key + '='; for I := SectionIdx to SL.Count - 1 do begin Line := SL[I]; // 遇到新Section则停止 if (Trim(Line) <> '') and (Trim(Line)[1] = '[') then Break; // 跳过注释行 if (Line <> '') and (Line[1] = ';') then Continue; // 匹配Key if Pos(KeyPrefix, TrimLeft(Line)) = 1 then begin // 提取等号后的原始内容(保留空格、引号) Result := Copy(Line, Pos('=', Line) + 1, MaxInt); Exit; end; end; finally SL.Free; end; end;
使用示例:
var aDatabase: string; begin // 读取Ini文件#1,返回MyName aDatabase := ReadIniRawString('config1.ini', 'SectionDatabase', 'Database', 'error'); // 读取Ini文件#2,返回'MyName' aDatabase := ReadIniRawString('config2.ini', 'SectionDatabase', 'Database', 'error'); end;
方案2:扩展TMemIniFile类(内存级解析)
如果已经在使用TMemIniFile,可以扩展该类,添加一个不处理引号的读取方法:
type TMyMemIniFile = class(TMemIniFile) public function ReadRawString(const Section, Ident, Default: string): string; end; function TMyMemIniFile.ReadRawString(const Section, Ident, Default: string): string; var SL: TStringList; I: Integer; Line: string; KeyPrefix: string; begin Result := Default; // 获取目标Section的字符串列表 SL := Sections.Values[Section]; if not Assigned(SL) then Exit; KeyPrefix := Ident + '='; for I := 0 to SL.Count - 1 do begin Line := SL[I]; // 匹配Key(忽略开头空格) if Pos(KeyPrefix, TrimLeft(Line)) = 1 then begin // 提取原始值,保留引号 Result := Copy(Line, Pos('=', Line) + 1, MaxInt); Exit; end; end; end;
使用示例:
var Ini: TMyMemIniFile; aDatabase: string; begin Ini := TMyMemIniFile.Create('config.ini'); try // 读取原始值,保留引号 aDatabase := Ini.ReadRawString('SectionDatabase', 'Database', 'error'); finally Ini.Free; end; end;
注意事项
- 自定义解析逻辑需要考虑INI文件的常见格式细节:注释行(
;开头)、空行、Key的大小写不敏感性(示例中用CompareText实现)。 - 如果INI值包含多行内容(通过续行符
\),需要额外处理续行逻辑,示例代码仅针对单行值场景。
内容的提问来源于stack exchange,提问作者Franz
相关产品推荐
相关产品推荐

