Pure Swift, cross platform way to open, read/write files?


(Greg Skluzacek) #1

Hi new to Swift and I am really excited that Apple has open sourced it! I
use macs at home an Linux at work, so now I may actually be able to develop
in one language on both platforms (and not use Java).

That being said, is there a way open a file for either reading line by line
and writing line by line that is done purely in Swift and is cross platform.

I did go through the Getting Started page and saw that one was able to
import Glibc on Linux which implements the C fopen, etc., but when I tried
to import it in the REPL on OS X, I got the error:

repl.swift:1:8: error: no such module 'Glibc'

import Glibc

       ^

swift --version returns:

Chateau-Louise:/ gskluzacek$ swift --version

Apple Swift version 2.1 (swiftlang-700.1.101.6 clang-700.1.76)

Target: x86_64-apple-darwin14.5.0

Chateau-Louise:/ gskluzacek$

Thanks,
-- Greg


(Kwame Bryan) #2

Hi Greg, you’ll need to do something like the following.
#if os(Linux)
    import Glibc
#else
    import Darwin
#endif
Also, take a look at this blog post. http://blog.krzyzanowskim.com/2015/12/04/swift-package-manager-and-linux-compatible/ Hope this helps.

Kwame

···

On Dec 7, 2015, at 10:47 PM, Greg Skluzacek via swift-users <swift-users@swift.org> wrote:

Hi new to Swift and I am really excited that Apple has open sourced it! I use macs at home an Linux at work, so now I may actually be able to develop in one language on both platforms (and not use Java).

That being said, is there a way open a file for either reading line by line and writing line by line that is done purely in Swift and is cross platform.

I did go through the Getting Started page and saw that one was able to import Glibc on Linux which implements the C fopen, etc., but when I tried to import it in the REPL on OS X, I got the error:

repl.swift:1:8: error: no such module 'Glibc'
import Glibc
       ^

swift --version returns:

Chateau-Louise:/ gskluzacek$ swift --version
Apple Swift version 2.1 (swiftlang-700.1.101.6 clang-700.1.76)
Target: x86_64-apple-darwin14.5.0
Chateau-Louise:/ gskluzacek$

Thanks,
-- Greg
_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


(Greg Skluzacek) #3

Thanks for that blog post... perhaps I wasn't clear in what my actual
question was. Let me restate:

Obviously I can use Glibc on Linux to open a file and read it. And since
there is no Glibc on OS X, is there some other way that would be both CROSS
PLATFORM and done purely in swift instead of relying on some external C
library?

I've taken a cursory look at some of the early swift resources and didn't
see anything that mentioned how to open a file using JUST Native Swift
code... One would surely think that a programing language as nifty and cool
as Swift would have a easy way to read files. Maybe its obvious and I just
am missing it.

But at the same time I get your point just use #if #else #endif to
conditional import / call functions... but coding like that doesn't seem
vary fun... reminds me of looking a C code that was meant to be compiled on
different processor architectures. :frowning:

--Greg

···

On Mon, Dec 7, 2015 at 9:51 PM, Kwame Bryan <kwame.bryan@gmail.com> wrote:

Hi Greg, you’ll need to do something like the following.

#if os(Linux)
    import Glibc
#else
    import Darwin
#endif

Also, take a look at this blog post.
http://blog.krzyzanowskim.com/2015/12/04/swift-package-manager-and-linux-compatible/ Hope
this helps.

Kwame

On Dec 7, 2015, at 10:47 PM, Greg Skluzacek via swift-users < > swift-users@swift.org> wrote:

Hi new to Swift and I am really excited that Apple has open sourced it! I
use macs at home an Linux at work, so now I may actually be able to develop
in one language on both platforms (and not use Java).

That being said, is there a way open a file for either reading line by
line and writing line by line that is done purely in Swift and is cross
platform.

I did go through the Getting Started page and saw that one was able to
import Glibc on Linux which implements the C fopen, etc., but when I tried
to import it in the REPL on OS X, I got the error:

repl.swift:1:8: error: no such module 'Glibc'
import Glibc
       ^

swift --version returns:

