简体   繁体   中英

Read N bytes from a file and print it using read() and write()

I'm trying to read a program that reads N bytes from a file using read() and prints them in STDOUT using write(). The thing is, the user can also especify the blocksize, by default it's 1024 and can only get up to 1048576. I have to store what I read in a buffer, but that buffer can't be the same size as the bytes that I have to read because, otherwise, I could potentially create a buffer too large for the stack size. Therefore, I create a buffer as large as the blocksize so I just read until it's full, write and then read again to the beginning of the buffer.

The problem with all this is that it definetely doesn't work as intended and I'm pretty sure there's gotta be an easier way to do this.

Relevant code:

void run_hd_b (int b, int fd, int BSIZE){
    int res_read; //result from write
    int res_write; //result from read
    int read_bytes = 0;
    char buffer[BSIZE];
    int i = 0;

    int count = 0;
    if (b < BSIZE) count = b;
    else count = BSIZE;

    while (read_bytes < b && (res_read = read(fd, &buffer[i], count)) != 0){ 
        if (res_read == BSIZE){
            i = 0;
        }
        else i = res_read;

        read_bytes += res_read;
        while((res_write = write(1, buffer, res_read)) < res_read);
    }
}

Below is a revised version of your loop that compiles (and probably works) followed by some notes.

#include <assert.h>
#include <unistd.h>

void run_hd_n (int n, int fd, int BSIZE) {
  int res_read;
  char buffer[BSIZE];

  // can only get up to 1048576
  assert(BSIZE <= 1048576);

  for( int read_bytes=0; read_bytes < n; read_bytes += res_read ) {
    if( (res_read = read(fd, buffer, BSIZE)) < BSIZE ) { 
      if( res_read == 0 ) return; // EOF or error
    }
    if( write(STDOUT_FILENO, buffer, res_read) < res_read ) return;
  }
}
  • I changed b to n out of convention.
  • Stick close to the standard. read (2) and write (2) take size_t , not int . How will your program react if called with n == -1 ?
  • If you have a known imposed constraint, include it somewhere. You asserted a maximum size for BSIZE; I used assert to enforce it.
  • I couldn't tell if your question was about allocating the space or copying the data. I chose to address the latter.
  • It's not an error to read less than the full size of the buffer. No need to putz with count . Just read and see if you got anything.
  • You've written an I/O function with a void return type. How will the caller learn what happened? I would return res_read and let the caller test if he read as many as requested, else consult errno .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM