如何在Swift中从文件(而不是整个文件)读取数据块
假设我有一个8字节长的文件,只包含ASCII字符:如何在Swift中从文件(而不是整个文件)读取数据块,swift,Swift,假设我有一个8字节长的文件,只包含ASCII字符:brownfox 我不想加载整个文件并处理if,而是想加载2字节的块[UInt8]并对2字节大小的块进行操作,因此操作如下: 从文件(而不是整个文件)加载br 对数据执行任何操作,例如反转到rb 将输出保存到另一个文件 重复以下步骤:ownfox 其背后的原因是: 这样,如果我处理的文件是1GB的文本,我实际上不必有1GB的RAM空闲(或2GB的输入和输出文件) 这种文件处理方法对于加密和发送到云解决方案对我来说很重要 我正在使用此扩展: 扩展数
brownfox
我不想加载整个文件并处理if,而是想加载2字节的块[UInt8]
并对2字节大小的块进行操作,因此操作如下:
br
rb
ow
nf
ox
扩展数据{
/**
使用指定的输入流,创建新的数据对象
与它的内容。
-参数读取:从中读取数据的输入流。
-注意:关闭指定的流。
*/
初始化(读取输入:InputStream){
self.init()
input.open()
让bufferSize=1024
let buffer=unsafemeutablepointer.allocate(容量:bufferSize)
当input.hasbytes可用时{
让read=input.read(缓冲区,maxLength:bufferSize)
self.append(缓冲区,计数:读取)
}
buffer.deallocate()
input.close()
}
/**
将指定的输入流消耗最多'byteCount'字节,
创建包含其内容的新数据对象。
-参数读取:从中读取数据的输入流。
-参数byteCount:从“reading”读取的最大字节数。
-注意:不关闭指定的流。
*/
init(读取输入:InputStream,字节数为:Int){
self.init()
input.open()
let buffer=unsafemeutablepointer.allocate(容量:字节数)
let read=input.read(缓冲区,maxLength:byteCount)
self.append(缓冲区,计数:读取)
buffer.deallocate()
}
}
但是init(读取输入:InputStream,字节数:Int)
总是从第一个字节开始。例如,如何读取16到20字节
关于InputStream.read(\uux:maxLength:)
从当前读取索引中,最多占用指定的字节数
在流的第二个参数中,并将它们放置在
客户端提供的缓冲区(第一个参数)。缓冲区必须是
由第二个参数指定的大小。返回实际的
放入缓冲区的字节;如果小溪里什么都没有了,
返回0。将索引重置到流中以进行下一次读取操作
如何才能不重置索引,并从上一个操作结束的位置获取下一个操作?使用
文件句柄。您可以打开文件句柄进行读取。然后使用seek(toFileOffset:)
设置要从中读取的位置。然后使用readData(长度:)
获取一些数据。完成后请确保关闭文件句柄。rmaddy的解决方案有效
这里有一个非常粗略的片段,供任何带着同样问题来到这里的人参考。这不是一个确切的答案,但它显示了需要做的一切:)
func加载块(路径:字符串)->[数据]{
变量块=[数据]()
让correctPath=//文件的路径
让fileHandle=fileHandle(用于读取路径:correctPath)
让dataFromFirstByteTo4thByte=fileHandle!.readData(长度:4)
blocks.append(数据从第一字节到第四字节)
文件句柄?.seek(toFileOffset:4)
让dataFrom5thByteTo8thByte=fileHandle!.readData(长度:4)
blocks.append(数据从5thbyteto8thbyte)
fileHandle?.closeFile()文件
返回块
}
以及实际用途:
func加载块(编号:Int,withBlockSize大小:Int,路径:String)抛出->数据{
让correctPath=path.replacingOccurrences(of:“file://”,with:).replacingOccurrences(of:“%20”,with:”)
guard let fileHandle=fileHandle(forReadingAtPath:correctPath)else{throw NSError()}
let bytesOffset=UInt64((数字-1)*大小)
查找(toFileOffset:bytesOffset)
let data=fileHandle.readData(of长度:大小)
fileHandle.closeFile()文件
返回数据
}
我很确定您不需要调用seek
,因为readData
移动了文件指针,您的下一次读取就到此为止。您还应该重新检查对nil
的处理。您可以同时使用代码>和文件句柄上的和?
。在这种情况下两者都不理想,但至少要保持一致。上面的代码只是概念的证明。实际代码解决了这个问题:)我做了一个编辑来展示它的样子。而且,是的,我知道,我可以做得比抛出一个通用的n错误更好