Bagusflyer
Bagusflyer

Reputation: 12925

Read bytes into a Swift String

I have a binary file test.data containing the following data:

01 E6 B5 8B E8 AF 95 02

The first byte is just for example a sequence number 01. The next 6 bytes are two UTF8 Chinese characters "测试".Then the 8th byte is again another sequence number 02.

As I know the UTF8 is variable length (1-4 bytes). Please refer to this post.

I'm using the following code to read Int32 and Byte(UInt8):

extension NSInputStream
{
    func readInt32() -> Int
    {
        var readBuffer = Array<UInt8>(count:sizeof(Int32), repeatedValue: 0)

        var numberOfBytesRead = self.read(&readBuffer, maxLength: readBuffer.count)

        return Int(readBuffer[0]) << 24 |
            Int(readBuffer[1]) << 16 |
            Int(readBuffer[2]) << 8 |
            Int(readBuffer[3])
    }

    func readByte() -> Byte {

        var readBuffer : Byte = 0
        return self.read(&readBuffer, maxLength: sizeof(UInt8))
    }

I'd like to write a method to read Strings from the stream. Here is what I'm thinking:

But the problem is how many bytes to read for a Character because the UTF8 length is variant? In general my question is how I'm supposed to read UTF8 String? Thanks in advance.

Upvotes: 1

Views: 7189

Answers (2)

Vivien Sonntag
Vivien Sonntag

Reputation: 4629

Here is the fixed version I mentioned in my comment to bagusflyer's post :

extension NSInputStream
{
  public func readString(length:Int) -> String {

    var str = ""

    if length > 0 {
        var readBuffer = UnsafeMutablePointer<UInt8>.alloc(length+1)

        var numberOfBytesRead = self.read(readBuffer, maxLength: length)
        // modified this from == length to > 0
        if numberOfBytesRead > 0 {

            var buf = UnsafeMutablePointer<CChar>(readBuffer)
            buf[numberOfBytesRead] = 0
            // the C String must be null terminated
            if let utf8String = String.fromCString(buf) {
                str = utf8String
            }
        }
        readBuffer.dealloc(length+1)
    }
    return str

  }
}

Upvotes: 4

user3847549
user3847549

Reputation:

Just read to UnsafeMutablePointer buffer and convert it to a String. The returned String will be UTF8.

extension NSInputStream
{
    public func readString(length:Int) -> String {

        var str = ""

        if length > 0 {
            var readBuffer = UnsafeMutablePointer<UInt8>.alloc(length+1)

            var numberOfBytesRead = self.read(readBuffer, maxLength: length)
            if numberOfBytesRead == length {

                var buf = UnsafeMutablePointer<CChar>(readBuffer)
                buf[length] = 0
                // the C String must be null terminated
                if let utf8String = String.fromCString(buf) {
                    str = utf8String
                }
            }
            readBuffer.dealloc(length)
        }
        return str

    }
}

Upvotes: 4

Related Questions