增加文件名的功能

时间:2015-01-29 16:44:01

标签: delphi delphi-2010

我试图创建一个可以增加文件名的函数。 如果字符串的最后一个字符是数字,则递增它。 如果最后一个字母是一个字母,那么添加_1或_2或_3(也增加它)。 我必须确保文件名是唯一的但我不能在文件名中使用datetime,因为所有文件名必须是< 32 chars而不是扩展名。

EX: Apple_99.txt =>Apple_100
Ex: Apple_173 => Apple_174
EX: This_is_my_first_text.txt => This_is_my_first_text_1.txt
Ex: This_is_my_first_text_9.txt => This_is_my_first_text_10.txt

我需要使用它来重命名文件,然后将其上传到ftp服务器。 我发现了一个可以执行此类操作的函数,但只有在文件名只包含大写的情况下才有效。如何修改此函数以便以大写字母的形式访问小写?

这是功能:

    function IncStr(Str: String; Amount: Integer; Index: Integer = -1): String;
    const
     MIN_VAL = 65; // 'A'
     MAX_VAL = 90; // 'Z'
    var
     Digit, ToAdd, ToCarry: Integer;
    begin

     if (Index = 0) and (Amount > 0) then
      begin
       Result := Char(MIN_VAL + Amount - 1) + Str;
       Exit;
      end;

     if Index = -1 then Index := Length(Str);

     ToCarry := 0;

     Digit := Ord(Str[Index]);

     while not (Digit in [MIN_VAL..MAX_VAL]) do
      begin
       Dec(Index);
       Digit := Ord(Str[Index]);
      end;

     ToAdd := Digit + Amount;

     while (ToAdd > MAX_VAL) do
      begin
       Dec(ToAdd, 26);
       Inc(ToCarry);
      end;

     Result := Str;
     Result[Index] := Char(ToAdd);

     if (ToCarry > 0) then
      Result := IncStr(Result, ToCarry, Index - 1);

    end;


    procedure TForm1.Button1Click(Sender: TObject);
    var
     S: String;   // holds string to increment
     C: Integer;  // amount to increment by
    begin
     // make sure that Edit1 starts with a valid character
     // i.e. 'A' to 'Z'
     S := Edit1.Text;
     C := StrtoIntDef(Edit2.Text, 0);
     // test it, place result in Edit3
     Edit3.Text := IncStr(S, C);
     {
       Example data:

         Edit1 := AAZ
         Edit2 := 2
       = Edit3 := ABB

         Edit1 := BZY
         Edit2 := 3
       = Edit3 := CAB

         Edit1 := ZZZ
         Edit2 := 1
       = Edit3 := AAAA

         Edit1 := AA-AC
         Edit2 := 3
       = Edit3 := AA-AF

         Edit1 := AA/Z
         Edit2 := 5
       = Edit3 := AB/E

       ... etc

       Here's one to try too :-)
         Edit1 := ZZZ
         Edit2 := 264172
     }
    end;

谢谢!

1 个答案:

答案 0 :(得分:5)

像许多编程问题一样,关键是将问题分解成小块。首先,让我们编写一个函数来将原始文件名解码为其组成部分:

procedure DecodeFileName(const Input: string; out Stem, Ext: string; out Number: Integer);
var
  P: Integer;
begin
  Ext := TPath.GetExtension(Input);
  Stem := TPath.GetFileNameWithoutExtension(Input);
  Number := 0;

  P := Stem.LastIndexOf('_');
  if P = -1 then begin
    exit;
  end;

  if TryStrToInt(Stem.Substring(P+1), Number) then begin
    Stem := Stem.Substring(0, P);
  end;
end;

以下说明了这是如何工作的:

DecodeFileName('test.txt', Stem, Ext, Number);
Writeln(Stem, ', ', Number, ', ', Ext);

DecodeFileName('test_dd.txt', Stem, Ext, Number);
Writeln(Stem, ', ', Number, ', ', Ext);

DecodeFileName('test_23.txt', Stem, Ext, Number);
Writeln(Stem, ', ', Number, ', ', Ext);

输出结果为:

test, 0, .txt
test_dd, 0, .txt
test, 23, .txt

所以现在你可以创建一个像这样的新文件名:

function IncrementedFileName(const FileName: string): string;
var
  Stem, Ext: string;
  Number: Integer;
begin
  DecodeFileName(FileName, Stem, Ext, Number);
  Result := Format('%s_%d%s', [Stem, Number+1, Ext]);
end;

然后我们可以看到它的表现如何:

Writeln(IncrementedFileName('test.txt'));
Writeln(IncrementedFileName('test_dd.txt'));
Writeln(IncrementedFileName('test_23.txt'));
Writeln(IncrementedFileName('test_28'));

输出结果为:

test_1.txt
test_dd_1.txt
test_24.txt
test_29

如果您无法访问字符串帮助程序方法,那么您可以像这样编写代码:

procedure DecodeFileName(const Input: string; out Stem, Ext: string; out Number: Integer);
var
  P: Integer;
begin
  Ext := TPath.GetExtension(Input);
  Stem := TPath.GetFileNameWithoutExtension(Input);
  Number := 0;

  P := LastDelimiter('_', Stem);
  if P = 0 then begin
    exit;
  end;

  if TryStrToInt(Copy(Stem, P+1, MaxInt), Number) then begin
    Stem := Copy(Stem, 1, P-1);
  end;
end;

我还没有执行这个最终功能,所以如果有错误也不要感到惊讶。