FileAttributeKeyを使ってファイルの情報を取得する


# 概要
- Swiftでファイルのサイズ・作成日時・inode番号などファイルの情報を取得したい。
- これはFileManagerの[attributesOfItem\(atPath:\)](https://developer.apple.com/documentation/foundation/filemanager/1410452-attributesofitem)で情報が取得できる。
- 具体的には下記のようにFinderの情報がいくつか取得することができる。

| 今回作成したもの | Finder(参考) |
|--------|-------|
|![image](https://i.imgur.com/awa8oQ3.png)|![image](https://i.imgur.com/CuBzO2z.png)|

# Gist
- [FileAttributesManager.md](https://gist.github.com/pommdau/e30413284f9c37daa0b572fd76c29205)

# 参考
- [\[iOSアプリ開発\] ファイルを抽象化した構造体を作る\(5\)](https://zenn.dev/nkysyuichi/articles/0689c909bcffb4)
- AppleのドキュメントにはC言語のデータ型が載っているので、Swiftに変換する時の参考に
    - [C言語のデータ型とSwiftのデータ型の対応表](https://ikeh1024.hatenablog.com/entry/2023/10/03/175042)
- [FileAttributeKey](https://developer.apple.com/documentation/foundation/fileattributekey)
- Dateに関して
    - [【Swift】Dateの王道 【日付】](https://qiita.com/rinov/items/bff12e9ea1251e895306#%E7%8E%8B%E9%81%931-style%E3%82%92%E6%A4%9C%E8%A8%8E%E3%81%99%E3%81%B9%E3%81%97)
    - [【Swift】DateFormatterの使い方 \| カピ通信](https://capibara1969.com/2153/)


# 実装

- 下記はFileAttributeKeyの[size](https://developer.apple.com/documentation/foundation/fileattributekey/1416548-size)を使用した例で、ファイルサイズを取得する例である。

```swift
let url = URL(fileURLWithPath: "/Users/ikeh/Downloads/InodeDemo/README.md")
guard let attributes = try? FileManager.default.attributesOfItem(atPath: url.path),
      let size = attributes[.size] as? NSNumber else {
    return
}
print(size)  // 568bytes
```

- [FileAttributeKey](https://developer.apple.com/documentation/foundation/fileattributekey)には色々種類があり、例えば作成日時・更新日時・inode番号などが取得できる。
- 種類が多いので今回下記のように、情報を取得するためのstructを作成した
    - ※一部の抜粋。他は[FileAttributesManager.md](https://gist.github.com/pommdau/e30413284f9c37daa0b572fd76c29205)を参照ください。

```swift
struct FileAttributesManager {
    
    // MARK: - Error Define
    
    enum FileAttributesError: Error {
        case typeCastingError
    }
    
    // MARK: - General
    
    static private var fileManager: FileManager = .default
    
    static private func loadAttributes(url: URL) throws -> [FileAttributeKey : Any] {
        try fileManager.attributesOfItem(atPath: url.path)
    }
}

// MARK: - Parameters

extension FileAttributesManager {
        
    // ファイルの作成日時
    // The key in a file attribute dictionary whose value indicates the file's creation date.
    static func creationDate(url: URL) throws -> Date {
        let attributes = try loadAttributes(url: url)
        guard let creationDate = attributes[.creationDate] as? Date else {
            throw FileAttributesError.typeCastingError
        }
        return creationDate
    }
        
    // ファイルサイズのバイト数
    // The key in a file attribute dictionary whose value indicates the file’s size in bytes.
    static func size(url: URL) throws -> UInt64 {
        let attributes = try loadAttributes(url: url)
        guard let size = attributes[.size] as? NSNumber else {
            throw FileAttributesError.typeCastingError
        }
        return size.uint64Value
    }
    
}
```

- 呼び出し例は以下の通り

```swift
guard let size = try? FileAttributesManager.size(url: url),
      let creationDate =  try? FileAttributesManager.creationDate(url: url),
      let modificationDate = try? FileAttributesManager.modificationDate(url: url) else {
    return nil
}
```