2011-10-04 85 views
5

這可能是一個新手問題,但我想避免緩衝區溢出。我從註冊表中讀取非常多的數據,並將其上傳到SQL數據庫。我在一個循環中讀取數據,並在每個循環之後插入數據。我的問題是,這樣,如果我讀了20個鍵,並且下面的值是(每個計算機上的鍵數不同),那麼我必須連接到SQL數據庫20次。如何正確處理一個巨大的字符串?

但是我發現,有一種方法,創建一個存儲過程,並傳遞整個數據,所以,SQL服務器將處理數據,而且我只需連接一次到SQL服務器。

不幸的是,我不知道如何處理這麼大的字符串,以避免任何意外的錯誤,如緩衝區電流。所以我的問題是我應該如何聲明這個字符串?

我應該只是一個像char string[ 15000 ];這樣的字符串並連接值嗎?還是有一個簡單的方法來做到這一點?

謝謝!

+6

如果我們知道您正在使用C或C++的編程語言這將有助於 –

+0

@Rob:我使用的是C,但如果有人顯示了一個C++例子,那麼我可以用它太 – kampi

+4

爲什麼不乾脆使用一個連接執行多個插入查詢? – Dmitri

回答

2

STL字符串應該比你描述的方法做得更好。

您還需要構建一些閾值。例如,如果您的字符串增長超過一個兆字節,那麼由於您的事務處理時間過長,因此將考慮進行不同的SQL連接。

+1

另請注意,標準C++庫字符串僅爲C++,而非C. C++實現附帶的庫是標準C++庫,不屬於STL。 –

+0

Mooing Duck:土豆potàto,至少在這個('std :: string')的情況下。 'STL'仍然可以明確地用於指代最初稱爲STL的C++標準庫的那部分,並且稍後將其併入到標準庫中。 – rubenvb

0

要在C中正確執行此操作,需要使用malloc或等效的操作系統之一動態分配內存。這裏的想法是弄清楚你實際需要多少內存,然後分配正確的數量。註冊表函數提供了多種方式來確定每次讀取所需的內存量。

如果您正在讀取多個值並將它們連接起來,它會變得更復雜一些。一種方法是將每個值讀入一個單獨分配的內存塊,然後將它們連接到一個新的內存塊,一旦得到它們全部。

但是,可能沒有必要去這麼多麻煩。如果你可以說「如果數據超過X字節,程序將會失敗」,那麼你可以按照你的建議創建一個靜態緩衝區。只要確保提供註冊表和/或字符串連接函數的正確大小的緩衝區的其餘部分,並檢查錯誤,以便如果它確實失敗它正常,而不是崩潰。

還有一個注意事項:char buf[15000];是可以的,只要聲明在程序範圍內,但如果它出現在函數中,則應該添加static說明符。在函數中隱式分配的內存默認從堆棧中獲取,因此大的分配可能會失敗並導致程序崩潰。 (一萬五千個字節應該是確定的,但它不是一個好習慣進入。)

而且,最好是定義你的緩衝區大小的宏,始終如一地使用它:

#define BUFFER_SIZE 15000 
char buf[BUFFER_SIZE]; 

以便稍後通過修改單行來輕鬆增加緩衝區的大小。

+0

我編輯了你的答案一點。宏名稱通常是全部大寫的,因此它們很突出。 'string'對於一個對象來說並不是一個好名字;我將它改爲'buf'。 –

+0

@Keith,我使用了string [],因爲這是OP在他的問題中使用的,但它並不重要。感謝抓住小寫的宏名稱,我一定還睡着了。 –

0

您可以從註冊表中讀取(鍵,值)對,並將它們存儲到預分配的緩衝區中,同時有足夠的空間。 保持緩衝區內的「寫入」位置。您可以使用它來檢查緩衝區中是否有足夠的空間用於新密鑰,值對。 當新的(鍵,值)對沒有剩餘空間時 - 執行存儲過程並重置緩衝區內的「寫入」位置。 在「讀取鍵值對」循環結束時 - 檢查緩衝區的「寫入」位置並執行存儲過程(如果該位置大於0)。 這樣可以最大限度地減少在服務器上執行存儲過程的次數

const int MAX_BUFFER_SIZE = 15000; 
char buffer[MAX_BUFFER_SIZE]; 
char buffer_pos = 0; // "write" position within the buffer. 

... 

// Retrieve key, value pairs and push them into the buffer. 
while(get_next_key_value(key, value)) { 
    post(key, value); 
} 

// Execute stored procedure if buffer is not empty. 
if(buffer_pos > 0) { 
    exec_stored_procedure(buffer); 
} 
... 

bool post(const char* key, const char* value) 
{ 
    int len = strlen(key) + strlen(value) + <length of separators>; 

    // Execute stored procedure if there is no space for new key/value pair. 
    if(len + buffer_pos >= MAX_BUFFER_SIZE) { 
    exec_stored_procedure(buffer); 
    buffer_pos = 0; // Reset "write" position. 
    } 

    // Copy key, value pair to the buffer if there is sufficient space. 
    if(len + buffer_pos < MAX_BUFFER_SIZE) { 
    <copy key, value to the buffer, starting from "write" position> 
    buffer_pos += len; // Adjust "write" position. 
    return true; 
    } 
    else { 
    return false; 
    } 
} 

bool exec_stored_procedure(const char* buf) 
{ 
    <connect to SQL database and execute stored procedure.> 
} 
相關問題