簡體   English   中英

如何在C ++中解析tar文件

[英]How to parse a tar file in C++

我想要做的是下載一個包含多個目錄的.tar文件,每個目錄包含2個文件。 問題是我找不到一種方法來讀取tar文件而不實際提取文件(使用tar )。

完美的解決方案將是這樣的:

#include <easytar>

Tarfile tar("somefile.tar");
std::string currentFile, currentFileName;
for(int i=0; i<tar.size(); i++){
  file = tar.getFileText(i);
  currentFileName = tar.getFileName(i);
  // do stuff with it
}

我可能不得不自己寫這個,但任何想法都會受到贊賞..

經過一番工作后,我自己想出了這個。 tar文件規范實際上告訴你需要知道的一切。

首先,每個文件都以512字節的頭開頭,因此您可以使用char [512]或char *來指示它,指向較大char數組中的某個位置(例如,如果您將整個文件加載到一個數組中)。

標題看起來像這樣:

location  size  field
0         100   File name
100       8     File mode
108       8     Owner's numeric user ID
116       8     Group's numeric user ID
124       12    File size in bytes
136       12    Last modification time in numeric Unix time format
148       8     Checksum for header block
156       1     Link indicator (file type)
157       100   Name of linked file

所以如果你想要文件名,你可以在這里用string filename(buffer[0], 100);抓住它string filename(buffer[0], 100); 文件名為空填充,因此您可以檢查以確保至少有一個null,如果要節省空間,則不要使用大小。

現在我們想知道它是文件還是文件夾。 “鏈接指示符”字段包含此信息,因此:

// Note that we're comparing to ascii numbers, not ints
switch(buffer[156]){
    case '0': // intentionally dropping through
    case '\0':
        // normal file
        break;
    case '1':
        // hard link
        break;
    case '2':
        // symbolic link
        break;
    case '3':
        // device file/special file
        break;
    case '4':
        // block device
        break;
    case '5':
        // directory
        break;
    case '6':
        // named pipe
        break;
}

此時,我們已經掌握了有關目錄的所有信息,但我們需要從普通文件中獲取更多信息:實際文件內容。

文件的長度可以以兩種不同的方式存儲,可以是0或空格填充的以空字符結尾的八進制字符串,也可以是“通過設置最左邊的字節的高位來指示的base-256編碼一個數字字段“。

數字值使用ASCII數字以八進制數編碼,前導零。 由於歷史原因,應使用最終的NUL或空格字符。 因此,盡管保留了12個字節用於存儲文件大小,但是只能存儲11個八進制數字。 這使歸檔文件的最大文件大小為8千兆字節。 為了克服這個限制,2001年的star引入了base-256編碼,通過設置數字字段最左邊字節的高位來指示。 GNU-tar和BSD-tar遵循了這個想法。 此外,1988年第一個POSIX標准之前的tar版本用空格而不是零填充值。

這是你如何閱讀八進制格式,但我還沒有為base-256版本編寫代碼:

// in one function
int size_of_file = octal_string_to_int(&buffer[124], 11);

// elsewhere
int octal_string_to_int(char *current_char, unsigned int size){
    unsigned int output = 0;
    while(size > 0){
        output = output * 8 + *current_char - '0';
        current_char++;
        size--;
    }
    return output;
}

好的,現在我們擁有除實際文件內容之外的所有內容。 我們所要做的就是從tar文件中獲取下一個size的數據字節,我們將獲得文件內容:

// Get to the next block after the header ends
location += 512;
file_contents = new char[size];
memcpy(file_contents, &buffer[location], size);
// Go to the next block by rounding up to 512
// This isn't necessarily the most efficient way to do this,
// but it's the most obvious.
location += (int)ceil(size / 512.0)

你看過libtar了嗎?

從fink包信息:

libtar-1.2-1:tar文件操作API libtar是一個用於操作POSIX tar文件的C庫。 它處理向tar存檔添加文件和從tar存檔中提取文件。 libtar提供以下功能:
*靈活的API - 您可以操作單個文件或只是一次提取整個存檔。
*允許用戶指定的read()和write()函數,例如zlib的gzread()和gzwrite()。
*支持POSIX 1003.1-1990和GNU tar文件格式。

不是c ++ 本身 ,但你很容易鏈接到c ...

libarchive可以是解析tarball的開源庫。 Libarchive可以從存檔文件中讀取每個文件而無需提取,也可以寫入數據以形成新的存檔文件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM