I need to read elevation data from a binary .hgt file in Swift. I have found this result for c, but I can not migrate it to Swift.
#include <stdio.h>
#define SIZE 1201
signed short int matrix[SIZE][SIZE] = {0};
int main(int argc, const char * argv[])
{
FILE *fp = fopen("N49E013.hgt", "rb");
unsigned char buffer[2];
for (int i = 0; i < SIZE; ++i)
{
for (int j = 0; j < SIZE; ++j)
{
if (fread(buffer, sizeof(buffer), 1, fp) != 1)
{
printf("Error reading file!\n");
system("PAUSE");
return -1;
}
matrix[i][j] = (buffer[0] << 8) | buffer[1];
}
}
fclose(fp);
}
#define SIZE 1201
This defines a constant named 'SIZE', so do that:
let size = 1201
next:
FILE *fp = fopen("N49E013.hgt", "rb");
This opens a file for reading. We can do that. Close the file in a 'defer' block, so that no matter what, the file gets closed when we're done.
// change the path below to the correct path
let handle = try FileHandle(forReadingFrom: URL(fileURLWithPath: "/path/to/N49E013.hgt"))
defer { handle.closeFile() }
Now, to construct the matrix. We want to create size
number of arrays, each of which has size
elements, read from the file. The original used two nested for loops, but Swift supports functional programming constructs, which we can use to do this a bit more elegantly:
let matrix = try (0..<size).map { _ in
try (0..<size).map { _ -> Int in
// Unfortunately, FileHandle doesn't have any decent error-reporting mechanism
// other than Objective-C exceptions.
// If you need to catch errors, you can use fread as in the original,
// or use an Objective-C wrapper to catch the exceptions.
let data = handle.readData(ofLength: 2)
if data.count < 2 { throw CocoaError(.fileReadCorruptFile) }
return (Int(data[0]) << 8) | Int(data[1])
}
}
Think that ought to do it.