Search code examples
iosutf-8swiftnsinputstream

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:

  • Read bytes (assume I know how many bytes to read)
  • Conver the bytes to Character
  • Append the Character into String

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.


Solution

  • 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
    
        }
    }