iOS文件名中允许使用哪些字符?

时间:2011-05-23 20:00:58

标签: ios file filenames character-encoding nsfilemanager

我正在寻找一种方法来确保字符串可以在iOS下用作文件名。我目前在删除不兼容字符的代码部分。我想知道我是否做得对。

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

我也想知道是否已经有一种方法可以将字符串验证为文件名。

感谢您的建议!

9 个答案:

答案 0 :(得分:27)

使用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:@"-"];

答案 1 :(得分:10)

我发现这更清洁,可能性能更高。这是基于Angel Naydenov的解决方案,但首先使用所有无效字符构建字符集,然后只调用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("")

答案 2 :(得分:9)

首先,你使用了错误的方法。修剪字符串只会删除字符串开头和结尾的字符。

您正在寻找的更像是:

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

然而,这是一个次优的解决方案,因为你必须为你想要排除的每个角色做到这一点,所以也许你想继续寻找或写你自己的方法来操纵字符串。

iOS是基于UNIX的,因此我认为它几乎支持文件名中的任何字符。 UNIX允许使用空格,<,>,|,\,:,(,),&,;以及通配符,例如?和*,使用\符号引用或转义。但是,我不会在我的文件名中使用任何这些字符。事实上,我会将文件名中的字符限制为'a' - 'z','0' - '9','_'和'。'。

答案 3 :(得分:9)

我必须在本地保存远程文件,文件名包含除基本字母数字字符之外的其他字符。我使用下面的方法去掉潜在的无效字符,确保在使用URLWithString生成NSURL时它是文件系统的有效文件名:

    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]]

答案 4 :(得分:7)

由于我没有在此问题中看到包含允许字符的列表,但问题想要一个包含此类字符的列表,我正在添加有关此主题的更多详细信息。

首先,我们需要知道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方法的原因是它对我来说似乎过于严格。我不想将我的用户仅限制为拉丁字符。他们也可能希望使用一些中文,西里尔文或其他任何他们喜欢的东西。

快乐的编码!

答案 5 :(得分:2)

此字符串扩展名(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"

答案 6 :(得分:1)

我提出了以下解决方案。到目前为止工作得很好。

import Foundation

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

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

答案 7 :(得分:0)

我对这个解决方案非常满意:

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:@"-"];

享受!

答案 8 :(得分:0)

基于玛丽安答案,这是一个字符串扩展名,用于删除所有不需要的字符。

extension String {

func stripCharacters() -> String {
    var invalidCharacters = CharacterSet(charactersIn: ":/")
    invalidCharacters.formUnion(.newlines)
    invalidCharacters.formUnion(.illegalCharacters)
    invalidCharacters.formUnion(.controlCharacters)

    let newString = self
        .components(separatedBy: invalidCharacters)
        .joined(separator: "_")

    return newString
   }
}

Example:
let fileName = "Man(lop23/45"
let newFileName = fileName.stripCharacters()
print(newFileName)