2009-07-30 4 views
9

¿Alguien sabe de cualquier biblioteca/código que me permita codificar y decodificar datos con formato .tar - que puedo utilizar en mi proyecto iPhone (preferiblemente de cacao)TAR de codificación/decodificación de la biblioteca para el iPhone (idealmente cacao)

Gracias de antemano

Craig

Actualización: he echado un vistazo a las bibliotecas sugeridos y llegan a la conclusión de que están haciendo waaaay a gran parte del problema - así que estoy desarrollando el códec a mí mismo - es solo un encabezado ASCII de 512 bytes después de todo - qué tan difícil puede ser :-)

+0

primer elemento encontrado en google 'tar library c' http://www.feep.net/libtar/ – KevinDTimm

+0

Craig, ¿alguna vez ha encontrado una buena respuesta aquí ... o ha progresado en su propia implementación? Es un gran agujero en el espacio API, por lo que puedo ver. También: Logré compilar libtar en bibliotecas estáticas compatibles con el iPhone, pero fue un proceso doloroso y me encontré con algunos bloqueos en casos de prueba que me hacen pensar que tengo que abandonar toda la dirección. –

Respuesta

2

De hecho, libarchive.dylib está incluido en el SDK de iPhone. Solo tienes que agregarlo. El problema es que, de alguna manera, Apple no incluyó el archivo de encabezado archive.h. Sin embargo, primero, no necesita los archivos de encabezado si está seguro de que las funciones que va a llamar existen (aunque el compilador silbará), en segundo lugar, si no desea que el compilador se queje, puede descargar el archivo de encabezado para libarchive 2.6 e inclúyalo en su programa ...

Si quiere saber saber utilizar libarchive, descargue su fuente de la web y estudie el ejemplo dado (especialmente minitar). Es realmente muy directo.

+0

Creo que eso hace indocumentado, lo que significa que no puede usarlo. Pero podría estar equivocado. –

+1

Por favor, vea mi respuesta a continuación. 'libarchive' es una API privada en TODAS las versiones de iOS. Para ser una API pública, (1) el binario de la biblioteca debe estar en el SDK y (2) el archivo de encabezado debe estar en el SDK. –

+0

¿Libarchive es público en Mac OS? – Enchilada

1

Aún mejor enlace: http://code.google.com/p/libarchive/downloads/detail?name=libarchive-2.6.2.tar.gz&can=2&q=

Versión 2.6.2 está incluido en el iOS 4.0 y 4.1 SDK. No está presente en 3.2 (o antes, supongo).

Si descarga que, ejecute ./configure --prefix=$HOME && make && make install y encontrará los dos archivos de cabecera colocados en $ HOME/include

+0

Consulte mi respuesta a continuación. 'libarchive' es una API privada en TODAS las versiones de iOS. Para ser una API pública, (1) el binario de la biblioteca debe estar en el SDK y (2) el archivo de encabezado debe estar en el SDK. –

5

La mejor biblioteca que he encontrado es libarchive. Está bien diseñado, bien documentado y rápido.

Acabo de crear un repositorio en GitHub que tenga las herramientas para compilar libarchive y libbz2 como bibliotecas estáticas para iOS 4.2+. (Debería ser posible utilizarlo para apuntar 3.x, también.)

http://github.com/davepeck/iOS-libarchive/

Otros han señalado que libarchive está incluido en el SDK. Esto no es completamente cierto. Se incluye el libarchive.2.dylib binario, pero los encabezados no lo están. Lo mismo se aplica al libbz2 (pero, curiosamente, no a libz). Esto significa que libarchive se considera una API privada; en otras palabras, no puede usarla si tiene previsto enviarla a la tienda de aplicaciones. De ahí mi repositorio.

+0

Hola Dave, gracias por compartir tu trabajo. Me pregunto si realmente has enviado una aplicación a la tienda usando este código. Esta pregunta sugiere que aún puede tener problemas: http://stackoverflow.com/questions/3507684/apple-private-api-rejection-with-libarchive – n8gray

+0

El proyecto vinculado se ha borrado de la existencia – jjxtra

1

Para libarchive, funciona de inmediato agregando "libarchive" a su lista de marcos, pero falta el encabezado. Puede copiar los encabezados de la fuente libarchive. O si desea que sea sencillo, intente esto:

//////////////////////////////////////////////////////////////////////////////////////////////////// 
// LibArchive "Header" - ios is missing this header. go figure. 
//////////////////////////////////////////////////////////////////////////////////////////////////// 