Chateau-Louise:/ gskluzacek$ swift --version
Apple Swift version 2.1 (swiftlang-700.1.101.6 clang-700.1.76)
Target: x86_64-apple-darwin14.5.0
Chateau-Louise:/ gskluzacek$

Thanks,
-- Greg
_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


(Brent Royal-Gordon) #4

But at the same time I get your point just use #if #else #endif to conditional import / call functions... but coding like that doesn't seem vary fun... reminds me of looking a C code that was meant to be compiled on different processor architectures. :frowning:

I would really like to see Swift offer a “POSIX” or “LibC” module which would import whatever the current platform offered for a C library. Obviously there would be differences between Glibc and Darwin.C, and I wouldn’t expect Swift to try to paper those over, but this `#if os` dance in every file is kind of ridiculous.

···

--
Brent Royal-Gordon
Architechies


(Chris Lattner) #5

+1

-Chris

···

On Dec 8, 2015, at 8:55 PM, Brent Royal-Gordon via swift-users <swift-users@swift.org> wrote:

But at the same time I get your point just use #if #else #endif to conditional import / call functions... but coding like that doesn't seem vary fun... reminds me of looking a C code that was meant to be compiled on different processor architectures. :-(

I would really like to see Swift offer a “POSIX” or “LibC” module which would import whatever the current platform offered for a C library. Obviously there would be differences between Glibc and Darwin.C, and I wouldn’t expect Swift to try to paper those over, but this `#if os` dance in every file is kind of ridiculous.


(Jens Alfke) #6

File I/O isn’t usually part of a language, it’s part of a library. Until now Swift has been able to depend on the Foundation framework, which includes APIs for files. Taking Swift cross-platform severed it from the Cocoa frameworks, so one of the resulting challenges is to create cross-platform libraries to do basic things like file I/O. Those are in development (the Core Libraries project.)

(Another hole in the standard library is that it’s ridiculously complex to create a String from a UTF-8 encoded byte array without “cheating” and using Foundation’s NSString API.)

—Jens

···

On Dec 8, 2015, at 8:45 PM, Greg Skluzacek via swift-users <swift-users@swift.org> wrote:

One would surely think that a programing language as nifty and cool as Swift would have a easy way to read files. Maybe its obvious and I just am missing it.


(Perry E. Metzger) #7

Going through the SUX (http://www.unix.org/online.html ) and reading
the available APIs will probably be inspirational for what's needed
for a POSIX module, and all sorts of things like sockets with a Swifty
flavor are probably needed in the short term, but a good start would
just be a Swifty version of stdio.

I recommend re-implementing stdio in pure Swift rather than just
wrapping the C library. This will make the swift code immune to safety
bugs in an underlying C implementation, and translating the existing
open source BSD stdio will not be onerous.

This will also require a bit of design to look "Swifty". An IO
interface, for example, so that IO to various kinds of things can all
inherit a common API would be useful. (Imagine, later on, being able
to do things like pushing a TLS library on top of an underlying
socket and having the interface remain entirely clean and unchanged.)

A lower layer is also needed -- simple Swifty wrappers for the Unix
system calls so that Swift implementations can get at them without
having to use unsafe constructs. open(2), read(2), write(2), lseek(2)
and close(2) would provide about 75% of what one needs for the higher
layer stuff (and everything one would want for stdio) with quite
minimal hacking.

Perry

···

On Tue, 8 Dec 2015 21:09:33 -0800 Chris Lattner via swift-users <swift-users@swift.org> wrote:

> On Dec 8, 2015, at 8:55 PM, Brent Royal-Gordon via swift-users > > <swift-users@swift.org> wrote:
>
>> But at the same time I get your point just use #if #else #endif
>> to conditional import / call functions... but coding like that
>> doesn't seem vary fun... reminds me of looking a C code that was
>> meant to be compiled on different processor architectures. :frowning:
>
> I would really like to see Swift offer a "POSIX" or "LibC" module
> which would import whatever the current platform offered for a C
> library. Obviously there would be differences between Glibc and
> Darwin.C, and I wouldn't expect Swift to try to paper those over,
> but this `#if os` dance in every file is kind of ridiculous.

+1

--
Perry E. Metzger perry@piermont.com


(Jens Alfke) #8

This will also require a bit of design to look "Swifty”.

Yes, amen. The thought of a Swift bridge to the standard C library gives me queasy thoughts of PHP, whose core APIs are a horrible pidgin translation of C.

An I/O library should begin with an abstract stream API, which can then be given a concrete file-descriptor-based implementation that can be used for files, sockets, etc. (Although the fact that it’s based on file descriptors should be hidden.)

IMHO one of the biggest design problems of Foundation is that it has very weak support for streams. NSStream is very difficult to subclass, and most I/O doesn’t even use it, so there are historical remnants like NSFileHandle and high-level alternatives like -[NSData initWithContentsOfFile:] that everyone ends up using.

A lower layer is also needed -- simple Swifty wrappers for the Unix
system calls so that Swift implementations can get at them without
having to use unsafe constructs. open(2), read(2), write(2), lseek(2)
and close(2) would provide about 75% of what one needs for the higher
layer stuff (and everything one would want for stdio) with quite
minimal hacking.

I agree, but I foresee problems in the future when Swift is ported to Windows. :confused:

—Jens

···

On Dec 9, 2015, at 6:40 AM, Perry E. Metzger via swift-users <swift-users@swift.org> wrote:


(Perry E. Metzger) #9

I'm a big believer in not prematurely generalizing an implementation.
APIs last a long time, implementations can be redone later. :slight_smile:

···

On Wed, 9 Dec 2015 09:36:01 -0800 Jens Alfke <jens@mooseyard.com> wrote:

> A lower layer is also needed -- simple Swifty wrappers for the
> Unix system calls so that Swift implementations can get at them
> without having to use unsafe constructs. open(2), read(2),
> write(2), lseek(2) and close(2) would provide about 75% of what
> one needs for the higher layer stuff (and everything one would
> want for stdio) with quite minimal hacking.

I agree, but I foresee problems in the future when Swift is ported
to Windows. :confused:

--
Perry E. Metzger perry@piermont.com


(Max Howell) #10

I feel I must point the community at:

https://github.com/apple/swift-package-manager/tree/master/Sources/POSIX

Which is mostly what I think you are calling the lower layer.

···

A lower layer is also needed -- simple Swifty wrappers for the
Unix system calls so that Swift implementations can get at them
without having to use unsafe constructs. open(2), read(2),
write(2), lseek(2) and close(2) would provide about 75% of what
one needs for the higher layer stuff (and everything one would
want for stdio) with quite minimal hacking.

I agree, but I foresee problems in the future when Swift is ported
to Windows. :confused:

I'm a big believer in not prematurely generalizing an implementation.
APIs last a long time, implementations can be redone later. :slight_smile:


(Perry E. Metzger) #11

I feel I must point the community at:

https://github.com/apple/swift-package-manager/tree/master/Sources/POSIX

Which is mostly what I think you are calling the lower layer.

It looks like a start. Some of it (say the unlink routine) is what you
want, but some seems to be too high level, i.e. bindings against
library calls rather than system calls (i.e. things calling in to C
at the fopen/fputs layer rather than the open/write).

One would really like to re-implement the stdio stuff rather than
simply rebinding the C implementation. The implementation of much of
the stuff isn't very deep, and avoiding the potential safety issues
in the C library would be nice. (stdio only looks scary -- it is
mostly just a buffering layer above read(2)/write(2) plus some
formatting.)

Perry

···

On Wed, 09 Dec 2015 10:25:11 -0800 Max Howell <max.howell@apple.com> wrote:

>>> A lower layer is also needed -- simple Swifty wrappers for the
>>> Unix system calls so that Swift implementations can get at them
>>> without having to use unsafe constructs. open(2), read(2),
>>> write(2), lseek(2) and close(2) would provide about 75% of what
>>> one needs for the higher layer stuff (and everything one would
>>> want for stdio) with quite minimal hacking.
>>
>> I agree, but I foresee problems in the future when Swift is
>> ported to Windows. :confused:
>
> I'm a big believer in not prematurely generalizing an
> implementation. APIs last a long time, implementations can be
> redone later. :slight_smile:

--
Perry E. Metzger perry@piermont.com