0

C では、バイト配列から 1 バイトを読み取り、それをファイルに入れ、読み取りを停止したい特定のバイトが見つかるまでそれを何度もループする方法を教えてください。

例:

while  (x = fgetc(file) != EOF )
{
    count++;//Counts the number of bytes
}

chars = (unsigned char*) malloc (sizeof(unsigned char)*count+1);
rewind(file);

FILE* output_file = fopen("Filename.jpg", "rb");

while(chars[i] != specificByte)
{
    fwrite(?,?,?,?); 
}

それは私が使用している正確なコードではありませんが、どこに問題があるかを示すために何かを公開したかっただけです。

バイトを配列に入れるのではなく、ファイルから直接読み取る方が良いでしょうか?

4

5 に答える 5

2

私が提案する場合は、ストップバイトが見つかるまで配列を読み込んでから、単一の I/O で最初からそのストップバイトまで配列を書き込む方がおそらくはるかに効率的です。

于 2011-04-18T13:52:20.790 に答える
2

fread / fwrite を使用した完全な例を次に示します。

しかし、以前の例のいくつかが示しているように、入力ファイルを読み取ると同時に出力ファイルを書き込むことができる一方で、ファイル全体をメモリに読み取ってから再度ファイルに書き込む意味があるかどうかはわかりません.

これが fgetc と fputc を使用するよりも効率的かどうかはわかりませんが、少なくともファイルは 1 回の関数呼び出しで読み書きされます

#include <stdio.h>
#include <stdlib.h>

/* this function retrieves the size of the input file */
long get_filesize(FILE *fp)
{
    long filesize;

    fseek(fp, 0, SEEK_END);
    filesize = ftell(fp);
    rewind(fp);

    return filesize;
}

int main(void)
{
    FILE *fp;
    unsigned char *data;
    long filesize;
    unsigned char specificByte = 10; /* line feed for example */

    /* open the input file */
    fp = fopen("input_file", "rb");
    if(fp == NULL) exit(EXIT_FAILURE);

    /* get the filesize */
    filesize = get_filesize(fp);

    /* allocate space for the file */
    data = malloc(filesize * sizeof(unsigned char));
    if(data == NULL) exit(EXIT_FAILURE);

    /* read the file into memory */
    fread(data, filesize, sizeof(unsigned int), fp);
    fclose(fp);

    /* open output file */
    fp = fopen("output_file", "wb");
    if(fp == NULL) {
        free(data);
        exit(EXIT_FAILURE);
    }

    /* check how many bytes should be written into output file */
    int i;
    for(i = 0; i < filesize && data[i] != specificByte; ++i);

    /* write the bytes */
    fwrite(data, i, sizeof(unsigned char), fp);

    /* close the file and free the memory */    
    fclose(fp);
    free(data);

    return EXIT_SUCCESS;
}
于 2011-04-18T14:07:35.877 に答える
1

これを行う簡単で効果的な方法は、メモリへの読み込みをまったく回避し、次のことを行うことです。

while ((input_char = fgetc(input_fp)) != EOF)
{
    if (input_char != specificByte)
    {
        fputc(input_char, output_fp);
    }
    else
    {
        /* do something with input_char */
    }
}

これは、バッファから一度に 1 文字ずつ読み取るため、コストがかかる可能性があるため、理論的には非効率的です。ただし、多くのアプリケーションでは、特にファイルの読み取りが C 標準ライブラリによってバッファリングされるため、これは問題なく実行されます。

効率を重視し、ファイル関数への呼び出しを最小限に抑えたい場合は、次のようなものを使用してください。

/* Don't loop through the chars just to find out the file size. Instead, use
 * stat() to find out the file size and allocate that many bytes into array.
 */
char* array = (char*) malloc(file_size);
fread(array, sizeof(char), file_size, input_fp);

/* iterate through the file buffer until you find the byte you're looking for */
for (char* ptr = array; ptr < array + file_size; ptr++);
{
    if (*ptr == specificByte)
    {
        break;
    }
}

/* Write everything up to ptr into the output file */
fwrite(array, sizeof(char), ptr - array, output_fp);

/* ptr now points to the byte you're looking for. Manipulate as desired */
于 2011-04-18T13:52:53.913 に答える
0

一度にファイル全体を読み取る必要がない場合は、固定サイズのバッファーを割り当てて、malloc完全に回避してください。動的メモリ管理をいじる必要がない場合は、動的メモリ管理をいじらないでください。

#define PAGE_SIZE ... // however big a chunk you process at a time
...
unsigned char inbuf[PAGE_SIZE];
unsigned char outbuf[PAGE_SIZE];

FILE *input_stream = fopen(...);
FILE *output_stream = fopen(...);

while (fread(inbuf, sizeof inbuf, 1, input_stream))
{
  unsigned char *r = inbuf, *w = outbuf;
  while (r != inbuf + sizeof inbuf && *r != specificByte)
    *w++ = *r++;
  fwrite(outbuf, (size_t) (w - outbuf), 1, output_stream);
  if (*r == specific_byte)
    break;
}
于 2011-04-18T15:08:39.570 に答える
0

1 つの方法を次に示します。

int putResult = 0;

for(int i = 0 ; i < BUFFER_SIZE && buffer[i] != specificByte && putResult != EOF ; ++i)
{
    putResult = fputc(buffer[i]);
}
if (putResult == EOF)
{
    // Deal with the error (in errno)
}

for 条件は、次の場合にループを終了します。

  • iバッファの最後にヒット
  • 特定のバイトがバッファ内にある
  • fputc()エラーを返します。
于 2011-04-18T14:09:10.480 に答える