Skip to content

Instantly share code, notes, and snippets.

@erica
Last active March 18, 2020 03:57
Show Gist options
  • Save erica/7aee99db9753a1636e0fbed8d68b5845 to your computer and use it in GitHub Desktop.
Save erica/7aee99db9753a1636e0fbed8d68b5845 to your computer and use it in GitHub Desktop.
#if os(Linux)
import Glibc
#else
import Darwin
#endif
// Still not lovely but tested under OS X Swift 3 and Linux Swift 3
// Use fopen/fwrite to output string
func writeStringToFile(string: String, path: String) -> Bool {
let fp = fopen(path, "w"); defer { fclose(fp) }
let byteArray = Array(string.utf8)
let count = fwrite(byteArray, 1, byteArray.count, fp)
return count == string.utf8.count
}
// Use fread to input string
func readStringFromFile(path: String) -> String {
let fp = fopen(path, "r"); defer { fclose(fp) }
var outputString = ""
let chunkSize = 1024
let buffer: UnsafeMutablePointer<CChar> = UnsafeMutablePointer(allocatingCapacity: chunkSize)
defer { buffer.deallocateCapacity(chunkSize) }
repeat {
let count: Int = fread(buffer, 1, chunkSize, fp)
guard ferror(fp) == 0 else { break }
if count > 0 {
let ptr = unsafeBitCast(buffer, to: UnsafePointer<CChar>.self)
if let newString = String(validatingUTF8: ptr) {
outputString += newString
}
}
} while feof(fp) == 0
return outputString
}
// Simple test case writes to file and reads back in
let inputString = "Hello Sailor"
let path = "/tmp/test.txt"
if writeStringToFile(string: inputString, path: path) {
let outputString = readStringFromFile(path: path)
print("String:", outputString)
}
@explainer
Copy link

This is great! I will plug it in to my testbed and, hopefully, learn something about Swift 3 Strings.

@mgritter
Copy link

I think I am seeing a bug with files bigger than 1024 bytes. fread() doesn't add a terminating null, so when we reuse the buffer on a less-than-1024 final chunk, we get part of the previous chunk.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment