Last active
April 15, 2022 03:47
-
-
Save reitzig/29d38b948812454a8dedc00a9f61f44f to your computer and use it in GitHub Desktop.
Reading InputStream into Data
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extension Data { | |
/** | |
Consumes the specified input stream, creating a new Data object | |
with its content. | |
- Parameter reading: The input stream to read data from. | |
- Note: Closes the specified stream. | |
*/ | |
init(reading input: InputStream) { | |
self.init() | |
input.open() | |
let bufferSize = 1024 | |
let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: bufferSize) | |
while input.hasBytesAvailable { | |
let read = input.read(buffer, maxLength: bufferSize) | |
self.append(buffer, count: read) | |
} | |
buffer.deallocate() | |
input.close() | |
} | |
/** | |
Consumes the specified input stream for up to `byteCount` bytes, | |
creating a new Data object with its content. | |
- Parameter reading: The input stream to read data from. | |
- Parameter byteCount: The maximum number of bytes to read from `reading`. | |
- Note: Does _not_ close the specified stream. | |
*/ | |
init(reading input: InputStream, for byteCount: Int) { | |
self.init() | |
input.open() | |
let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: byteCount) | |
let read = input.read(buffer, maxLength: byteCount) | |
self.append(buffer, count: read) | |
buffer.deallocate() | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import XCTest | |
class DataTests: XCTestCase { | |
func testInitFromStream() { | |
// Tests some random values, plus the empty case | |
[[UInt8](), | |
[0b00001001], | |
[0b01000000, 0b01001011], | |
[0b01011110, 0b11101111, 0b00011001], | |
[0b01101100, 0b00101010, 0b10111001, 0b10000111], | |
[0b00011011, 0b00010111, 0b00011000, 0b01100100, 0b10110000], | |
[UInt8](repeating: 77, count: 2049) // something large; 2*buffersize + 1 | |
].forEach { (bytes) in | |
let referenceData = Data(bytes) | |
let stream = InputStream(data: referenceData) | |
XCTAssertEqual(Data(reading: stream), referenceData) | |
} | |
} | |
func testInitFromStreamWithMaxLength() { | |
// Tests some random values, plus the empty case | |
[[UInt8](), | |
[0b00001001], | |
[0b01000000, 0b01001011], | |
[0b01011110, 0b11101111, 0b00011001], | |
[0b01101100, 0b00101010, 0b10111001, 0b10000111] | |
].forEach { (bytes) in | |
let referenceData = Data(bytes) | |
let stream = InputStream(data: referenceData) | |
defer { stream.close() } | |
XCTAssertEqual( | |
Data(reading: stream, for: 3), | |
referenceData[0..<(min(3, referenceData.count))] | |
) | |
} | |
} | |
} |
Sorry, I completely missed your comment! Do we not get notifications here?
Did you solve the issue? I'm not sure I understand fully what the problem is; I'd recommend you open a question on Stack Overflow!
That said, I don't think the function I've written is suitable for reading from streams that are "slow". At least I never tried it on such.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Does buffer.deallocate() clear/flush the buffer? Below is an example of the function I have that needs to read from the stream. The stream is receiving data every 1 or 2 seconds. The data is an integer data type. However, if I don't read from the stream after each update, the buffer is overwritten. I am working on a project and can't seem to find an efficient way to simply clear the buffer after each read.
` // Function: readMessage - read a message from the stream (1 integer value)
}`