Simple text file I/O with Swift 3


(Ken Burgett) #1

Hi all,

I am trying to understand how Swift 3 File I/O works in a linux environment. I put together a trivial test program using what I
can glean from the few examples I can find. See below.

main.swift (426 Bytes)

···

===============================
import Glibc
import Foundation

let filename = Process.arguments[1]
let file_handle = fopen (filename, "r")
let BUFSIZE = 1024
var buf = [CChar](repeating:CChar(0), count:BUFSIZE)
while fgets(&buf, Int32(BUFSIZE), file_handle) != nil
{
   print(buf)
}
exit(0)

The program runs, but produces a stream of integer arrays, each of 1024 bytes. I can see what appears to be ASCII character values in the sample text, plus a lot of trailing zeros. I suspect I haven't mapped the bytes in buf to Strings, so how should that be done?
--
Ken Burgett
Principal Software Engineer
Email: kenb@iotone.io
Office: 530.693.4449
Mobile: 831.332.6846
URL: www.iotone.co


(Quinn “The Eskimo!”) #2

The trick here is to replace the above line with:

    print(String(validatingUTF8: buf))

`fgets` sets up `buf` to hold a C string, so you have to convert it to a Swift string. How do you do this depends on the encoding of the bytes. If you expect the C string to be UTF-8, then `String(validatingUTF8:)` is the way to go.

IMPORTANT: This conversion can fail, which is why the above will print a bunch of optional strings, and you will have to decide what to your program should do when it does.

                   * * *

btw This question came up recently. See the thread for other suggestions about how to handle it.

<http://article.gmane.org/gmane.comp.lang.swift.user/1943>

Share and Enjoy

···

On 28 May 2016, at 19:05, Ken Burgett via swift-users <swift-users@swift.org> wrote:

print(buf)

--
Quinn "The Eskimo!" <http://www.apple.com/developer/>
Apple Developer Relations, Developer Technical Support, Core OS/Hardware


(Ken Burgett) #3

Sorry, that does not compile with Swift 3. First of all, the expression "(count:BUFSIZE, repeatedValue:CChar(0))" must be written as "(repeating:CChar(0), count:BUFSIZE)", Note that the order within the expression is significant (don't ask me why, it just is. Ask the language designers).

Second, print line causes the compiler to disgorge the following:
" error: 'fromCString' is unavailable: Please use String.init?(validatingUTF8:) instead. Note that it no longer accepts NULL as a valid input. Also consider using String(cString:), that will attempt to repair ill-formed code units.
     print(String.fromCString(buf)!, terminator:"")
                  ^~~~~~~~~~~
Swift.String:4:24: note: 'fromCString' has been explicitly marked unavailable here
     public static func fromCString(_ cs: UnsafePointer<CChar>) -> String?
"

I frankly don't know how to parse that compiler output, since it is NOT like Swift 2.2, and is apparently trying to explain that in some tortured form of syntax. I don't know how to map that response into working code.

···

On 2016-05-28 18:54, TUNG CK wrote:

Same as Linux 2.2

import Glibc

let path = "./sample.txt"
let BUFSIZE = 1024

let fp = fopen(path, "r")
if fp != nil {
  var buf = [CChar](count:BUFSIZE, repeatedValue:CChar(0))
  while fgets(&buf, Int32(BUFSIZE), fp) != nil {
    print(String.fromCString(buf)!, terminator:"")
  }
}

Ken Burgett via swift-users <swift-users@swift.org> 於 29 May 2016 2:05 AM 寫道:

Hi all,

I am trying to understand how Swift 3 File I/O works in a linux environment. I put together a trivial test program using what I
can glean from the few examples I can find. See below.

===============================
import Glibc
import Foundation

let filename = Process.arguments[1]
let file_handle = fopen (filename, "r")
let BUFSIZE = 1024
var buf = [CChar](repeating:CChar(0), count:BUFSIZE)
while fgets(&buf, Int32(BUFSIZE), file_handle) != nil
{
print(buf)
}
exit(0)

The program runs, but produces a stream of integer arrays, each of 1024 bytes. I can see what appears to be ASCII character values in the sample text, plus a lot of trailing zeros. I suspect I haven't mapped the bytes in buf to Strings, so how should that be done?
--
Ken Burgett
Principal Software Engineer
Email: kenb@iotone.io
Office: 530.693.4449
Mobile: 831.332.6846
URL: www.iotone.co
<main.swift>
_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

--
Ken Burgett
Principal Software Engineer
Email: kenb@iotone.io
Office: 530.693.4449
Mobile: 831.332.6846
URL: www.iotone.co