【Swift】アプリからCSVファイルを作成・保存・書き込みする方法!
この記事からわかること
- SwiftでCSVファイルを作成する方法
- 保存や追記などの操作
- デバイス内ないから確認するには?
- BOM付きUTF-8とは?
- OutputStreamの使い方
index
[open]
\ アプリをリリースしました /
友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-
posted withアプリーチ
CSVファイルとは?
そもそもCSVファイルとは「Comma-Separated Values」の略称で直訳すると「カンマで区切られた値」という意味になります。
ファイル名通りCSVファイルは行単位にカンマ(,)区切りで値が区切られているテキストファイル形式です。
Excelを使用してCSVファイルを開くことができますが、「0落ち(001が1になる)」や「文字化け」、「日付変換」などそれなりに問題は多いです。
CSVファイル自体はフォーマットに準じた普通のテキストファイルなのでSwiftでも簡単に作成することができます。
SwiftでCSVファイルを構築する方法
Swiftで CSVファイルを構築するにはCSVの記述形式に倣ったデータをファイルに書き込むだけです。まずはCSV形式の文字列を定義します。
以下のようにカンマを使って値を区切り、行の終わりには改行コード(\r\n)を渡します。
let csv = "name,age,like\r\name,26,chocolat\r\nkasa,20,hamburger\r\n"
CSVファイルをデバイスに保存する
「デバイスに保存」と書きましたが厳密には「アプリ内のフォルダへのアクセスを許可する」になります。
作成したCSVファイルはアプリのDocumentsフォルダへ保存します。そしてそのDocumentsフォルダを「ファイル」アプリからアクセス可能にすることで表示できるようにします。そのためには設定が必要なので以下記事を参考に設定しておいてください。
おすすめ記事:【Swift】ファイルアプリからDocumentsフォルダへアクセス許可する方法!
では実際にUIKitベースでコードにしていきます。コピペだけで動作するように作っていくので試してみてください。まずはUIを配置します。
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let button = UIButton()
button.frame = CGRect(x: 0, y:0, width: 100 , height: 100)
button.backgroundColor = .orange
button.center = self.view.center
button.addTarget(self, action: #selector(createFile), for: .touchUpInside)
self.view.addSubview(button)
}
}
続いてボタン押下時にCSVファイルをDocumentsフォルダに生成する処理を記述します。ファイル操作にはFileManager
クラスを使用します。
おすすめ記事:【Swift】FileManagerでファイルを保存!操作方法や格納場所
@objc func createFile() {
// Documentsディレクトリまでのパスを生成
let fileManager = FileManager.default
let docPath = NSHomeDirectory() + "/Documents"
let filePath = docPath + "/sample.csv"
let csv = "name,age,like\r\name,26,chocolat\r\nkasa,20,hamburger\r\n"
let data = csv.data(using: .utf8)
if !fileManager.fileExists(atPath: filePath) {
fileManager.createFile(atPath:filePath, contents: data, attributes: [:])
}else{
print("既に存在します。")
}
}
FileManager
クラスを使用して保存先のパスとファイル名を指定し、CSVデータは文字列で定義後Data型に変換しFileManager
クラスに渡します。
これでボタンを押すとCSVファイルが生成されているので確認してみます。シミュレーター内の「ファイル」アプリから、「このiPhone内」>「アプリ名」>「ファイル名」を確認し以下のように生成したファイルを確認できれば成功です。
開いてみるとExcelのように値がセルごとに区切られた形式で正しく保存されていることを確認できます。
またこのファイルをExcelで開いても正常に表示されました。
BOM付きUTF-8にして文字化けを防ぐ
英語や数字のみの場合はExcelでも問題なく表示できましたが、日本語などのマルチバイト文字を含む以下のようなCSVデータの場合は「ファイル」からは正常に表示できましたが、「Excel」からでは文字化けを起こしてしまいました。
let csv = "名前,年齢,好きなもの\r\nあめ,26,チョコレート\r\nかさ,20,ハンバーガー\r\n"
これを解決するにはBOM付きUTF-8形式のCSVファイルにする必要があります。
BOM付きUTF-8とは?
UTF-8は文字コード(コンピューター上で文字を表示するための形式)の1つであり、Unicode用の符号化方式です。
BOM(ボム)とは「byte order mark」の略称でファイル先頭に付与される3バイトの識別子です。識別するのは「符号化方式(これはUnicodeのUTF-8だよ)」です。
SwiftでBOMを付与する
BOMを付与するにはOutputStream
クラスを使用します。UnicodeのUTF-8のBOMは「U+FEFF
」らしいのでそれを付与します。
参考文献:BOM(Byte Order Mark)
ではどうやって付与するのかというとエスケープ文字を使ってUnicodeの文字列が表現できるようなので以下記事を参考に構築していきます。
参考文献:2.3.8. Unicode | 文字列と文字 | Swift
\u{n}
形式(n部分に16進数)でUnicodeスカラーが表現できるので\u{feff}
とすることでBOMを定義できます。あとはOutputStream
クラスを用いてCSVファイルを作成するコードに書き換えます。
@objc func createFile() {
let fileManager = FileManager.default
guard let docURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first else{
fatalError("URL取得失敗")
}
let filePath = docURL.appendingPathComponent("sample.csv")
if let strm = OutputStream(url:filePath, append: false) {
strm.open()
defer {
strm.close()
}
let BOM = "\u{feff}"
strm.write(BOM, maxLength: 3)
let csv = "名前,年齢,好きなもの\r\nあめ,26,チョコレート\r\nかさ,20,ハンバーガー\r\n"
let data = csv.data(using: .utf8)
let _ = data?.withUnsafeBytes {
strm.write($0, maxLength: Int(data?.count ?? 0))
}
}else{
print("false")
}
}
コードはガッツリ変更になりましたが正常にファイルアプリからCSVファイルが表示でき、またExcelからも以下のように文字化けを起こすことなく表示できるようになりました。
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。