File 在Swift中,如何将现有的二进制文件读入数组?

File 在Swift中,如何将现有的二进制文件读入数组?,file,swift,io,binary,File,Swift,Io,Binary,作为我项目的一部分,我有一个二进制数据文件,由一大系列的32位整数组成,我的一个类在初始化时读取这些整数。在我的C++库中,我用下面的初始化器读取它: Evaluator::Evaluator() { m_HandNumbers.resize(32487834); ifstream inputReader; inputReader.open("/path/to/file/7CHands.dat", ios::binary); int inputValue;

作为我项目的一部分,我有一个二进制数据文件,由一大系列的32位整数组成,我的一个类在初始化时读取这些整数。在我的C++库中,我用下面的初始化器读取它:

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();
};
当我调试它时,它工作得很好,我可以看到inputBuffer包含我的十六进制编辑器所说的相同的字节数组。现在,我想有效地从那里获取数据。我知道它储存在。。无论您将其称为何种格式,其中最低有效字节位于第一位(即,数字0x00011D4A在文件中表示为“4A1D 0100”)。我很想手动迭代并手动计算字节值,但我想知道是否有一种快速方法可以传递[Int32]数组并让它读取这些字节。我尝试使用NSData,例如:

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

但这似乎没有加载值(所有值仍然为零)。有人能帮我把这个字节数组转换成一些Int32值吗?更好的做法是将它们转换为Int(即64位整数),以便在整个项目中保持变量大小相同。

不确定您的endian值,但我使用以下函数。与代码的不同之处在于使用实际所需类型的
NSRanges
,而不是字节长度。此例程一次读取一个值(用于内容随字段而变化的ESRI文件),但应易于调整

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
}

Grimxn为我的问题提供了解决方案的主干,它向我展示了如何将缓冲区的各个部分读入数组;然后,他向我展示了一种一次读取整个缓冲区的方法。我没有将数组的所有项不必要地转换为
Int
,而是将数组作为UInt32读入缓冲区,并在访问该数组的函数中转换为
Int

现在,由于我还没有定义我的实用程序类,我将Grimxn的代码直接集成到我的初始值设定项中。类初始值设定项现在如下所示:

public class Evaluator {
    let HandNumberArraySize = 32487834

    var handNumbers: [Int32]

    public init() {
        let data = NSData(contentsOfFile: "/path/to/file/7CHands.dat")!
        var dataRange = NSRange(location: 0, length: HandNumberArraySize * 4)
        handNumbers = [Int32](count: HandNumberArraySize, repeatedValue: 0)
        data.getBytes(&handNumbers, range: dataRange)

        println("Evaluator loaded successfully")
    }

...

}
。。。引用它们的函数现在是:

public func cardVectorToHandNumber(#cards: [Int], numberToUse: Int) -> Int {
    var output: Int

    output = Int(handNumbers[53 + cards[0] + 1])

    for i in 1 ..< numberToUse {
        output = Int(handNumbers[output + cards[i] + 1])
    }

    return Int(handNumbers[output])
}
public func cardVectorHandNumber(#cards:[Int],numberToUse:Int)->Int{
变量输出:Int
输出=整数(手机号码[53+卡[0]+1])
对于1中的i..

感谢Grimxn,再次感谢StackOverflow以非常真实的方式帮助我

我试着用那个函数,结果只得到了零。我认为data.getBytes语句没有正确地从输入缓冲区加载数据。你的功能可能很好,但我现在不知道。如果我知道inputBuffer包含非零,那么你知道为什么我的data.getBytes语句不工作吗?
data.getBytes(&inputBuffer…
读取
数据
并将其放入
inputBuffer
,而不是相反。您需要将文件读入
NSData
中,然后将其读入正确大小的整数数组。基于此,我实际上简化了使用数据文件路径初始化数据的过程,即:
let data=NSData(contentsOfFile:“/path/to/file/7CHands.dat”)而且它看起来就像一种魅力,加载数据,然后简单地调用你的函数(事实证明是littleEndian),一切都是船形的。然而,这确实需要很长时间。。即使在发布构建中,安装也需要90秒左右,而C++是即时的。这两种语言之间的差异真的有那么大吗?还是我在某个地方遗漏了一个构建设置?你是一次只做一个值吗?将我的例程更改为返回
[UInt32]
而不是
Int
,然后传入值的计数,将
length:4
修改为
length:4*count
并将
count:1
修改为
count:count
,然后返回
i
而不是
i[0]
。。。这将大大加快速度…是的,这带来了很大的不同。在释放模式下为瞬时,在调试模式下为1s。我甚至可以读取整个数组并将其存储为“[Int32]”,并在执行查找值时根据需要将其转换为Int。非常感谢!伟大的检查引用函数的下标协议。这不是必要的,但可能会让事情变得更整洁。。。
public func cardVectorToHandNumber(#cards: [Int], numberToUse: Int) -> Int {
    var output: Int

    output = Int(handNumbers[53 + cards[0] + 1])

    for i in 1 ..< numberToUse {
        output = Int(handNumbers[output + cards[i] + 1])
    }

    return Int(handNumbers[output])
}