2011-10-04 40 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.> 
} 
相关问题