开发者

How to read one byte at a time from an array?

开发者 https://www.devze.com 2023-02-26 22:56 出处:网络
In C, how would I read one byte from an array of bytes, put that into a file, and then loop that over and over until I find a specific byte I want to stop reading at?

In C, how would I read one byte from an array of bytes, put that into a file, and then loop that over and over until I find a specific byte I want to stop reading at?

Example:

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(?,?,?,?); 
}

That's not the exact code I'm using, but I just wanted to put something out there to show where I'm having the problem.

Wou开发者_如何学Cld it possibly be better to just read straight from the file instead of putting the bytes into an array?


If I may make a suggestion, It would probably be much more efficient to read through the array until you find your stop byte, then write the array from the start until that stop byte in a single I/O.


Here is one full example with fread / fwrite.

But I am not sure is there any sense to read the whole file into memory and then write it to file again while you can just write the the output file at the same time you are reading the input file like some of the earlier examples are demonstrating.

I am not even sure if this is more efficient than using fgetc & fputc but at least the files are read and written in one function call.

#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;
}


A simple but effective way of doing this is to avoid reading into memory at all, and just do the following:

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

This is theoretically inefficient, since you're reading one character at a time from a buffer, which could be costly. However, for many applications this will run just fine, especially since the file reads are buffered by the C standard library.

If you do care about efficiency and want to minimize calls into file functions, use something like the following.

/* 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 */


Here's one way:

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)
}

The for condition exits the loop if

  • i hits the end of the buffer
  • the specific byte is found in the buffer
  • fputc() returns an error.


If you don't have to read the entire file in at a time, just allocate a fixed-size buffer and avoid malloc altogether; don't mess with dynamic memory management if you don't have to mess with dynamic memory management.

#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;
}
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号