计算Swift中文件的64位校验和

时间:2015-03-26 15:16:44

标签: objective-c swift nsdata checksum

我正在尝试移植用于计算OpenSubtitles哈希的代码,并且我使用Objective-C示例作为参考(http://trac.opensubtitles.org/projects/opensubtitles/wiki/HashSourceCodes#Objective-C)。哈希的公式是文件大小+文件的前64k的64位校验和+文件的最后64k的64位校验和。

我在计算校验和的代码中遇到了麻烦。这是Objective-C中代码的重要部分:

const NSUInteger CHUNK_SIZE=65536;
NSData *fileDataBegin, *fileDataEnd;
uint64_t hash=0;

fileDataBegin = [handle readDataOfLength:(NSUInteger)CHUNK_SIZE];
[handle seekToEndOfFile];
unsigned long long fileSize = [handle offsetInFile];

uint64_t * data_bytes= (uint64_t*)[fileDataBegin bytes]; 
for( int i=0; i< CHUNK_SIZE/sizeof(uint64_t); i++ )
    hash+=data_bytes[i];

我尝试通过以类似方式重写代码来转换大部分代码ti Swift。我在为这一点找到替换代码时遇到了麻烦:

uint64_t * data_bytes= (uint64_t*)[fileDataBegin bytes]; 
for( int i=0; i< CHUNK_SIZE/sizeof(uint64_t); i++ )
    hash+=data_bytes[i];

任何帮助都会很棒。

1 个答案:

答案 0 :(得分:1)

uint64_t * data_bytes= (uint64_t*)[fileDataBegin bytes]; 

可翻译为

let data_bytes = UnsafeBufferPointer<UInt64>(
                    start: UnsafePointer(fileDataBegin.bytes),
                    count: fileDataBegin.length/sizeof(UInt64)
                )

具有data_bytes不仅仅具有额外优势 一个指针,但也存储元素的数量。一个 UnsafeBufferPointer几乎可以像Swift Array一样对待。

因此

for( int i=0; i< CHUNK_SIZE/sizeof(uint64_t); i++ )
    hash+=data_bytes[i];

可以简单地写成

var hash : UInt64 = 0
// ...
hash = reduce(data_bytes, hash) { $0 &+ $1 }
使用

/// Return the result of repeatedly calling `combine` with an
/// accumulated value initialized to `initial` and each element of
/// `sequence`, in turn.
func reduce<S : SequenceType, U>(sequence: S, initial: U, combine: (U, S.Generator.Element) -> U) -> U

"overflow operator" &+

  

与C中的算术运算符不同,Swift中的算术运算符不相同   默认溢出。溢出行为被捕获并报告为   错误。要选择溢出行为,请使用Swift的第二组   默认情况下溢出的算术运算符,例如溢出   加法运算符(&amp; +)。所有这些溢出运算符都以a开头   &符号(&amp;)。