1

我编写的程序获取一个文件的大小,从该文件中读取 partSize 个字节,并将 partSize 个字节写入一个新创建的文件。问题是它只适用于小文本文件。如果我尝试使用几百行的文本文件或图片运行程序,则会出现分段错误,并且将明显少于 partSize 的字节存储到新文件中。

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h> 
#include <sys/types.h> 
#include <errno.h>

int main()
{
    int createDescriptor;
    int openDescriptorOriginal;
    int closeCreateDescriptor;

    //   char fileNameOriginal[] = "picture.jpg";
    char fileNameOriginal[] = "myFile.txt";

    int parts;
    int partSize;

    parts=2;

    int bytesRemaining;
    int partNumber;
    char BUFFER[512];
    int readDescriptor;

    int buffer[1];
    oid *pbuffer = &buffer;

    int bytes, infile, outfile;

    if ((openDescriptorOriginal = open(fileNameOriginal, O_RDONLY )) == -1)
    {
        printf("Error opening %s", fileNameOriginal);
        exit(EXIT_FAILURE);
    }

    struct stat buf;
    int r = fstat(openDescriptorOriginal, &buf);
    if (r)
    {
        fprintf(stderr, "error: fstat: %s\n", (char *) strerror(errno));
        exit(1);
    }

    int originalFileSize = buf.st_size;
    printf("The file is %.9f bytes large.\n",(double)originalFileSize);

    partSize = ((originalFileSize + parts) - 1)/parts;
    printf("Part size: %.9f bytes large\n",(double)partSize);
    umask(0000);
    //create and open new file
    if ( (outfile = open("NewPicture.jpg", O_CREAT|O_WRONLY,0777))==-1 ) 
    {
        printf("ERROR %s\n", "NewPicture.jpg");
    }

    ssize_t count, total;
    total = 0;
    char *bufff = BUFFER;
    while (partSize) {
        count = read(openDescriptorOriginal, bufff, partSize);
        if (count < 0) {
            break;
        }
        if (count == 0)
            break;
        bufff += count;
        total += count;
        partSize -= count;

    }

    write (outfile, BUFFER, total);
    printf("\n");

    return 0;

}
4

4 回答 4

2

您仅使用 512 字节的缓冲区。

BUFFER[512];

如果该文件中的内容超出此限制,则会发生段错误。

于 2013-01-03T07:04:58.060 回答
1

count = read(openDescriptorOriginal, bufff, partSize); 在这一行中,第三个参数是错误的,

在您的代码中,您定义 了一次只从文件中读取 511 个字节的char BUFFER[512];用途。BUFFER

count = read(openDescriptorOriginal, BUFFER, 512);      

不使用大赞的原因:
如果partSize > then 512那么可能会发生缓冲区溢出(缓冲区溢出)。这就是为什么您不适用于大文件的原因。因为该read()函数应尝试partSize从与打开的文件描述符openDescriptorOriginalfildes 关联的文件中读取字节到由 BUFFER 指向的缓冲区中,该缓冲区的长度仅为512字节长。此缓冲区溢出是程序中分段错误的原因。

如果文件大小很小,那么代码将起作用。


我已经更正了您的代码:

ssize_t count=0, total=0;
total = 0;
char *bufff = calloc(partSize+1, sizeof(char));
char *b = bufff;
while (partSize > 0) {
    count = read(openDescriptorOriginal, b, 512);

    if (count < 0) {
        break;
    }
    if (count == 0)
        break;
    b = b + count;
    total = total + count;
    partSize = partSize - count; 

}
write (outfile, bufff, total);
close(openDescriptorOriginal);
close(outfile);
于 2013-01-03T07:05:45.543 回答
1

你的缓冲区太小了。您需要一个更大的缓冲区变量。如果您的文件大小超过 512 字节,则会出现段错误。

理想情况下,您应该以固定的块读取文件。也就是说,每次读取可能读取 30-40 或恒定数量的字符,然后将其写入新文件。重复直到读取完整的文件。

于 2013-01-03T07:05:49.947 回答
0

这在这里没有意义

partSize = ((originalFileSize + parts) - 1)/parts;

您已初始化parts为 2,然后将原始文件大小加 2 并减去 1,然后再除以 2,即使在一天结束时您的缓冲区大小为 512?

您需要做的是在从文件中读取并检查实际读取了多少字节时使用缓冲区大小,从原始文件大小中减去该值,重复直到实际读取的字节小于缓冲区大小和/或何时原始文件大小为 0。

如果您使用文件缓冲 I/O 也可能会更好fopen/fread/fwrite/fclose- 如果您没有任何特殊原因要使用非缓冲 I/O。

于 2013-01-03T07:12:01.843 回答