Какие символы разрешены в имени файла iOS?

Я ищу способ убедиться, что строка может использоваться в качестве имени файла под iOS. В настоящее время я нахожусь в разделе кода, который удаляет несовместимые символы. Мне интересно, правильно ли я это делаю.

NSString *filename = @"A file name";
fileName = [fileName stringByTrimmingCharactersInSet: [NSCharacterSet controlCharacterSet]];
fileName = [fileName stringByTrimmingCharactersInSet: [NSCharacterSet newlineCharacterSet]];

мне также интересно, есть ли уже метод, который проверяет строку как имя файла.

Спасибо за ваш совет!

7 ответов


прежде всего, вы используете неправильный метод. Обрезка строки приведет только к удалению символов в начале и конце строки.

то, что вы ищете, больше похоже на:

fileName = [fileName stringByReplacingOccurrencesOfString:@"/" withString:@"_"];

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

iOS основан на UNIX и как таковой я полагаю, что это поддерживает практически любые символы в именах файлов. UNIX допускает пробелы, , |, \, :, (, ), &, ;, а также подстановочные знаки, такие как ? и *, чтобы быть в кавычках или экранировать с помощью символа\. Однако я бы не использовал ни один из этих символов в своих именах файлов. Фактически, я бы ограничил символы в моих именах файлов "a" - "z', '0'-'9', '_' и".'.


Использовать Регулярное Выражение:

NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"[^a-zA-Z0-9_]+" options:0 error:nil];
filename = [regex stringByReplacingMatchesInString:filename options:0 range:NSMakeRange(0, filename.length) withTemplate:@"-"];

мне пришлось сохранять удаленные файлы локально с именами файлов, содержащими другие символы, кроме основных буквенно-цифровых символов. Я использую метод ниже, чтобы удалить потенциальные недопустимые символы, гарантируя, что это допустимое имя файла для файловой системы при создании NSURL с помощью URLWithString:

    filename = [[filename componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] componentsJoinedByString:@"" ];
    filename = [[filename componentsSeparatedByCharactersInSet:[NSCharacterSet illegalCharacterSet]] componentsJoinedByString:@"" ];
    filename = [[filename componentsSeparatedByCharactersInSet:[NSCharacterSet symbolCharacterSet]] componentsJoinedByString:@"" ];
    fileURLString = [NSTemporaryDirectory() stringByAppendingPathComponent:filename];
    fileURL = [NSURL URLWithString:fileURLString];

вы также можете сначала протестировать ошибки столкновения, используя:

    [[NSFileManager defaultManager] fileExistsAtPath:[fileURL absoluteString]]

Я нахожу это более чистым и, вероятно, гораздо более эффективным. Это основано на решении Ангела Найденова, но сначала построение набора символов со всеми недопустимыми символами, а затем вызов components(separatedBy:) только один раз.

Swift 3 & 4

var invalidCharacters = CharacterSet(charactersIn: ":/")
invalidCharacters.formUnion(.newlines)
invalidCharacters.formUnion(.illegalCharacters)
invalidCharacters.formUnion(.controlCharacters)

let newFilename = originalFilename
    .components(separatedBy: invalidCharacters)
    .joined(separator: "")

Swift 2

let invalidCharacters = NSMutableCharacterSet(charactersInString: ":/")
invalidCharacters.formUnionWithCharacterSet(NSCharacterSet.newlineCharacterSet())
invalidCharacters.formUnionWithCharacterSet(NSCharacterSet.illegalCharacterSet())
invalidCharacters.formUnionWithCharacterSet(NSCharacterSet.controlCharacterSet())

let filename = originalFilename
    .componentsSeparatedByCharactersInSet(invalidCharacters)
    .joinWithSeparator("")

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

Сначала нам нужно знать, что такое файловая система, которую используют устройства iOS. Используя несколько онлайн-источников, это, по-видимому, HFSX, который является чувствительной к регистру версией HFS+. И включая одну ссылку здесь для справки: https://apple.stackexchange.com/questions/83671/what-filesystem-does-ios-use

теперь мы знаем, что файловая система мы можем искать какие символы не допускаются. И это, похоже, двоеточие (:) и Слэш (/). Вот ссылка для справки:http://www.comentum.com/File-Systems-HFS-FAT-UFS.html

имея эту информацию и то, что другие написали в этом потоке, мое личное предпочтение для удаления недопустимых символов из имена файлов - это следующий Swift код:

filename = "-".join(filename.componentsSeparatedByCharactersInSet(NSCharacterSet.newlineCharacterSet()))
filename = "-".join(filename.componentsSeparatedByCharactersInSet(NSCharacterSet.illegalCharacterSet()))
filename = "-".join(filename.componentsSeparatedByCharactersInSet(NSCharacterSet.controlCharacterSet()))
filename = "-".join(filename.componentsSeparatedByString(":"))
filename = "-".join(filename.componentsSeparatedByString("/"))

причина, по которой я не предпочитаю подход регулярных выражений, заключается в том, что он кажется мне слишком ограничительным. Я не хочу ограничивать своих пользователей только латинскими символами. Они также могут захотеть использовать китайский, кириллицу или что-то еще, что им нравится.

удачи в кодировании!


Я придумал следующее решение. Пока неплохо работает.

import Foundation

extension String {
    func removeUnsupportedCharactersForFileName() -> String {
        var cleanString = self
        ["?", "/", "\", "*"].forEach {
            cleanString = cleanString.replacingOccurrences(of: , with: "-")
        }
        return cleanString
    }
}

let a = "***???foo.png"
let validString = a.removeUnsupportedCharactersForFileName()

Я очень доволен этим решением:

NSString *testString = @"This*is::/legal.,?縦書き 123";
NSString *result = [[[testString componentsSeparatedByCharactersInSet:[[NSCharacterSet alphanumericCharacterSet] invertedSet]] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"length > 0"]] componentsJoinedByString:@"-"];

выход:

"This-is-legal-縦書き-123"

что это за колдовство?

позвольте мне разбить его на несколько строк, чтобы было понятно, что происходит:

NSString *testString = @"This*is::/legal.,?縦書き 123";
// Get a character set for everything that's NOT alphanumeric.
NSCharacterSet *nonAlphanumericCharacterSet = [[NSCharacterSet alphanumericCharacterSet] invertedSet];
// Split the string on each non-alphanumeric character, thus removing them.
NSArray *cleanedUpComponentsWithBlanks = [testString componentsSeparatedByCharactersInSet:nonAlphanumericCharacterSet];
// Filter out empty strings ("length" is a KVO-compliant property that the predicate can call on each NSString in the array).
NSArray *cleanedUpComponentsWithoutBlanks = [cleanedUpComponentsWithBlanks filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"length > 0"]];
// Put the components back together and join them with a "-".
NSString *result = [cleanedUpComponentsWithoutBlanks componentsJoinedByString:@"-"];

наслаждайтесь!