Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Swift, how do I read an existing binary file into an array?

As part of my projects, I have a binary data file consisting of a large series of 32 bit integers that one of my classes reads in on initialization. In my C++ library, I read it in with the following initializer:

Evaluator::Evaluator() {
    m_HandNumbers.resize(32487834);
    ifstream inputReader;

    inputReader.open("/path/to/file/7CHands.dat", ios::binary);

    int inputValue;
    for (int x = 0; x < 32487834; ++x) {
        inputReader.read((char *) &inputValue, sizeof (inputValue));
        m_HandNumbers[x] = inputValue;
    }
    inputReader.close();
};

and in porting to Swift, I decided to read the entire file into one buffer (it's only about 130 MB) and then copy the bytes out of the buffer.

So, I've done the following:

public init() {
    var inputStream = NSInputStream(fileAtPath: "/path/to/file/7CHands.dat")!
    var inputBuffer = [UInt8](count: 32478734 * 4, repeatedValue: 0)
    inputStream.open()
    inputStream.read(&inputBuffer, maxLength: inputBuffer.count)
    inputStream.close()
}

and it works fine in that when I debug it, I can see inputBuffer contains the same array of bytes that my hex editor says it should. Now, I'd like to get that data out of there effectively. I know it's stored in.. whatever format you call it where the least significant bytes are first (i.e. the number 0x00011D4A is represented as '4A1D 0100' in the file). I'm tempted to just iterate through it manually and calculate the byte values by hand, but I'm wondering if there's a quick way I can pass an array of [Int32] and have it read those bytes in. I tried using NSData, such as with:

    let data = NSData(bytes: handNumbers, length: handNumbers.count * sizeof(Int32))
    data.getBytes(&inputBuffer, length: inputBuffer.count)

but that didn't seem to load the values (all the values were still zero). Can anyone please help me convert this byte array into some Int32 values? Better yet would be to convert them to Int (i.e. 64 bit integer) just to keep my variable sizes the same across the project.

like image 922
Charles Avatar asked Mar 11 '15 16:03

Charles


People also ask

Which method is used to read data from a binary file?

The BinaryReader class is used to read binary data from a file. A BinaryReader object is created by passing a FileStream object to its constructor.

How binary data and text content are downloaded?

Binary (or unstructured text) files can be downloaded using a GET, POST or PUT HTTP Method as a response.

How do I read a binary file on a Mac?

To decode a MacBinary document in Mac OS, Mac OS X, or Windows, use StuffIt Expander. Simply drag and drop the file onto the StuffIt Expander icon and it will decode the file. When necessary, it will also decompress the file into a usable form.


1 Answers

Not sure about your endian-ness, but I use the following function. The difference from your code is using NSRanges of the actual required type, rather than lengths of bytes. This routine reads one value at a time (it's for ESRI files whose contents vary field by field), but should be easily adaptable.

func getBigIntFromData(data: NSData, offset: Int) -> Int {
    var rng = NSRange(location: offset, length: 4)
    var i = [UInt32](count: 1, repeatedValue:0)

    data.getBytes(&i, range: rng)
    return Int(i[0].bigEndian)// return Int(i[0]) for littleEndian
}
like image 174
Grimxn Avatar answered Sep 29 '22 08:09

Grimxn