// from ftp://ftp8.freebsd.org/pub/FreeBSD/FreeBSD-current/src/lib/libarchive/archive.h.in 

#define  ARCHIVE_EOF    1   /* Found end of archive. */ 
#define  ARCHIVE_OK     0   /* Operation was successful. */ 
#define  ARCHIVE_RETRY   (-10)  /* Retry might succeed. */ 
#define  ARCHIVE_WARN    (-20)  /* Partial success. */ 
#define  ARCHIVE_FAILED   (-25)  /* Current operation cannot complete. */ 
#define  ARCHIVE_FATAL   (-30)  /* No more operations are possible. */ 

struct archive; 
struct archive_entry; 

int    archive_version_number(void); 
const char *  archive_version_string(void); 
int    archive_version_stamp(void); 
const char *  archive_version(void); 
int    archive_api_version(void); 
int    archive_api_feature(void); 
typedef ssize_t archive_read_callback(struct archive *, void *_client_data, const void **_buffer); 
//typedef ssize_t archive_skip_callback(struct archive *, void *_client_data, size_t request); 
typedef off_t  archive_skip_callback(struct archive *, void *_client_data, off_t request); 
typedef ssize_t archive_write_callback(struct archive *, void *_client_data, const void *_buffer, size_t _length); 
typedef int  archive_open_callback(struct archive *, void *_client_data); 
typedef int  archive_close_callback(struct archive *, void *_client_data); 
struct   archive *archive_read_new(void); 
int    archive_read_support_compression_all(struct archive *); 
int    archive_read_support_compression_bzip2(struct archive *); 
int    archive_read_support_compression_compress(struct archive *); 
int    archive_read_support_compression_gzip(struct archive *); 
int    archive_read_support_compression_none(struct archive *); 
int    archive_read_support_compression_program(struct archive *, const char *command); 
int    archive_read_support_format_all(struct archive *); 
int    archive_read_support_format_ar(struct archive *); 
int    archive_read_support_format_cpio(struct archive *); 
int    archive_read_support_format_empty(struct archive *); 
int    archive_read_support_format_gnutar(struct archive *); 
int    archive_read_support_format_iso9660(struct archive *); 
int    archive_read_support_format_mtree(struct archive *); 
int    archive_read_support_format_tar(struct archive *); 
int    archive_read_support_format_zip(struct archive *); 
int    archive_read_open(struct archive *, void *_client_data, archive_open_callback *, archive_read_callback *, archive_close_callback *); 
int    archive_read_open2(struct archive *, void *_client_data, archive_open_callback *, archive_read_callback *, archive_skip_callback *, archive_close_callback *); 
int    archive_read_open_filename(struct archive *, const char *_filename, size_t _block_size); 
int    archive_read_open_file(struct archive *, const char *_filename, size_t _block_size); 
int    archive_read_open_memory(struct archive *, void * buff, size_t size); 
int    archive_read_open_memory2(struct archive *a, void *buff, size_t size, size_t read_size); 
int    archive_read_open_fd(struct archive *, int _fd, size_t _block_size); 
int    archive_read_open_FILE(struct archive *, FILE *_file); 
int    archive_read_next_header(struct archive *, struct archive_entry **); 
int64_t   archive_read_header_position(struct archive *); 
ssize_t   archive_read_data(struct archive *, void *, size_t); 
int    archive_read_data_block(struct archive *a, const void **buff, size_t *size, off_t *offset); 
int    archive_read_data_skip(struct archive *); 
int    archive_read_data_into_buffer(struct archive *, void *buffer, ssize_t len); 
int    archive_read_data_into_fd(struct archive *, int fd); 
int    archive_read_extract(struct archive *, struct archive_entry *, int flags); 
void    archive_read_extract_set_progress_callback(struct archive *, void (*_progress_func)(void *), void *_user_data); 
void    archive_read_extract_set_skip_file(struct archive *, dev_t, ino_t); 
int    archive_read_close(struct archive *); 
int    archive_read_finish(struct archive *); 
//void    archive_read_finish(struct archive *); 
struct   archive *archive_write_new(void); 
int    archive_write_set_bytes_per_block(struct archive *, int bytes_per_block); 
int    archive_write_get_bytes_per_block(struct archive *); 
int    archive_write_set_bytes_in_last_block(struct archive *, int bytes_in_last_block); 
int    archive_write_get_bytes_in_last_block(struct archive *); 
int    archive_write_set_skip_file(struct archive *, dev_t, ino_t); 
int    archive_write_set_compression_bzip2(struct archive *); 
int    archive_write_set_compression_compress(struct archive *); 
int    archive_write_set_compression_gzip(struct archive *); 
int    archive_write_set_compression_none(struct archive *); 
int    archive_write_set_compression_program(struct archive *, const char *cmd); 
int    archive_write_set_format(struct archive *, int format_code); 
int    archive_write_set_format_by_name(struct archive *, const char *name); 
int    archive_write_set_format_ar_bsd(struct archive *); 
int    archive_write_set_format_ar_svr4(struct archive *); 
int    archive_write_set_format_cpio(struct archive *); 
int    archive_write_set_format_cpio_newc(struct archive *); 
int    archive_write_set_format_pax(struct archive *); 
int    archive_write_set_format_pax_restricted(struct archive *); 
int    archive_write_set_format_shar(struct archive *); 
int    archive_write_set_format_shar_dump(struct archive *); 
int    archive_write_set_format_ustar(struct archive *); 
int    archive_write_open(struct archive *, void *, archive_open_callback *, archive_write_callback *, archive_close_callback *); 
int    archive_write_open_fd(struct archive *, int _fd); 
int    archive_write_open_filename(struct archive *, const char *_file); 
int    archive_write_open_file(struct archive *, const char *_file); 
int    archive_write_open_FILE(struct archive *, FILE *); 
int    archive_write_open_memory(struct archive *, void *_buffer, size_t _buffSize, size_t *_used); 
int    archive_write_header(struct archive *, struct archive_entry *); 
ssize_t   archive_write_data(struct archive *, const void *, size_t); 
//int    archive_write_data(struct archive *, const void *, size_t); 
ssize_t   archive_write_data_block(struct archive *, const void *, size_t, off_t); 
int    archive_write_finish_entry(struct archive *); 
int    archive_write_close(struct archive *); 
int    archive_write_finish(struct archive *); 
//void    archive_write_finish(struct archive *); 
struct   archive *archive_write_disk_new(void); 
int    archive_write_disk_set_skip_file(struct archive *, dev_t, ino_t); 
int    archive_write_disk_set_options(struct archive *, int flags); 
int    archive_write_disk_set_standard_lookup(struct archive *); 
int    archive_write_disk_set_group_lookup(struct archive *, void *private_data, gid_t (*loookup)(void *, const char *gname, gid_t gid), void (*cleanup)(void *)); 
int    archive_write_disk_set_user_lookup(struct archive *, void *private_data, uid_t (*)(void *, const char *uname, uid_t uid), void (*cleanup)(void *)); 
int64_t   archive_position_compressed(struct archive *); 
int64_t   archive_position_uncompressed(struct archive *); 
const char *  archive_compression_name(struct archive *); 
int    archive_compression(struct archive *); 
int    archive_errno(struct archive *); 
const char *  archive_error_string(struct archive *); 
const char *  archive_format_name(struct archive *); 
int    archive_format(struct archive *); 
void    archive_clear_error(struct archive *); 
void    archive_set_error(struct archive *, int _err, const char *fmt, ...); 
void    archive_copy_error(struct archive *dest, struct archive *src); 

