web-dev-qa-db-ja.com

iOSファイル名に使用できる文字は何ですか?

IOSで文字列をファイル名として使用できるようにする方法を探しています。私は現在、互換性のない文字を削除するコードのセクションにいます。私はそれを正しくやっているかどうか疑問に思っています。

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

文字列をファイル名として検証するメソッドがすでにあるかどうかも疑問に思います。

アドバイスありがとうございます!

21

まず第一に、あなたは間違った方法を使用しています。文字列をトリミングすると、文字列の最初と最後の文字のみが削除されます。

あなたが探しているものはもっと似ています:

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

ただし、これは最適ではない解決策です。除外するすべての文字に対してこれを行う必要があるため、文字列を操作するための独自のメソッドを探し続けたり、記述したりする必要があるかもしれません。

iOSはUNIXベースであるため、ファイル名のほぼすべての文字をサポートしていると思います。 UNIXでは、空白、<、>、|、\、:、(、)、&、;、および?などのワイルドカードを使用できます。および*、\記号を使用して引用符またはエスケープします。ただし、ファイル名にはこれらの文字は使用しません。実際、ファイル名の文字は「a」-「z」、「0」-「9」、「_」、「。」に制限します。

9
Erik B

正規表現を使用する:

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

これはよりクリーンで、おそらくはるかにパフォーマンスが高いと思います。これはAngelNaydenovのソリューションに基づいていますが、最初にすべての無効な文字を使用して文字セットを作成し、次にcomponents(separatedBy:)を1回だけ呼び出します。

スウィフト3&4

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

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

スウィフト2

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

let filename = originalFilename
    .componentsSeparatedByCharactersInSet(invalidCharacters)
    .joinWithSeparator("")
14
Marián Černý

基本的な英数字以外の文字を含むファイル名でリモートファイルをローカルに保存する必要がありました。以下の方法を使用して、潜在的な無効な文字を取り除き、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]]
9
Lmd64

この質問では許可された文字を含むリストは表示されませんでしたが、質問ではそのような文字を含むリストが必要だったため、このトピックについてもう少し詳しく説明します。

まず、iOSデバイスが使用するファイルシステムを知る必要があります。複数のオンラインソースを使用すると、これはHFS +の大文字と小文字を区別するバージョンであるHFSXのようです。そして、参照用にここに1つのリンクを含めます: 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("/"))

私が正規表現アプローチを好まない理由は、それが私にはあまりにも制限的であるように思われるからです。ユーザーをラテン文字だけに制限したくありません。中国語、キリル文字、またはその他の好きなものを使用したい場合もあります。

ハッピーコーディング!

8
Angel Naydenov

この文字列拡張子(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"
4
Groot

私は次の解決策を思いついた。これまでのところうまく機能します。

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()
1
Sebastian Boldt

Marian Answersに基づいて、不要な文字を削除するための文字列拡張機能を次に示します。

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)
0
STerrier

私はこの解決策にかなり満足しています:

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

楽しい!

0