일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- Git
- 스위프트
- enum
- IOS
- Method
- property
- String
- 코딩테스트
- extension
- Foundation
- Protocol
- Unicode
- Class
- tuist
- init
- delegate
- Terminal
- url
- struct
- instance
- Swift
- type
- 디자인패턴
- UIKit
- initalizer
- 이니셜라이저
- initializer
- interpace
- optional
- Xcode
- Today
- Total
아리의 iOS 탐구생활
[Swift/iOS] FileManager로 파일 생성(쓰기), 읽기, 삭제하기 본문
아이폰 앱마다 자기만의 공간을 가지고 있는데, 이 공간을 관리하는 매니저라 생각하면 될 것 같다. 이 공간은 일반 맥, 윈도우처럼 Document 폴더, Download 폴더 등등 다양한 종류의 폴더가 있다.
경로(URL) 접근하기
다른 작업을 하기전 공통 사항인 해당 폴더로 접근하는 방법을 먼저 알아보자.
// 파일매니저 인스턴스 생성
let fileManager = FileManager.default
// 사용자의 문서 경로
let documentPath: URL = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]
urls라는 메소드는 요청된 도메인에서 지정된 공통 디렉토리에 대한 URL배열을 리턴해주는 메소드이다.
- for: 폴더를 정해주는 요소. Download 혹은 Document 등등…
- in: 제한을 걸어주는 요소. 그 이상은 못가게 하는…
애플이 주석을 굉장히 잘 써놨으므로 좀더 디테일하게 보면 아래와 같다.
굉장히 많다. 그 중 친숙해 보이는 몇개만 가져왔다. 이런식으로 접근 폴더를 지정해준다.
- for enum 값들 (Objective C Enum)
documentDirectory // documents (Documents)
developerDirectory // (Developer) DEPRECATED - there is no one single Developer directory.
desktopDirectory // location of user's desktop
downloadsDirectory // location of the user's "Downloads" directory
musicDirectory // location of user's Music directory (~/Music)
...
- in enum 값들 (Swift Enum)
public static var localDomainMask: FileManager.SearchPathDomainMask { get }
// local to the current machine --- place to install items available to everyone on this machine (/Library)
public static var networkDomainMask: FileManager.SearchPathDomainMask { get }
// publically available location in the local area network --- place to install items available on the network (/Network)
public static var systemDomainMask: FileManager.SearchPathDomainMask { get }
// provided by Apple, unmodifiable (/System)
public static var allDomainsMask: FileManager.SearchPathDomainMask { get }
// all domains: all of the above and future items
터미널을 조금이라도 써봤다면 뒤에 괄호만 봐도 쉽게 이해할 수 있을 것이다.
경로(URL) 추가
appendingPathComponent 메소드를 사용하여 경로를 새롭게 추가해줄 수 있다. URL을 반환한다.
아래 예제에서는 "새 폴더" 라는 경로를 추가해주었다.
// FileManager 인스턴스 생성
let fileManager: FileManager = FileManager.default
// 사용자의 문서 경로
let documentPath: URL = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]
// 파일을 저장할 디렉토리 경로(URL) 반환 (경로 추가)
let directoryPath: URL = documentPath.appendingPathComponent("새 폴더")
"새 폴더"로 경로를 추가해줬다고 해서 폴더가 생성된 것이 아니다. 말 그대로 경로(URL)만 설정해준 것이라고 생각하면 된다.
자, 그러면 폴더 추가는 어떻게 할까?
Directory(폴더)를 추가하는 방법
do {
// 아까 만든 디렉토리 경로에 디렉토리 생성 (폴더가 만들어진다.)
try fileManager.createDirectory(at: directoryPath, withIntermediateDirectories: false, attributes: nil)
} catch let e {
print(e.localizedDescription)
}
아까 새로 만들어주었던 "새 폴더" 의 경로에 Directory를 생성하여 폴더를 만들어주었다. 경로에 직접 접근하면 폴더가 만들어진 것을 확인할 수 있다.
createDirectory 메소드의 파라미터들을 살펴보자.
- at: 경로 및 폴더명, 위에서 만든 URL 사용
- withIntermediateDirectories: “중간 디렉토리들도 만들거니?” 라는 의미
- attributes: 파일 접근 권한, 그룹 등등 폴더 속성 정의
Xcode에서 반환하는 경로(URL)을 타고 눈으로 직접 확인하고 싶다면, Finder에서 CMD + Shift + G를 누르게 된다면,
이러한 검색창이 뜨는데, directoryPath가 반환하는 URL을 그대로 복사하여 붙여넣으면 접근할 수 있다.
경로를 보면 hi.txt가 있는데 지금부터 FileManager를 이용하여 hi.txt를 만들어줄 것이다.
Directory(폴더)에 파일 추가하는 방법
자, 먼저 txt파일을 생성해줘야 한다.
폴더를 만들 때와 똑같이 경로(URL)를 먼저 설정해줘야 한다.
let textPath: URL = directoryPath.appendingPathComponent("hi.txt")
그리고 해당 경로에 String 타입을 Data로 변환하여 '쓰기'를 진행하면 텍스트파일이 생성되면서 안에 내가 변환한 문자열 데이터가 작성되어 만들어진다.
// 아까 만든 'hi.txt' 경로에 텍스트 쓰기
if let data: Data = "안녕하세요.".data(using: String.Encoding.utf8) { // String to Data
do {
try data.write(to: textPath) // 위 data를 "hi.txt"에 쓰기
} catch let e {
print(e.localizedDescription)
}
}
파일을 생성하였으니 해당 파일을 읽어오려면 쓰기에서 했던 작업을 반대로 해주면 된다.
파일을 불러오는 방법
// 만든 파일 불러와서 읽기.
do {
let dataFromPath: Data = try Data(contentsOf: textPath) // URL을 불러와서 Data타입으로 초기화
let text: String = String(data: dataFromPath, encoding: .utf8) ?? "문서없음" // Data to String
print(text) // 출력
} catch let e {
print(e.localizedDescription)
}
아까 hi.txt 경로(불러올 파일의 경로)를 Data 타입으로 초기화 해주고, Data 타입을 String으로 인코딩 해주게 되면 읽을 수 있게 된다.
생성한 파일을 삭제하려면 어떻게 하는거지?
파일을 삭제하는 방법
// 파일을 삭제한다.
do {
try fileManager.removeItem(at: textPath)
} catch let e {
print(e.localizedDescription)
}
removeItem 메소드를 호출하여 삭제할 파일의 경로(URL)을 전달해주면 된다.
삭제를 하고 Finder를 확인해보거나 불러오려고 다시 읽기를 시도하면 에러가 발생하는 것을 확인할 수 있다.
do {
let dataFromPath: Data = try Data(contentsOf: textPath) // URL을 불러와서 Data타입으로 초기화
let text: String = String(data: dataFromPath, encoding: .utf8) ?? "문서없음" // Data to String
print(text) // 출력
} catch let e {
print(e.localizedDescription) // The file “hi.txt” couldn’t be opened because there is no such file.
}
Full Code
// FileManager 인스턴스 생성
let fileManager: FileManager = FileManager.default
// 사용자의 문서 경로
let documentPath: URL = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]
// 파일을 저장할 디렉토리 경로(URL) 반환 (경로 추가)
let directoryPath: URL = documentPath.appendingPathComponent("새 폴더")
// 디렉토리에 만들 '파일이름.확장자' 설정 (경로에 'hi.txt'의 새 경로 추가)
let textPath: URL = directoryPath.appendingPathComponent("hi.txt")
// 파일매니저로 디렉토리 생성하기
do {
// 아까 만든 디렉토리 경로에 디렉토리 생성 (폴더가 만들어진다.)
try fileManager.createDirectory(at: directoryPath, withIntermediateDirectories: false, attributes: nil)
} catch let e {
print(e.localizedDescription)
}
// 아까 만든 'hi.txt' 경로에 텍스트 쓰기
if let data: Data = "안녕하세요.".data(using: String.Encoding.utf8) { // String to Data
do {
try data.write(to: textPath) // 위 data를 "hi.txt"에 쓰기
} catch let e {
print(e.localizedDescription)
}
}
// 만든 파일 불러와서 읽기.
do {
let dataFromPath: Data = try Data(contentsOf: textPath) // URL을 불러와서 Data타입으로 초기화
let text: String = String(data: dataFromPath, encoding: .utf8) ?? "문서없음" // Data to String
print(text) // 출력
} catch let e {
print(e.localizedDescription)
}
// 파일을 삭제한다.
do {
try fileManager.removeItem(at: textPath)
} catch let e {
print(e.localizedDescription)
}
// 삭제한 파일을 읽으려니 에러 발생
do {
let dataFromPath: Data = try Data(contentsOf: textPath)
let text: String = String(data: dataFromPath, encoding: .utf8) ?? "문서없음"
print(text)
} catch let e {
print(e.localizedDescription) // The file “hi.txt” couldn’t be opened because there is no such file.
}
QnA
텍스트나 이미지 말고 GIF 등등 다른건 어떻게 관리하죠?
NSDate 형식으로 아래처럼 손쉽게 변경할 수 있다.
// Archive Data
let archivedData = NSKeyedArchiver.archivedData(withRootObject: file)
// Unarchive Data
let unarchivedData = NSKeyedUnarchiver.unarchiveObject(with: file as Data)
애플 내장 앱중 File App 이랑 관련이 있나요?
관련 있다. 프로젝트 내에 설정을 하면 File App이 해당 어플에 접근할 수 있게 된다.
Reference
'Swift > iOS' 카테고리의 다른 글
[iOS] Bundle이 뭘까? (0) | 2021.09.28 |
---|---|
[iOS/Xcode] Auto Layout에 대해 알아보자. (1) | 2021.09.27 |
[Swift] 시간과 날짜를 다루는 타입에 대해서 알아보자. (0) | 2021.08.25 |
[Swift/iOS] Codable로 JSON을 파싱해보자. (0) | 2021.08.22 |
[Swift/iOS] 메모리를 관리해주는 ARC에 대해 알아보자. (0) | 2021.08.15 |