// From ftp://ftp8.freebsd.org/pub/FreeBSD/FreeBSD-current/src/lib/libarchive/archive_entry.h 

time_t   archive_entry_atime(struct archive_entry *); 
long    archive_entry_atime_nsec(struct archive_entry *); 
time_t   archive_entry_ctime(struct archive_entry *); 
long    archive_entry_ctime_nsec(struct archive_entry *); 
dev_t    archive_entry_dev(struct archive_entry *); 
dev_t    archive_entry_devmajor(struct archive_entry *); 
dev_t    archive_entry_devminor(struct archive_entry *); 
mode_t   archive_entry_filetype(struct archive_entry *); 
void    archive_entry_fflags(struct archive_entry *, unsigned long *set, unsigned long *clear); 
const char*  archive_entry_fflags_text(struct archive_entry *); 
gid_t    archive_entry_gid(struct archive_entry *); 
const char*  archive_entry_gname(struct archive_entry *); 
const wchar_t* archive_entry_gname_w(struct archive_entry *); 
const char*  archive_entry_hardlink(struct archive_entry *); 
const wchar_t* archive_entry_hardlink_w(struct archive_entry *); 
ino_t    archive_entry_ino(struct archive_entry *); 
mode_t   archive_entry_mode(struct archive_entry *); 
time_t   archive_entry_mtime(struct archive_entry *); 
long    archive_entry_mtime_nsec(struct archive_entry *); 
unsigned int  archive_entry_nlink(struct archive_entry *); 
const char*  archive_entry_pathname(struct archive_entry *); 
const wchar_t* archive_entry_pathname_w(struct archive_entry *); 
dev_t    archive_entry_rdev(struct archive_entry *); 
dev_t    archive_entry_rdevmajor(struct archive_entry *); 
dev_t    archive_entry_rdevminor(struct archive_entry *); 
int64_t   archive_entry_size(struct archive_entry *); 
const char*  archive_entry_strmode(struct archive_entry *); 
const char*  archive_entry_symlink(struct archive_entry *); 
const wchar_t* archive_entry_symlink_w(struct archive_entry *); 
uid_t    archive_entry_uid(struct archive_entry *); 
const char*  archive_entry_uname(struct archive_entry *); 
const wchar_t* archive_entry_uname_w(struct archive_entry *); 

