Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/58.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 使用有限缓冲区大小的posix读取_C_File_File Io_Posix - Fatal编程技术网

C 使用有限缓冲区大小的posix读取

C 使用有限缓冲区大小的posix读取,c,file,file-io,posix,C,File,File Io,Posix,我正在编写一个应用程序,其中必须解析文件的内容。我使用的一些库函数不能很好地处理动态分配的数组。这迫使我在堆栈上有一个固定大小的数组。然而,如果一行只是部分读取,那么解析数据将不起作用,而我被迫使用POSIX read来实现这一点 char buff[512] = '\0'; int fileHandle = open( scEndOfLinePPSPath , O_RDONLY ); if(-1 != fileHandle) { while( 0 < read(fileHand

我正在编写一个应用程序,其中必须解析文件的内容。我使用的一些库函数不能很好地处理动态分配的数组。这迫使我在堆栈上有一个固定大小的数组。然而,如果一行只是部分读取,那么解析数据将不起作用,而我被迫使用POSIX read来实现这一点

char buff[512] = '\0';
int fileHandle = open( scEndOfLinePPSPath , O_RDONLY );

if(-1 != fileHandle)
{
    while( 0 < read(fileHandle, &buff, sizeof(buff) - 1) )
    {
        parse(&buff); /* doesn't play nice with dynamically allocated memory */
charbuff[512]='\0';
int fileHandle=open(scendoflinepppath,仅限ordu);
如果(-1!=文件句柄)
{
而(0
当我开始尝试限制缓冲区大小时,可能会遇到解析失败的情况,因为文件更大,一行只能部分读取(因此解析算法只能处理部分数据)

如果读取缓冲区结束,如下图所示,解析算法显然无法获取属性名称,下一次读取将使用属性名称的后半部分:

attribute=“Mai

在继续使用POSIX读取的同时,有没有一种优雅的方法来处理这种情况?我知道我可以根据文件大小动态分配内存,但正如我所说的,动态分配的内存在解析库中不起作用

谢谢

已解决:

谢谢大家的支持!问题现在已经解决了。我可以使用动态内存分配并为整个文件创建足够大的缓冲区

我使用lseek确定文件大小。不知何故,读取API读取的字节数比lseek或fstat报告的大小多3个字节,因此分配的缓冲区不够大,无法成功解析。这是否意味着,lseek不是确定文件大小的可靠方法?

解析()
函数不应该能够区分动态分配的缓冲区和声明为固定大小数组的缓冲区。但是,它可能期望缓冲区具有特定大小。在这种情况下,
parse()
函数的问题是处理跨越缓冲区边界的数据(可能需要多次调用),但您的问题是确保缓冲区达到预期大小,并且在每次调用之前完全填满缓冲区(文件末尾除外,它必须以某种方式通知
parse()
)。
read()
函数不保证这样做,这可能是您的问题

如果要将所有可用字节读取到缓冲区中,直至达到其容量,则需要准备执行多个
read()
s。它看起来如下所示:

#define BUFF_SIZE 512

char buff[BUFF_SIZE];
ssize_t next_offset = 0;

do {
    ssize_t n_read = read(fd, buff + next_offset, BUFF_SIZE - next_offset);

    if (n_read == 0) {
        /* end of file */
        buff[next_offset] = 0;  /* add a terminator */
        break;
    } else if (n_read < 0) {
        /* handle error ... */
    } else {
        next_offset += n_read;
    }
} while (next_offset < BUFF_SIZE);
#定义缓冲大小512
字符缓冲[缓冲大小];
ssize_t next_offset=0;
做{
ssize_t n_read=读取(fd,buff+下一个_偏移量,buff_大小-下一个_偏移量);
如果(n_read==0){
/*文件结束*/
buff[next_offset]=0;/*添加终止符*/
打破
}否则如果(n_读取<0){
/*处理错误*/
}否则{
next_offset+=n_read;
}
}while(下一个_偏移

或者,问题可能只是
parse()
需要一个(以零结尾的)C字符串。如果静态声明缓冲区并初始化缓冲区的任何部分,则未显式初始化的元素将自动初始化为“\0”。如果缓冲区恰好大于输入,则会半自动获得终止符,但如果输入恰好与缓冲区大小相同或更长,则会自动终止另一方面,使用动态分配的缓冲区,您需要为终止符留出空间,并且需要手动将其插入结尾。(并且您仍然需要准备执行多个
read()
调用,如上所述)问题是你通常不知道你要读的行有多长——你需要先读它们并寻找换行符,在这一点上你可能已经读了下一行的一部分,所以你需要确保你不会丢失它。所以你最终需要的代码是循环读取到缓冲区,同时也要查找f或者换行,并在缓冲区中的换行之后移动数据

所以你通常会得到这样的结果:

char buffer[512];
char *data_start = buffer, *data_end = buffer;

while(1) {
    if (char *eol = memchr(data_start, '\n', data_end-data_start)) {
        /* have a full line, null-terminate and pass to parse */
        *eol = '\0';
        parse(data_start);
        data_start = eol+1;
    } else {
        /* no newline in the buffer -- read more */
        if (data_start != buffer) {
            /* move leftover data (if any) to the front of the buffer */
            memmove(buffer, data_start, data_end - data_start);
            data_end -= data_start-buffer;
            data_start = buffer; }
        if (data_end == buffer + sizeof(buffer)) {
            /* line too long for the buffer -- can't deal with it */
            break; }
        int rv = read(fd, data_end, buffer+sizeof(buffer)-data_end);
        if (rv <= 0) {
            /* error or end of file */
            break; }
        data_end += rv; } }
char缓冲区[512];
char*data\u start=buffer,*data\u end=buffer;
而(1){
if(char*eol=memchr(数据开始,'\n',数据结束-数据开始)){
/*有一个完整的行,null终止并传递给parse*/
*下线='\0';
解析(数据启动);
数据_开始=下线+1;
}否则{
/*缓冲区中没有换行符--请阅读更多*/
如果(数据开始!=缓冲区){
/*将剩余数据(如果有)移到缓冲区的前面*/
memmove(缓冲区、数据开始、数据结束-数据开始);
数据\u结束-=数据\u开始缓冲区;
数据\u start=buffer;}
if(data_end==buffer+sizeof(buffer)){
/*行对于缓冲区太长--无法处理它*/
中断;}
int rv=读取(fd,数据结束,缓冲区+sizeof(缓冲区)-数据结束);

if(rv)请定义“动态分配内存不好用”。这没有什么意义,除非它做了一些非常奇怪的事情。怎么会是
parse()
适用于固定大小的数组,但不适用于动态分配的数组?除非假定缓冲区具有特定大小,否则它不应该能够分辨出差异。如果输入文件包含的行长度超过
sizeof(buff)-1
?如果解析函数使用sizeof()例如,对于动态分配的缓冲区和本地数组,结果可能不同。当我使用动态数组时,解析函数最终会出现分段错误。解析函数是qnx ppsparse api!@Ashwin如果从解析函数内部对缓冲区使用
sizeof
,它返回的大小将取决于类型在参数列表中,而不是在传递给t的缓冲区中