Fly to the sky & Return

[Swift] Streamreader를 이용하여 원하는 부분을 빠르게 읽어오기 본문

프로그래밍/Swift(IOS & Mac)

[Swift] Streamreader를 이용하여 원하는 부분을 빠르게 읽어오기

낼은어떻게 2020. 3. 11. 19:23
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

맥용 어플중에  텍스트 리더로 쓸만한 애들이 없는 것 같아서  직접 만들어 쓰겠다는 일념으로 시작한 프로젝트의 일부입니다.

 

온라인상에서 흔히 찾아볼수 있는 streamreader 코드를 이용하여 대용량의 텍스트 파일을 빠르고..  원하는 부분으로 빠르게 이동하기 위한 방법을 고민하닥 만든 코드입니다.

실행환경 :  XCODE Version 11.3.1 (11C504)

 

다음은 넷상에서 쉽게 찾을 수 있는 StreamReader 코드입니다.

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
class StreamReader {
    let encoding: String.Encoding
    let chunkSize: Int
    let fileHandle: FileHandle
    var buffer: Data
    let delimPattern : Data
    var isAtEOF: Bool = false
 
    init?(url: URL, delimeter: String = "\n", encoding: String.Encoding = .utf8, chunkSize: Int = 4096)
    {
        guard let fileHandle = try? FileHandle(forReadingFrom: url) else { return nil }
        self.fileHandle = fileHandle
        self.chunkSize = chunkSize
        self.encoding = encoding
        buffer = Data(capacity: chunkSize)
        delimPattern = delimeter.data(using: .utf8)!
    }
 
    deinit {
        fileHandle.closeFile()
    }
 
    func rewind() {
        buffer.removeAll(keepingCapacity: true)
        isAtEOF = false
    }
    
    func setoffset(offset: UInt64) {
    }
    
    func offsetvalue() -> UInt64 {
        return fileHandle.offsetInFile
    }
 
    func nextLine() -> String? {
        if isAtEOF { return nil }
    
    repeat {
        if let range = buffer.range(of: delimPattern, options: [], in: buffer.startIndex..<buffer.endIndex) {
            let subData = buffer.subdata(in: buffer.startIndex..<range.lowerBound)
            let line = String(data: subData, encoding: encoding)
            buffer.replaceSubrange(buffer.startIndex..<range.upperBound, with: [])
            return line
            } else {
                let tempData = fileHandle.readData(ofLength: chunkSize)
                if tempData.count == 0 {
                    isAtEOF = true
                    return (buffer.count > 0) ? String(data: buffer, encoding: encoding) : nil
                }
                buffer.append(tempData)
            }
        } while true
    }
    
}
 
 
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
http://colorscripter.com/info#e" target="_blank" style="text-decoration:none;color:white">cs

 

위 코드를 이용하는 방법은 다음과같습니다.

1
2
3
4
5
let pathURL = URL(fileURLWithPath: (NSString(string: "~/Downloads/words.txt").expandingTildeInPath))
let s = StreamReader(url: pathURL)
while let line = s?.nextLine() {
    print(line)
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
http://colorscripter.com/info#e" target="_blank" style="text-decoration:none;color:white">cs

위 코드를 사용하면 불러온 문서 전체를 보여주게 되는데  제가 만들 부분은 필요한 부분만 가지과 와서 일종의 페이징을 할 예정이기 때문에 코드를 수정합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
        var text_result = [String]()
        
        let pathURL = URL(fileURLWithPath: (NSString(string:  "~/Downloads/words.txt").expandingTildeInPath))
        
         et s = StreamReader(url: pathURL)
         
        
         
         while let line = s?.nextLine() {
             
            text_result.append(line)
         }
         
        
        for list in text_result[1...100]{
        
        
            text_viewer.documentView!.insertText(list)
        }
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
http://colorscripter.com/info#e" target="_blank" style="text-decoration:none;color:white">cs

배열을 설정하고

 streamReader로 읽어드린 것을 배열에 저장합니다.

배열 index를 이용하여  원하는 위치의 텍스트를 불러들여 text_viewer 에 보여줍니다.

 

요렇게 하면 빠르게 10메가가 넘는 텍스트 파일도 빠르게 읽어들일 수가 있습니다.

일단 텍스트 리더로 쓰기에 적당한 코드가 된듯합니다.,