que sólo se preocupaba por la lectura, así que no me molesté con algunas de las funciones de mutación archive_entry.h. Además, algunos de los métodos están comentados. Esos son los suplentes para diferentes versiones que obtienen # ifdef'd out. Buena suerte y buena caza de errores!

He aquí una muestra de usarlo para descomprimir un archivo en un directorio de ios:

+ (void)unpackArchive: (NSData*) archiveData 
{ 
    int r; 
    struct archive* a; 
    struct archive_entry *entry; 
    const char *entry_path; 
    NSString *baseDir = [self baseDir]; 
    NSFileHandle* file; 
    NSError* error; 
    NSDictionary* result = @{}; 

    NSLog(@"Unpacking %d byte static assets tarball into %@", [archiveData length], baseDir); 

    if (![[NSFileManager defaultManager] createDirectoryAtPath:baseDir 
            withIntermediateDirectories:YES 
                attributes:nil 
                 error:&error]) 
    { 
     NSLog(@"Create directory error: %@", error); 
    } 

    a = archive_read_new(); 
    archive_read_support_format_gnutar(a); 
    archive_read_support_format_tar(a); 
    archive_read_support_compression_gzip(a); 

    r = archive_read_open_memory(a, (void*)[archiveData bytes], [archiveData length]); 
    if (r != ARCHIVE_OK) { 
     NSLog(@"ERROR[%d] in archive_read_open_file(): %s", r, archive_error_string(a)); 
     return; 
    } 
    for (;;) { 
     r = archive_read_next_header(a, &entry); 
     if (r == ARCHIVE_EOF) { 
      break; 
     } 
     if (r != ARCHIVE_OK) { 
      NSLog(@"ERROR[%d] in archive_read_next_header(): %s", r, archive_error_string(a)); 
      return; 
     } 
     entry_path = archive_entry_pathname(entry); 

     NSString* path = [baseDir stringByAppendingPathComponent: [NSString stringWithUTF8String: entry_path]]; 
     NSLog(@"Tarball Entry: %s", entry_path); 

     // Create the file and blank it out 
     [[NSFileManager defaultManager] createFileAtPath: path contents:[[NSMutableData alloc] init] attributes:nil]; 
     // Actually write the file 
     file = [NSFileHandle fileHandleForWritingAtPath:path]; 
     r = archive_read_data_into_fd(a, [file fileDescriptor]); 
     if (r != ARCHIVE_OK) { 
      NSLog(@"ERROR[%d] in archive_read_data_into_fd(): %s", r, archive_error_string(a)); 
      return; 
     } 
     [file closeFile]; 
    } 
    r = archive_read_close(a); 
    if (r != ARCHIVE_OK) { 
     NSLog(@"ERROR[%d] in archive_read_close(): %s", r, archive_error_string(a)); 
     return; 
    } 
} 

--- David

0

Parece que hay dos más modernas bibliotecas, ambos disponibles como Cocoapods :

  • NVHTarGzip: Admite informes de progreso y tiene métodos de sincronización y asincrónicos. No es compatible con la escritura tar.
  • tarkit: Admite la escritura tar, pero no tiene las otras funciones agradables.

Ambos son muy similares, ya que ambos se basan en Light-Untar-for-iOS.

+0

tarkit produce archivos que no están expandidos por Archive Utility.app, Yosemite, el archivo que he tardado es un archivo de fuente. –

+0

corrección: [DCTar tarFileAtPath: filePath toPath: tarFilePath error: nil] está asumiendo que filePath es una carpeta y si solo tiene un archivo en tar, falla ... –

+0

Terminé usando NVHTarGzip, después de [contribuir '. tar' y '.tar.gz' packing] (https://github.com/nvh/NVHTarGzip/pull/6) a él. –

Cuestiones relacionadas