1

私が書いたプログラムは、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];

そのファイルの内容がこの制限を超えると、seg fault が発生します。

于 2013-01-03T07:04:58.060 に答える
1

count = read(openDescriptorOriginal, bufff, partSize); この行では第 3 引数が間違っています

あなたのコードでは 、ファイルから一度に 511 バイトだけ読み取るようにchar BUFFER[512];使用を定義しました。BUFFER

count = read(openDescriptorOriginal, BUFFER, 512);      

大きないいねを処理しない理由: >
の 場合、バッファ オーバーラン (バッファ オーバーフロー) が発生する可能性があります。そのため、大きなファイルでは機能しません。この関数は、開いているファイル記述子 fildes に関連付けられたファイルから、バイト長の BUFFER が指すバッファーにバイトを読み取ろうとするためです。このバッファ オーバーランは、プログラムのセグメンテーション違反の原因です。partSize 512read()partSizeopenDescriptorOriginal512

ファイル サイズが小さい場合、コードは機能します。


私はあなたのコードをいくらか修正しました:

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 バイトを超えると、segfault が発生します。

理想的には、固定チャンクでファイルから読み取る必要があります。つまり、読み取りごとにおそらく 30 ~ 40 文字または一定数の文字を読み取り、それを新しいファイルに書き込みます。完全なファイルが読み取られるまで繰り返します。

于 2013-01-03T07:05:49.947 に答える
0

ここは意味がない

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

2 に初期化partsした後、元のファイル サイズに 2 を加算して 1 を減算し、最終的にバッファ サイズが 512 であっても、再び 2 で割りますか?

あなたがする必要があるのは、ファイルから読み取るときにバッファサイズを使用し、実際に読み取られたバイト数を確認することです。この値を元のファイルサイズから減算し、実際の読み取りバイト数がバッファサイズよりも小さくなるまで繰り返します。元のファイル サイズは 0 です。

fopen/fread/fwrite/fcloseまた、バッファリングされていない I/O を使用する特別な理由がない場合は、ファイル バッファリングされた I/O を使用する方がよいでしょう。

于 2013-01-03T07:12:01.843 に答える