Как я могу санировать строку для использования в качестве имени файла?

У меня нет непосредственного опыта, но, судя по API, вы можете просто написать свой собственный класс, который реализует интерфейс Application.ActivityLifecycleCallbacks , и зарегистрировать этот класс в предоставленном экземпляре класса Application

getApplicaton().registerActivityLifecycleCallbacks(yourCustomClass);

Этот класс получит те же обратные вызовы, что и ваши отдельные действия. Удачи.

PS. Кстати, это уровень API 14, поэтому он не будет работать на старых телефонах.

26
задан Alex 31 July 2009 в 13:09
поделиться

6 ответов

Вы можете использовать функцию PathGetCharType , функцию PathCleanupSpec или следующий трюк:

  function IsValidFilePath(const FileName: String): Boolean;
  var
    S: String;
    I: Integer;
  begin
    Result := False;
    S := FileName;
    repeat
      I := LastDelimiter('\/', S);
      MoveFile(nil, PChar(S));
      if (GetLastError = ERROR_ALREADY_EXISTS) or
         (
           (GetFileAttributes(PChar(Copy(S, I + 1, MaxInt))) = INVALID_FILE_ATTRIBUTES)
           and
           (GetLastError=ERROR_INVALID_NAME)
         ) then
        Exit;
      if I>0 then
        S := Copy(S,1,I-1);
    until I = 0;
    Result := True;
  end;

Этот код делит строку на части и использует MoveFile для проверки каждой часть. MoveFile завершится ошибкой из-за недопустимых символов или зарезервированных имен файлов (например, «COM») и вернет успех или ERROR_ALREADY_EXISTS для допустимого имени файла.


PathCleanupSpec находится в Jedi Windows API в Win32API / JwaShlObj.pas

23
ответ дан 28 November 2019 в 06:51
поделиться

Что касается вопроса о том, есть ли какая-либо функция API для очистки файла с именем (или даже проверки его действительности), похоже, что ее нет. Цитата из комментария к функции PathSearchAndQualify () :

Похоже, не существует никакого Windows API, который проверял бы путь, введенный пользователем; это оставлено как специальное упражнение для каждого приложения.

Таким образом, вы можете ознакомиться с правилами допустимости имени файла только из Имена файлов, пути и пространства имен (Windows) :

  • Использовать почти любой символ в текущей кодовой странице для имени, включая символы Unicode и символы из расширенного набора символов (128–255), за исключением следующего:

    • Следующие зарезервированные символы не допускаются:
      <>: " / \ | ? *
    • Символы, целочисленные представления которых находятся в диапазоне от нуля до 31, не допускаются.
    • Любой другой символ, запрещенный целевой файловой системой.
  • Не используйте следующие зарезервированные имена устройств для имени файл: CON , PRN , AUX , NUL , COM1..COM9 , LPT1 ..LPT9 .
    Также избегайте этих имен, за которыми сразу следует расширение; например, NUL.txt не рекомендуется.

Если вы знаете, что ваша программа будет писать только в файловую систему NTFS, вы, вероятно, можете быть уверены, что нет других символов, которые файловая система не поддерживает allow, поэтому вам нужно будет только проверить, что имя файла не слишком длинное (используйте константу MAX_PATH ) после того, как все недопустимые символы будут удалены (или заменены, например, символами подчеркивания).

A Программа также должна убедиться, что очистка имени файла не привела к конфликту имен файлов, и она автоматически перезаписывает другие файлы с тем же именем.

12
ответ дан 28 November 2019 в 06:51
поделиться

Проверить, содержит ли строка недопустимые символы; решение из здесь :

//test if a "fileName" is a valid Windows file name
//Delphi >= 2005 version

