Skip to content
Advertisement

ByteArrayOutputStream or Binary Writer equivalent in Swift

I wondering equivalent of Java java.io.ByteArrayOutputStream or C#’s BinaryWriter into Swift.

Having some difficulties in the following static public class CustomArrayOutputStream extends java.io.ByteArrayOutputStream part. I wonder how to achieve the same functionalities in the Swift.

Swift Code

public class CustomSerializer {
   fileprivate var output: CustomArrayOutputStream

   func custom_bool(value: Bool) {
      output.write(value == true ? 1 : 0)
   }
}

// Having difficulties to convert it to Swift
static public class CustomArrayOutputStream : ?? {
    public func getBuffer() -> [UInt8] {
        return buf
    }
}

Java Code:

public class CustomSerializer {
   protected CustomArrayOutputStream output;

   public void custom_bool(Boolean value) {
      output.write(value.booleanValue() ? 1: 0);
   }
}

static public class CustomArrayOutputStream extends java.io.ByteArrayOutputStream {
    public byte[] getBuffer() {
        return buf;
    }
}

or equivalent of C# BinaryWriter in Swift

protected readonly BinaryWriter output;

Update:

The first case is to achieve something similar

var content:[UInt8] = output.getBuffer() 
var size: Int = output.size() 

but OutputStream does not have getBuffer() and size() do not exist.

or

the second use case, do not know how to convert the following Java into Swift

Java

public int getOffset() {
    return (int)output.BaseStream.Position;
}

Swift

public func getOffset() -> Int {
    return output.???
}

Advertisement

Answer

For the methods you’re asking for, you could do a very simple implementation using OutputStream, something like this; (have mercy on the code style, I’m rather new at Swift myself)

If you need something more high performance, maybe getting the data to check the offset isn’t the best idea, you may want to extend OutputStream to count bytes as you write instead.

import Foundation

public class CustomSerializer {
    fileprivate var output = OutputStream.toMemory()

    init() {
        output.open()
    }

    deinit {
        output.close()
    }
    
    func custom_bool(value: Bool) -> Void {
        custom_write(value: UInt8(value ? 1 : 0))
    }

    func custom_int(value: Int32) -> Void {
        custom_write(value: value.bigEndian)
    }

    private func custom_write<T>(value: T) -> Void {
        var value = value
        let size = MemoryLayout.size(ofValue: value)
        withUnsafeBytes(of: &value) {
            ptr in
            output.write(ptr.baseAddress!.assumingMemoryBound(to: UInt8.self), maxLength: size)
        }
    }
 }

extension OutputStream {
    public func getBuffer() -> [UInt8] {
        return [UInt8](self.property(forKey: .dataWrittenToMemoryStreamKey) as! Data)
    }
    public func getOffset() -> Int {
        return (self.property(forKey: .dataWrittenToMemoryStreamKey) as! Data).count
    }
}

let test = CustomSerializer()
test.custom_bool(value: true)
test.custom_int(value: 4711)
print(test.output.getBuffer())  // [1, 0, 0, 18, 103]
print(test.output.getOffset()). // 5
Advertisement