我需要更改文檔文件夾中文件的標頭信息。 什麼是讀取和寫回二進制數據最值得推薦的方式?更改標頭信息二進制並將其寫回
- 如何從文件夾的二進制數據讀取到陣列/流
- 如何將數據寫入從Array /流本地iPad的文件夾回?
我需要更改文檔文件夾中文件的標頭信息。 什麼是讀取和寫回二進制數據最值得推薦的方式?更改標頭信息二進制並將其寫回
這一個是硬而你沒有更具體一點回答,但最有效的方法來做到這一點可以說是根本不改變文件。
由於我們在談論iOS,除了應用程序本身之外,沒有文件系統級訪問這些文檔的權限。那麼,爲什麼不保存在應用程序範圍內的元數據存儲(如iTunes或iPhoto)中與您的文件關聯的附加/自定義標題數據,並在導出期間將它們與實際文件標題進行交織?
無論如何,我真的沒有看到一個令人信服的理由,下降到C級文件功能來更改這些數據:NSInputStream
爲您提供流式文件讀取訪問和NSOutputStream
可用於流數據到一份文件。
如果你用我的建議去從上面你很可能像這樣的API結束:
typedef void (^DataExportHandler)(NSData *resultData, NSError *exportError);
@interface DataStore (FileExport)
/** If you wanted to abort the export, you could pass the stream into the `abort…:`-method
@param identifier Something that you use internally to manage your stored files.
@param error For good measure…
@return The export stream for the object or `nil` if an error occurred.
*/
- (NSInputStream *)exportStreamForObjectWithIdentifier:(id)identifier error:(NSError * __autoreleasing*)error;
/** If your data are mostly small, it may be more convenient to not consume the exports as streams but as BLOBs, if the sizes vary you could implement this as a convenience…
@param identifier Equivalent to the identifier in the method above
@param handler Callback that is invoked once some time later when the export finished or failed. **Must not** be `nil`.
*/
@return A cancellation token.
- (id)asynchronouslyExportDataForObjectWithIdentifier:(id)identifier resultHandler:(DataExportHandler)handler;
/**
@param exportToken Either a stream from the first method or a token returned from the second one.
*/
- (void)abortAsynchronousExportWithToken:(id)exportToken;
@end
假設ARC,不知道你必須做與原來的交錯額外的元數據是什麼,這裏是實現的樣板部分可能是的樣子。
牛肉顯然在我沒有在這裏展示的部分:執行rawDataStream
的代理,您將從原始文件中消耗數據,將標頭與附加信息交錯。 雖然這可能應該被分解成一個單獨的類,但我暗示數據存儲相應地實現了NSStreamDelegate
回調。
你只是通過文件的其餘部分頭後...
/// Scribble of another helper class that can be used whenever one needs to consume a stream for its aggregate data:
@interface _StreamConsumer : NSObject <NSStreamDelegate> {
NSInputStream *_stream;
DataExportHandler _handler;
NSMutableData *_data;
}
// initiate the data, set itself as the stream’s delegate, open and schedule the stream in a runloop.
- (id)initWithInputStream:(NSInputStream *)stream resultHandler:(DataExportHandler)handler;
// forward the close to the stream
- (void)close;
// Implementation of the stream delegate callbacks can be more or less copy-pasted from Apple’s Stream Programming Guide (https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Streams/Streams.html)
@end
@implementation DataStore (FileExport)
- (id)asynchronouslyExportDataForObjectWithIdentifier:(id)someUniqueIdentifier resultHandler:(void (^)(NSData *fileData, NSError *exportError))
{
NSParameterAssert(handler);
handler = [handler copy];
NSError *setupError;
NSInputStream *exportStream = [self exportStreamForObjectWithIdentifier:someUniqueIdentifier error:&setupError];
if (!exportStream)
{
dispatch_async(dispatch_get_current_queue(), ^{
handler(nil, setupError);
});
return nil;
}
_StreamConsumer *helper = [[_StreamConsumer alloc] initWithStream:exportStream resultHandler:handler];
return helper;
}
- (void)abortAsynchronousExportWithToken:(id)exportToken
{
[exportToken close];
}
- (NSInputStream *)exportStreamForObjectWithIdentifier:(id)identifier error:(NSError * __autoreleasing*)error
{
// do your thing to retrieve the URL to the actual data-file and then:
NSInputStream *rawDataStream = [NSInputStream inputStreamWithURL:rawFileURL];
if (!rawDataStream)
{
// populate the error in a meaningful way
return nil;
}
CFReadStream cfExportStream;
CFWriteStream cfBuffer;
CFStreamCreateBoundPair(kCFAllocatorDefault, &cfExportStream, &cfBuffer, someValueYouHaveTuned);
if (!cfExportStream || !cfBuffer)
{
// error population
return nil;
}
NSInputStream *exportStream = (__bridge_transfer NSInputStream *)cfExportStream;
// HACKITY HACK: In reality, you’d want this stuff separated!
// For the sake of simplicity, take the responsibility for that ourselves
_exportBuffer = (__bridge_transfer NSOutputStream *)cfBuffer;
rawDataStream.delegate = self;
[rawDataStream open];
[rawDataStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunloopDefaultMode];
// END: HACKITY HACK
return exportStream;
}
@end
主束是隻讀的,你不能寫有什麼。
對於寫作我們有文檔目錄。
這將從主束
NSString *path= [[NSBundle mainBundle] pathForResource:@"myFile" ofType:@"txt"];
編輯
讀取文件當你表現出你的頭是從1到10個字節..
你能告訴我一個覺得怎麼一個誰正在讀取您的文件知道什麼是您的標題的確切長度。它可以是2到3或7到1到10之間的任何值。必須有一種方法來告訴它它具有特定長度的標題,文件的其他部分也是如此。
沒有這個信息,我不認爲人會知道您的標題,身體或頁腳的大小。
如果我已經創建了這個文件,我可能會將頭的第一個字節作爲頭的長度,這樣任何人都可以讀取頭,並在讀取頭之後的第一個字節之後,爲主體的大小做出相同的處理。
Ç流是很容易:FILE*
,fopen
,fseeko
,fread
,fwrite
。
如果你的數據的只是266個字節,這是足夠小,你可以閱讀所有使用[NSMutableData dataWithContentsOfURL:url]
,然後將它寫回用NSData
的write*
方法(覆蓋整個文件)。但是,您將希望避免使用較大文件的方法。在這一點上,你會想用C接口(上圖),或考慮NSFileHandle
,NSInputStream
,NSOutputStream
,CFReadStream
,CFWriteStream
等。
嗨。感謝你的回答。也許你可以顯示在哪裏寫入樣本,以11開頭的索引讀取字節?直到讀到字節索引255? – Nasenbaer