2

I am implementing a small logger, in which I am writing to a TXT file. I wanted the last event to be at the top of the file but I'm having trouble getting this to work. All examples on the internet are using "fileHandle.seekToEndOfFile()" to write at the end of the file.

This is what I have:

private static func writeToFile(text: String) {

        guard let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first else { return }
        guard let writePath = NSURL(fileURLWithPath: path).appendingPathComponent(Logger.folderName) else { return }
        let fileManager = FileManager.default

        try? fileManager.createDirectory(atPath: writePath.path, withIntermediateDirectories: true)
        let file = writePath.appendingPathComponent(Logger.fileName)

        if !fileManager.fileExists(atPath: file.path) {
            do {
                try "".write(toFile: file.path, atomically: true, encoding: String.Encoding.utf8)
            } catch _ {
            }
        }

        let msgWithLine = text + "\n"
        do {
            let fileHandle = try FileHandle(forWritingTo: file)
            //fileHandle.seekToEndOfFile()
            fileHandle.write(msgWithLine.data(using: .utf8)!)
            fileHandle.closeFile()
        } catch {
            print("Error writing to file \(error)")
        }
    }

With this code, I write in the first line but nevertheless, I am always rewriting what is on the first line.

How can I change this to whatever is in the first be taken to a line below and then write new content in the first line?

Thank you!!

Tiago Mendes
  • 4,572
  • 1
  • 29
  • 35
  • what about fileHandle.seek(toFileOffset: 0) instead of fileHandle.seekToEndOfFile() – m1sh0 Jun 04 '19 at 10:28
  • Why do you need this approach, the normal solution is to append at the end of the file? – Joakim Danielson Jun 04 '19 at 13:42
  • @JoakimDanielson I have inside of one app one small logger view and make sense to show on top the more recent event. I saw the solution by m1sh0 and I saw it going to be very heavy. I'll follow the suggestion m1sh0 write normally on the text file and then revert when is to show. – Tiago Mendes Jun 04 '19 at 14:14
  • That sound like the best solution! – Joakim Danielson Jun 04 '19 at 15:00

1 Answers1

2

This should be okay: First, get the old data and after that append the new one and write everything.

let msgWithLine = text + "\n"
do {
    let fileHandle = try FileHandle(forWritingTo: file)
    fileHandle.seek(toFileOffset: 0)
    let oldData = try String(contentsOf: file, encoding: .utf8).data(using: .utf8)!
    var data = msgWithLine.data(using: .utf8)!
    data.append(oldData)
    fileHandle.write(data)
    fileHandle.closeFile()
} catch {
    print("Error writing to file \(error)")
}

I didn't test the code it may have some problems.

Another possible solution is to write at the end of the file and to invert the file when you read it.

m1sh0
  • 2,236
  • 1
  • 16
  • 21
  • It work, I just had to changed the line: let oldData = fileHandle.readDataToEndOfFile() To this: let oldData = try String(contentsOf: file, encoding: .utf8).data(using: .utf8)! – Tiago Mendes Jun 04 '19 at 13:05
  • But by doing this is going to be a heavy process even if is working in a background thread? – Tiago Mendes Jun 04 '19 at 13:07
  • @TiagoMendes you are right it will be heavy for big files – m1sh0 Jun 04 '19 at 13:19
  • 1
    @TiagoMendes something that you can think is if you write the file in a normal way (like just adding text at the end of the file) and only when you read to invert the lines. But this is related to the sums of writes and reads of the file. – m1sh0 Jun 04 '19 at 14:02
  • Yes you are right, write normal and the revert is the way to go. Thank you for the suggestion :) I'll mark your answer correctly. Since that was the answered the question. – Tiago Mendes Jun 04 '19 at 14:11
  • How can I write to the end of a file? – Aalexander Dec 22 '20 at 12:35
  • maybe with this fileHandle.seekToEndOfFile() – m1sh0 Dec 23 '20 at 15:21