【问题标题】:Extract string from a text file using 2 delimiters使用 2 个分隔符从文本文件中提取字符串
【发布时间】:2011-02-09 21:13:54
【问题描述】:

我正在尝试使用 2 个分隔符从文本文件中提取字符串。一开始一停止。

例子:

Hi my name is$John and I'm happy/today

我需要做的是调用一个函数,该函数将返回$/ 之间的字符串。我到处找,但似乎找不到有用的东西,而且我是编程新手。

【问题讨论】:

    标签: string delphi extract


    【解决方案1】:

    全部搞定

    function ExtractText(const Str: string; const Delim1, Delim2: string): TStringList;
    var
      c,pos1, pos2: integer;
    begin
      result:=TStringList.Create;
      c:=1;
      pos1:=1;
    
      while pos1>0 do
      begin
        pos1 := PosEx(Delim1, Str,c);
        if pos1 > 0 then begin
          pos2 := PosEx(Delim2, Str, pos1+1);
        if pos2 > 0 then
          result.Add(Copy(Str, pos1 + length(delim1), pos2 - (length(delim1) + pos1)));
          c:=pos1+1;
         end;
    
      end;
    end;
    

    【讨论】:

    • 处理多次出现的好主意,但在函数内创建对象并不是一个好的设计 - 调用代码必须在未创建对象的情况下释放对象。字符串列表应该由调用代码创建(和管理),并通过引用传递。
    • 我是编程新手。只是分享想法。也许,有人可以解决它。
    【解决方案2】:

    如果第二个文本也出现在第一个模式之前,则上述功能将不起作用...

    您应该使用PosEx() 而不是Pos()

    您可以使用 Pos 和 Copy 来做到这一点:

    function ExtractText(const Str: string; const Delim1, Delim2: string): string;
    var
      pos1, pos2: integer;
    begin
      result := '';
      pos1 := Pos(Delim1, Str);
      if pos1 > 0 then begin
        pos2 := PosEx(Delim2, Str, pos1+1);
        if pos2 > 0 then
          result := Copy(Str, pos1 + 1, pos2 - pos1 - 1);
      end;
    end;
    

    【讨论】:

      【解决方案3】:

      在较新的 Delphi 中,您可以这样做......(耶)

      program Project40; {$APPTYPE CONSOLE}
      
      uses RegularExpressions;
      
      const
        str = 'Is$John and I''m happy/today';
      
      function GetStr(const aStr: string): string;
      begin
        Result := TRegEx.Match(aStr, '\$.*/').Value;
        Result := Copy(Result, 2, Length(Result) - 2);
      end;
      
      begin
        Writeln(GetStr(str));
        ReadLn;
      end.
      

      【讨论】:

      • 不是正则表达式的最佳用途,但对于跳出框框思考 +1。
      【解决方案4】:

      您可以使用PosCopy 来做到这一点:

      function ExtractText(const Str: string; const Delim1, Delim2: char): string;
      var
        pos1, pos2: integer;
      begin
        result := '';
        pos1 := Pos(Delim1, Str);
        pos2 := Pos(Delim2, Str);
        if (pos1 > 0) and (pos2 > pos1) then
          result := Copy(Str, pos1 + 1, pos2 - pos1 - 1);
      end;
      

      【讨论】:

      • 使用PosExDelim1的位置之后开始搜索Delim2
      • 感谢我所需要的!
      • 安德烈亚斯:不仅仅是表演。如果在开始分隔符之前有一个结束分隔符,它也会产生结果,而您的代码没有。
      • @Marco:是的,确实如此。
      【解决方案5】:

      我会这样做:

      function ExtractDelimitedString(const s: string): string;
      var
        p1, p2: Integer;
      begin
        p1 := Pos('$', s);
        p2 := Pos('/', s);
        if (p1<>0) and (p2<>0) and (p2>p1) then begin
          Result := Copy(s, p1+1, p2-p1-1);
        end else begin
          Result := '';//delimiters not found, or in the wrong order; raise error perhaps
        end;
      end;
      

      【讨论】:

        【解决方案6】:

        Gab,您可以使用TFileStream 类以及CopyPos 函数编写一个函数来执行此操作。

        查看此示例:

        uses
          Classes,
          SysUtils;
        
        function ExtractString(Const FileName: TFileName;Const IDel,FDel : AnsiString) : AnsiString;
        Var
         FileStream : TFileStream;
         i,f        : Integer;
        begin
          FileStream:= TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite); //oopen the file
          try
            try
              SetLength(Result, FileStream.Size); //set the size of the string
              FileStream.Read(Pointer(Result)^, FileStream.Size);//read the content into a string
              i:=Pos(IDel,Result);//search the initial delimiter
              f:=Pos(FDel,Result);//search the final delimiter
              Result:=Copy(Result,i+1,f-i-1); //extract the value between the delimiters
            except
              Result := '';
              raise;
            end;
          finally
            FileStream.Free;
          end;
        end;
        

        并以这种方式使用

        ExtractString('your_file_name','$','/');
        

        【讨论】:

        • 您也可以使用 TMemoryStream 代替 SetLength+Read,然后 LoadFromFile() 然后 SetString(Result,PAnsiChar(MemoryStream.Memory),MemoryStream.Size);
        【解决方案7】:

        根据您的帖子,假设两个分隔符都是单个字符:

        function ExtractDelimitedValueFromFile(const aFilename: String;
                                               const aOpenDelim: Char;
                                               const aCloseDelim: Char;
                                               var aValue: String): Boolean;
        var
          i: Integer;
          strm: TStringStream;
          delimStart: Integer;
          delimEnd: Integer;
        begin
          result      := FALSE;
          aValue      := '';
          delimStart  := -1;
          delimEnd    := -1;
        
          strm := TStringStream.Create;
          try
            strm.LoadFromFile(aFileName);
        
            for i := 1 to strm.Size do
            begin
              if (delimStart = -1) and (strm.DataString[i] = aOpenDelim) then
                delimStart := i
              else if (delimStart <> -1) and (strm.DataString[i] = aCloseDelim) then
                delimEnd := i;
        
              result := (delimStart <> -1) and (delimEnd <> -1);
              if result then
              begin
                aValue := Copy(strm.DataString, delimStart + 1, delimEnd - delimStart - 1);
                BREAK;
              end;
            end;
        
          finally
            strm.Free;
          end;
        end;
        

        用法:

          var
            str: String;
          begin
            if ExtractDelimitedValueFromFile('path\filename.ext', '$', '/', str) then
              // work with str
            else
              // delimited value not found in file
          end;
        

        【讨论】:

          猜你喜欢
          • 2013-05-29
          • 1970-01-01
          • 2016-06-03
          • 1970-01-01
          • 1970-01-01
          • 2014-11-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多