function IsValidFileName(const fileName : string) : boolean;
const 
  InvalidCharacters : set of char = ['\', '/', ':', '*', '?', '"', '<', '>', '|'];
var
  c : char;
begin
  result := fileName <> '';

  if result then
  begin
    for c in fileName do
    begin
      result := NOT (c in InvalidCharacters) ;
      if NOT result then break;
    end;
  end;
end; (* IsValidFileName *)

И для строк, возвращающих False, вы можете сделать что-то простое, например this для каждого недопустимого символа:

var
  before, after : string;

begin
  before := 'i am a rogue file/name';

  after  := StringReplace(before, '/', '',
                      [rfReplaceAll, rfIgnoreCase]);
  ShowMessage('Before = '+before);
  ShowMessage('After  = '+after);
end;

// Before = i am a rogue file/name
// After  = i am a rogue filename
5
ответ дан 28 November 2019 в 06:51
поделиться

Что ж, проще всего использовать регулярное выражение и версию gsub вашего любимого языка для замены всего, что не является «словесным символом». Этот класс символов будет « \ w » в большинстве языков с регулярными выражениями, подобными Perl, или « [A-Za-z0-9] » в качестве простого варианта в противном случае.

] В частности, в отличие от некоторых примеров в других ответах, вы не хотите искать недопустимые символы для удаления, а ищите допустимые символы, которые нужно сохранить. Если вы ищете недопустимые символы, вы всегда уязвимы для введения новых символов, но если вы ищете только действительные, вы можете быть немного менее неэффективными (поскольку вы заменили символ, который на самом деле не нужно), но по крайней мере вы никогда не ошибетесь.

Теперь, если вы хотите сделать новую версию максимально похожей на старую, вы можете подумать о замене. Вместо удаления вы можете заменить символ или символы, которые вам подходят. Но это достаточно интересная проблема, и, вероятно, это хорошая тема для другого вопроса.

3
ответ дан 28 November 2019 в 06:51
поделиться

Я сделал это:

// Initialized elsewhere...
string folder;
string name;
var prepl = System.IO.Path.GetInvalidPathChars();
var frepl = System.IO.Path.GetInvalidFileNameChars();
foreach (var c in prepl)
{
    folder = folder.Replace(c,'_');
    name = name.Replace(c, '_');
}
foreach (var c in frepl)
{
    folder = folder.Replace(c, '_');
    name = name.Replace(c, '_');
}
1
ответ дан 28 November 2019 в 06:51
поделиться
{
  CleanFileName
  ---------------------------------------------------------------------------

  Given an input string strip any chars that would result
  in an invalid file name.  This should just be passed the
  filename not the entire path because the slashes will be
  stripped.  The function ensures that the resulting string
  does not hae multiple spaces together and does not start
  or end with a space.  If the entire string is removed the
  result would not be a valid file name so an error is raised.

}

function CleanFileName(const InputString: string): string;
var
  i: integer;
  ResultWithSpaces: string;
begin

  ResultWithSpaces := InputString;

  for i := 1 to Length(ResultWithSpaces) do
  begin
    // These chars are invalid in file names.
    case ResultWithSpaces[i] of 
      '/', '\', ':', '*', '?', '"', '<', '>', '|', ' ', #$D, #$A, #9:
        // Use a * to indicate a duplicate space so we can remove
        // them at the end.
        {$WARNINGS OFF} // W1047 Unsafe code 'String index to var param'
        if (i > 1) and
          ((ResultWithSpaces[i - 1] = ' ') or (ResultWithSpaces[i - 1] = '*')) then
          ResultWithSpaces[i] := '*'
        else
          ResultWithSpaces[i] := ' ';

        {$WARNINGS ON}
    end;
  end;

  // A * indicates duplicate spaces.  Remove them.
  result := ReplaceStr(ResultWithSpaces, '*', '');

  // Also trim any leading or trailing spaces
  result := Trim(Result);

  if result = '' then
  begin
    raise(Exception.Create('Resulting FileName was empty Input string was: '
      + InputString));
  end;
end;
7
ответ дан 28 November 2019 в 06:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: