Asynchronously iterating line-by-line through a file
Asked Answered
L

2

9

In the "Platforms State of the Union" video of WWDC2021 at 28:00 it was mentioned that

[Apple] even added support for asynchronously iterating line-by-line through a file

in Foundation for macOS 12/iOS 15 and Swift 5.5.

What is that new API, how can I now asynchronously iterate line-by-line through a file?

Landsturm answered 10/6, 2021 at 11:16 Comment(7)
developer.apple.com/videos/play/wwdc2021/10132 ?Martinet
@Martinet Already watched that, there wasn't any mention of the API I'm looking for.Landsturm
or developer.apple.com/videos/play/wwdc2021/101 (at 1:38)? Its await/async? It's not really an API, it's in the language I'd say. And the related topic on the previous link: github.com/apple/swift-evolution/blob/main/proposals/… github.com/apple/swift-evolution/blob/main/proposals/… etc. ?Martinet
Pretty sure it's an API, since in context they mentioned other APIs before that. But I'd also welcome an answer explaining how to do this yourself with async/awaitLandsturm
Are you talking about this?Witchcraft
@Witchcraft Maybe? Seems a bit like it, but that's just for URLSession. I would have expected something for FileHandle, String and/or Data so it can be used for local files.Landsturm
@Landsturm There is one for FileHandle too, but in the documentation it is stated that it is recommended to use the URLSession version instead.Witchcraft
W
13

The main thing they added that enables this, is AsyncSequence. AsyncSequence is like Sequence, but its Iterator.next method is async throws.

Specifically, you can use URLSession.AsyncBytes.lines to get an AsyncSequence of the lines in a file.

Suppose you are in an async throws method, you can do:

let (bytes, response) = try await URLSession.shared.bytes(from: URL(string: "file://...")!)
for try await line in bytes.lines {
    // do something...
}

Note that there is also FileHandle.AsyncBytes.lines, but in the documentation it says:

Rather than creating a FileHandle to read a file asynchronously, you can instead use a file:// URL in combination with the async-await methods in URLSession. These include the bytes(for:delegate:) and bytes(from:delegate:) methods that deliver an asynchronous sequence of bytes, and data(for:delegate:) and data(from:delegate:) to return the file’s entire contents at once.

Witchcraft answered 10/6, 2021 at 11:47 Comment(1)
This is unavailable on linux, anybody knows an alternative?Mammillary
F
3

The URL struct has a variable that returns the destination asynchronously and line-by-line which you can iterate on like:

for try await line in URL(string: pathToFile)!.lines { print(line) }
Frag answered 12/2 at 13:41 Comment(3)
does anyone knows how to cancel an on going iteration ?Titanic
@lorenzogonzalez just return from the for-loopFrag
thanks! lol.. cant believe i did ask for this ...Titanic

© 2022 - 2024 — McMap. All rights reserved.