2012-04-29 2 views
8

Я пишу текстовый редактор, и мне нужно будет хранить несколько фрагментов информации (как правило, всего несколько строк, а хранение не обязательно должно быть особенно долговечным) с каждым файлом приложение сохраняет (без того, чтобы быть частью текстового файла, поскольку другие приложения могли его прочитать, а информация касается только моего приложения).Сохранение произвольных метаданных с текстовым файлом

Как бы я это сделал?


Дополнительная информация: У меня есть NSDocument настроить, и я хотел бы просто хранить переменную экземпляра NSString как в файле мета-данности. Исходя из ответов ниже я пришел с этим, что в настоящее время глючит и вызывает программу к сбою при запуске:

#import <sys/xattr.h> 
@interface MyDocument : NSDocument { 
    NSString *metadatum; 
} 

@implementation MyDocument 

- (BOOL)writeToURL:(NSURL *)url ofType:(NSString *)type error:(NSError **)err 
{ 
    BOOL output = [super writeToURL:url ofType:type error:err]; 
    if(!setxattr([[url path] cStringUsingEncoding:NSUTF8StringEncoding], 
       "eu.gampleman.xattrs.style", 
       [metadatum cStringUsingEncoding:NSUTF8StringEncoding], 
       sizeof(char) * [styleName length], 0, 0)) 
    { 
     NSLog(@"Write failure"); 
    } 
    return output; 
} 

- (BOOL)readFromURL:(NSURL *)url ofType:(NSString *)type error:(NSError **)err { 
    char *output; 
    ssize_t bytes = getxattr([[url path] cStringUsingEncoding:NSUTF8StringEncoding], 
          "eu.gampleman.xattrs.style", &output, 1024, 0, 0); 
    if (bytes > 0) { 
    metadatum = [[NSString alloc] initWithBytes:output length:bytes 
      encoding:NSUTF8StringEncoding]; // <- crashes here with "EXC_BAD_ACCESS" 
    } 
    return [super readFromURL:url ofType:type error: err]; 
} 

// ... 
// fairly standard -dataOfType:error: and 
// -readFromData:ofType:error: implementations 

PS: Если ваш ответ действительно хорош (с примерами кода, и т.д. .), Я награду 100-кратной наградой.

+2

Используйте '- [NSString fileSystemRepresentation]' вместо '-cStringUsingEncoding:'. Длина 'NSString' находится в символах UTF-16, которая не совпадает с длиной символов UTF-8 (за исключением чистого ASCII). Вызов 'getxattr()' передает указатель на указатель, который содержит 4 или 8 байтов памяти, но говорит, что это 1024 байта. Вероятно, вы повредили стек или кучу. Вы должны выделить хранилище нужного размера. –

ответ

13

Используйте расширенные атрибуты. См. setxattr().

Вот пример вызова написать строку:

NSData* encodedString = [theString dataUsingEncoding:NSUTF8StringEncoding]; 
int rc = setxattr("/path/to/your/file", "com.yourcompany.yourapp.yourattributename", [encodedString bytes], [encodedString length], 0, 0); 
if (rc) 
    /* handle error */; 

Чтобы прочитать строку:

ssize_t len = getxattr("/path/to/your/file", "com.yourcompany.yourapp.yourattributename", NULL, 0, 0, 0); 
if (len < 0) 
    /* handle error */; 
NSMutableData* data = [NSMutableData dataWithLength:len]; 
len = getxattr("/path/to/your/file", "com.yourcompany.yourapp.yourattributename", [data mutableBytes], len, 0, 0); 
NSString* string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 

PS: Вы не должны установить Баунти на вопрос, прежде чем он ответил?

+0

Не совсем, я могу установить его позже (хотя я должен ждать два дня, чтобы это сделать). Также спасибо за ссылку, любые примеры того, как я могу ее использовать (читать, писать)? –

+0

В нижней части связанной страницы man есть ссылки на 'getxattr()', 'listxattr()' и 'removexattr()'. –

+0

Обновленный ответ с тривиальным примером установки атрибута. Если вы хотите больше деталей, вам нужно больше объяснить, что вы пытаетесь сохранить. Если это подграф объекта, вы можете сделать его «совместимым с NSCoding» и архивировать в «NSData» и написать это. –

2

Существует несколько мест для хранения такого рода информации на Mac. Самое простое, конечно, хранить его в отдельной отдельной базе данных метаданных. Конечно, есть проблемы, если файл перемещается. Однако с 10.6 вы можете использовать Закладки для решения этой проблемы. Закладка (см. NSURL) позволяет сохранить ссылку на файл, даже если он перемещен (даже при перезапуске приложения). До 10.6 был Alias ​​Manager, но он не мог создавать новые псевдонимы; просто прочитайте, что создал Finder.

Следующим распространенным решением является создание файлов метаданных. Поэтому, если у меня есть foo.txt, тогда вы создаете родного брата .foo.txt.metadata, чтобы провести дополнительную информацию. Существует несколько компромиссов, если файлы можно перемещать.

Следующий Spotlight, который может использоваться для прикрепления произвольной информации к файлам. Фактическим инструментом здесь является xattr (см. Справочные страницы для setxattr и его родственников). Они в основном поглощают несколько вещей, которые раньше выполнялись с помощью Resource Forks (кроме xattr, как предполагается, были только метаданные).

+0

Информация хороша (мне нравится обзор подходов), но, возможно, больше идей о том, как на самом деле использовать некоторые из этих материалов, было бы аккуратно (ссылки на учебные материалы были бы замечательными). –