TAR encode/decode library for iPhone (ideally cocoa) [closed]

左心房为你撑大大i 提交于 2019-12-22 03:56:45

问题


Does anyone know of any library/code that will enable me to encode and decode .tar formatted data - that I can use in my iPhone project (preferably cocoa)

Thanks in advance

Craig

UPDATE: I've taken a look at the suggested libraries and come to the conclusion that they are making waaaay to much of the problem - so I'm developing the codec myself - it's only a 512byte ASCII header after all - how hard can it be :-)


回答1:


The best library I've found is libarchive. It is well-designed, well-documented, and fast.

I just created a repository on GitHub that has the tools to build libarchive and libbz2 as static libraries for iOS 4.2+. (It should be possible to use it to target 3.x, too.)

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

Others have pointed out that libarchive is included in the SDK. This is not quite true. The binary libarchive.2.dylib is included, but the headers are not. The same applies to libbz2 (but, oddly, not to libz.) This means that libarchive is considered a private API -- in other words, you can't use it if you intend to ship on the App Store. Hence my repository.




回答2:


In fact, libarchive.dylib is included in the iPhone SDK. You just have to add it. The problem is that somehow Apple did not include the header file archive.h. However, first, you do not need the header files if you know for sure the functions you are going to call exist (though the compiler will whine), second, if you do not want the compiler to complain, you can download the header file for libarchive 2.6 and include it in your program ...

If you want to know know to use libarchive, download its source from the web and study the example given (especially minitar). It is really very straightforward.




回答3:


You might try libxad. This is the library that The Unarchiver, a Mac app, uses.




回答4:


Even better link: http://code.google.com/p/libarchive/downloads/detail?name=libarchive-2.6.2.tar.gz&can=2&q=

Version 2.6.2 is included in the iOS 4.0 and 4.1 SDK's. It's not present in 3.2 (or earlier I assume).

If you download that, run ./configure --prefix=$HOME && make && make install and you'll find the two header files placed in $HOME/include




回答5:


For libarchive, it works out of the box by just adding "libarchive" to your framework list, but the header is missing. You can copy the headers from the libarchive source. Or if you want to keep it simple, try this:

////////////////////////////////////////////////////////////////////////////////////////////////////
//  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 *);

I only cared about reading so I didn't bother with some of the archive_entry.h mutation functions. Also, a few of the methods are commented out. Those are the alternates for different versions that get #ifdef'd out. Good luck and good bug hunting!

Here's a sample of using it to unpack an archive to a directory on 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;
    }
}

--- Dave




回答6:


libarchive comes preinstalled on iOS.




回答7:


There seem to be two more modern libraries, both of them available as Cocoapods:

  • NVHTarGzip: Supports progress reporting, and has both sync and async methods. Doesn't support tar writing.
  • tarkit: Supports tar writing, but doesn't have the other nice features.

Both of them are very similar, as they are both based on Light-Untar-for-iOS.



来源:https://stackoverflow.com/questions/1204912/tar-encode-decode-library-for-iphone-ideally-cocoa

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!