2013-10-21 19 views
0

我有一個字符串中有一些二進制數據。這是xml格式的字符串,所以在我要處理它之前,我需要以base64格式轉換二進制數據。 我正在使用一個稱爲findXMLTag的函數,它將查找包含它的xml標記的數據的開始位置和結束位置。 現在我可以將該數據轉換爲base64,但我在用新的base64數據替換舊的二進制數據時遇到問題。替換字符串的二進制部分?

問題是我不能使用任何類型的字符串,因爲當它找到一個空字符時,它會認爲它是字符串的終點,但事實上,因爲我有二進制數據存儲在字符串中, char可以是我的二進制數據的一部分。

所以我想我正在尋找某種二進制替換,我無法弄清楚如何使它工作。 在此先感謝您提供任何幫助。

這是我用來定位數據在xml字符串中的開始和結束的代碼。

std::vector<TForm1::Pair> TForm1::findXMLTag(char *XMLString, char* XMLTag, int XMLSize) 
{ 
    void *found = XMLString; 
    int XMLTagLen = strlen(XMLTag); 
    std::vector<TForm1::Pair> result; 
    TForm1::Pair pair; 
    AnsiString XMLTagEnd = "</"; 
    XMLTagEnd += &XMLTag[1]; 

    while(found = memmem(XMLString, XMLSize - ((char*)found - XMLString), XMLTag, XMLTagLen)) 
    { 
     if(found == NULL) 
      return result; 

     found = (char*)found + XMLTagLen; 

     pair.start = int((char*)found - XMLString); 

     found = memmem(found, XMLSize - ((char*)found - XMLString), XMLTagEnd.c_str(), XMLTagEnd.Length()); 

     pair.end = int((char*)found - XMLString); 

     found = (char*)found + XMLTagEnd.Length(); 

     result.push_back(pair); 
    } 

    return result; 
} 
+2

只需使用'vector '。 – paddy

+0

在理解這段代碼的作用和問題是什麼時遇到了一些麻煩。我認爲你正在試圖用base64字符串就地替換二進制數據,但是在所示的代碼中我沒有看到它。 –

+0

另外二進制數據在std :: string下也能正常工作。 –

回答

2

翻譯你的C風格的答案,C++,我們只剩下一個一個班輪這是安全的(爲有效索引),高效性和可讀性:

std::string binary_replace(
    std::string const& bin, unsigned bin_start, unsigned bin_end, 
    std::string const& replace_with 
) { 
    assert(bin_start < bin.size() and bin_end < bin.size()); 
    return bin.substr(0, bin_start) + replace_with + bin.substr(bin_end); 
} 

這可製成甚至更簡單使用replace function爲了這個目的:

std::string binary_replace(
    std::string bin, unsigned bin_start, unsigned bin_end, 
    std::string const& replace_with 
) { 
    assert(bin_start < bin.size() and bin_end < bin.size()); 
    return bin.replace(bin_start, bin_end - bin_start, replace_with); 
} 

(你要小心,bin由價值在這裏,因爲replace修改它通過)

從本質上講,C++中大多數C字符串函數都是直接替代的 - 在這種情況下,請看documentation of std::basic_string::substr

+0

這可以通過'string :: replace'進一步簡化。甚至被替換爲'replace'。 :-) –

+0

那麼我試着這個版本的一些二進制數據到字符串,它不工作。只要它遇到一個NULL字符,它就認爲它是該字符串的終止字符,並且我得到了一個boudns錯誤。我已經嘗試了一個自編寫的字符串與一個NULL字符(「嗨\ 0」)相同的代碼,當我試圖用別的東西替換「there」時,我仍然遇到了同樣的錯誤。 –

+0

@Stamatis你將不會在我的代碼中出現空字符錯誤。你如何嘗試調用代碼?我懷疑你正在構造你的字符串是錯誤的:直接給字符串對象分配''Hi \ 0'這裏'會截斷字符串(因爲C使用'\ 0'作爲終止符)。 –

-1
char *binary_replace(char *binString, int _strlen, int binDataStart, int binDataEnd, char* replaceWith) 
{ 
    char *buffer = (char*)malloc((strlen(replaceWith)+(_strlen - (binDataEnd-binDataStart)))*sizeof(char)); 

    memcpy(buffer, binString, binDataStart); 

    strcat(buffer, replaceWith); 

    memmove(buffer+binDataStart+strlen(replaceWith), binString+binDataEnd, _strlen - binDataEnd); 

    return buffer; 
} 

我知道,這不是C++,但它解決了我的問題。

+0

您可以將此解決方案1:1轉換爲正確的,無內存泄漏,安全的C++並獲得更短,更簡潔的代碼。不知道你爲什麼選擇這條路線。 –

+0

因爲我嘗試使用C++的每一件事都失敗了,我需要儘快結束這件事,這就是現在想到的,所以我會堅持下去直到我可以投入更多時間。 –

+0

然後看我的答案,馬上花點時間學習C++字符串處理。 –

1

這裏有一個可以幫助你的自包含的例子。請注意,沒有錯誤或邊界檢查,它只是爲了演示一個概念。

#include <iostream> 
#include <vector> 
#include <string> 
using namespace std; 

// stub for real base64_encode 
std::string base64_encode(const string &data) 
{ 
    return "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"; 
} 

// search without terminating on NULL 
size_t binary_find(const string &str, size_t offset, const string &s) 
{ 
    for (size_t i=offset; i<str.length(); i++) 
     if (str.compare(i, string::npos, s) == 0) 
      return i; 
    return string::npos; 
} 

int main() 
{ 
    string tag = "<data>"; 
    string endtag = "</data>"; 
    string xml("<data>\0\0\0\0\0\0\0\0\0\0</data>", 23); 
    size_t start = xml.find(tag) + tag.length(); 
    size_t end = binary_find(xml, start, endtag); 
    string binary = xml.substr(start, end-start); 
    string base64 = base64_encode(binary); 
    xml.replace(start, end-start, base64); 
    cout << xml << endl; 
} 
+0

非常感謝! –

+0

是和康拉德魯道夫的解決方案工作得很好......我只需要使用字符串字符串(數據,num_of_data)的數字的字符串構造函數,它的工作就像一個魅力。 –