Я ищу способ убедиться, что строку можно использовать в качестве имени файла под iOS. Я сейчас нахожусь в разделе кода, который удаляет несовместимые символы. Мне интересно, правильно ли я делаю.
NSString *filename = @"A file name";
fileName = [fileName stringByTrimmingCharactersInSet: [NSCharacterSet controlCharacterSet]];
fileName = [fileName stringByTrimmingCharactersInSet: [NSCharacterSet newlineCharacterSet]];
Мне также интересно, существует ли уже метод, который проверяет строку как имя файла.
Спасибо за совет!
Прежде всего, вы используете неправильный метод. Обрезка строки удалит только символы в начале и конце строки.
То, что вы ищете, выглядит примерно так:
fileName = [fileName stringByReplacingOccurrencesOfString:@"/" withString:@"_"];
Однако это неоптимальное решение, поскольку вам придется делать это для каждого персонажа, которого вы хотите исключить, поэтому, возможно, вы захотите чтобы продолжать искать или писать, у вас есть собственный метод манипулирования строкой.
iOS основана на UNIX и, как полагаю, поддерживает практически любые символы в именах файлов. UNIX допускает пробелы, & lt ;,>, |, \,:, (,), & amp ;,;, а также символы подстановки, такие как? и *, для кавычек или экранирования с помощью символа \. Однако я не буду использовать ни один из этих символов в моих именах файлов. Фактически, я бы ограничил символы в именах файлов до «a» - «z», «0» - «9», «_» и «.».
Используйте RegEx:
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"[^a-zA-Z0-9_]+" options:0 error:nil];
filename = [regex stringByReplacingMatchesInString:filename options:0 range:NSMakeRange(0, filename.length) withTemplate:@"-"];
Я считаю, что это чище и, вероятно, намного более эффективно. Это основано на решении Ангела Найденова, но сначала создается набор символов со всеми недопустимыми символами, а затем вызывается components(separatedBy:)
только один раз.
var invalidCharacters = CharacterSet(charactersIn: ":/")
invalidCharacters.formUnion(.newlines)
invalidCharacters.formUnion(.illegalCharacters)
invalidCharacters.formUnion(.controlCharacters)
let newFilename = originalFilename
.components(separatedBy: invalidCharacters)
.joined(separator: "")
let invalidCharacters = NSMutableCharacterSet(charactersInString: ":/")
invalidCharacters.formUnionWithCharacterSet(NSCharacterSet.newlineCharacterSet())
invalidCharacters.formUnionWithCharacterSet(NSCharacterSet.illegalCharacterSet())
invalidCharacters.formUnionWithCharacterSet(NSCharacterSet.controlCharacterSet())
let filename = originalFilename
.componentsSeparatedByCharactersInSet(invalidCharacters)
.joinWithSeparator("")
Мне приходилось сохранять удаленные файлы локально с именами файлов, содержащими другие символы, кроме основных буквенно-цифровых символов. Я использую метод ниже, чтобы удалить потенциально недопустимые символы, гарантируя, что это правильное имя файла для файловой системы при генерации 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]]
Это расширение String (Swift 4.2) поможет преобразовать недопустимое имя файла iOS в правильное имя файла iOS.
extension String {
func convertToValidFileName() -> String {
let invalidFileNameCharactersRegex = "[^a-zA-Z0-9_]+"
let fullRange = startIndex..<endIndex
let validName = replacingOccurrences(of: invalidFileNameCharactersRegex,
with: "-",
options: .regularExpression,
range: fullRange)
return validName
}
}
Например
"name.name?/!!23$@1asd".convertToValudFileName() // "name-name-23-1asd"
"!Hello.312,^%-0//\r\r".convertToValidFileName() // "-Hello-312-0-"
"/foo/bar/pop?soda=yes|please".convertToValidFileName() // "-foo-bar-pop-soda-yes-please"
Я очень доволен этим решением:
NSString *testString = @"This*is::/legal.
Поскольку в этом вопросе я не видел списка с разрешенными символами, но вопрос требовал списка с такими символами, я добавляю немного больше деталей по этой теме.
Сначала нам нужно узнать, какую файловую систему используют устройства 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("/"))
Причина, по которой я не предпочитаю подход RegEx, заключается в том, что он кажется мне слишком ограничительным. Я не хочу ограничивать своих пользователей только латинскими символами. С таким же успехом они могут захотеть использовать китайский, кириллицу или все, что им нравится.
Удачного кодирования!