Get number of not null bytes fread() - c

I am developing simple server-client app and now I have problem with reading file on server side. Here is code:
int size;
for (i = 0; i < parts; i++) {
size = fread(buffer, 1, 256, file);
printf("size: %i \n", size);
send(sockfd, buffer, size, 0);
/* ... */
}
I supposed that if fread() can read only (for example) 50 bytes, then size will be 50, but it's not true. It's still 256.
Is there any simple way how to get number of not null bytes?

If you want to have the length of the buffer after fread(), why don't use strlen()?
Also, its probably not a good idea to depend on the return value of fread() for number of bytes read. In case, if the size (second argement) is not 1, it may cause you trouble with actual bytes count.

size_t fread(void * ptr, size_t size, size_t nmemb, FILE * stream) returns the number of elements successfully read. In OP's case, a return value of 256 means 256 char are read.
A simple way to get number of "not null bytes" would entail a simple loop.
size_t size = fread(buffer, 1, 256, file);
size_t count = 0;
for (size_t i = 0; i< size; i++) {
if (buffer[i] == '\0') count++;
}
number_of_not_null_bytes = count;
As #Ron Burk says, the \0 may be interspersed in buffer and need select handling before passing on to send().

Related

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.

How to use read() to get input of unknown length from stdin

Until now, whenever I wanted to get user input from stdin I used scanf() but this time I can't and have to use read().
Usually, to get input from stdin using read I use:
char buf[128];
read(0, buf, sizeof(buf));
But this time I don't have any length limit to the input and I want to allow input with arbitrary size. In the past I used scanf for this, like so:
char *user_input;
scanf("%ms", &user_input);
How can I do this with read()?
Note: safety isn't important here
The function read returns the number of read bytes. You can take advantage of this information and loop until you read 0 bytes, that is, read returns 0.
char buf[BUF_SIZE]; // Set BUF_SIZE to the maximum number of character you expect to read (e.g. 1000 or 10000 or more).
int bytes_to_read, total_read_bytes, read_bytes;
// Number of bytes to read at each iteration of the loop.
bytes_to_read = 128;
// The following variable counts the number of total read bytes.
total_read_bytes = 0;
while ((read_bytes = read(0, buf + total_read_bytes, bytes_to_read) != 0) {
if (read_bytes < 0) {
// read() may return -1. You can look at the variable errno to
// have more details about the cause of the error.
return -1;
}
total_read_bytes += read_bytes;
}
Notice that read does not automatically append the null terminator \0 to buf, that is, buf is not a string until you explicitly add \0 at the end of it.
...
// Making buf a string.
buf[total_read_bytes] = '\0';
...
one way is run a loop with getchar() function and keep rading the characters into an array. check the array size with each iteration ,Once the array is full, reallocate it to a larger size. OR use the The getline() function.
link for getline()
Check the below programme .
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char *lines = NULL;
size_t n = 0;
ssize_t res = getline(&line, &n, stdin);
free(line);
}

Using read() system call

For an assignment in class we were tasked with using the read() function to read a file containing numbers. While I was able to read the numbers into a buffer I have been unable to move them from the buffer into a char *array so that they can be easily accessed and sorted. Any advice is appreciated.
int readNumbers(int hexI, int MAX_FILENAME_LEN, int **array, char* fname) {
int numberRead = 0, cap = 2;
*array = (int *)malloc(cap*sizeof(int));
int n;
int filedesc = open(fname, O_RDONLY, 0);
if(filedesc < 0){
printf("%s: %s\n", "COULD NOT OPEN", fname);
return -1;
}
char * buff = malloc(512);
buff[511] = '\0';
while(n = read(filedesc, buff+totaln, 512 - totaln) > 0) //Appears to loop only once
totaln += n;
int len = strlen(buff);
for (int a = 0; a < len; a++) { //Dynamically allocates array according to input size
if ((&buff[a] != " ") && (&buff[a] != '\n'))
numberRead++;
if (numberRead >= cap){
cap = cap*2;
*array = (int*)realloc(*array, cap*sizeof(int));
}
}
int k = 0;
while((int *)&buff[k]){ //attempts to assign contents of buff to array
array[k] = (int *)&buff[k];
k++;
}
}
Your use of read() is wrong. There are at least two serious errors:
You ignore the return value, except to test for end-of-file.
You seem to assume that read() will append a nul byte after the data it reads. Perhaps even that it will pad out the buffer with nul bytes.
If you want to read more data into the same buffer after read() returns, without overwriting what you already read, then you must pass a pointer to the first available position in the buffer. If you want to know how many bytes were read in total, then you need to add the return values. The usual paradigm is something like this:
/*
* Read as many bytes as possible, up to buf_size bytes, from file descriptor fd
* into buffer buf. Return the number of bytes read, or an error code on
* failure.
*/
int read_full(int fd, char buf[], int buf_size) {
int total_read = 0;
int n_read;
while ((n_read = read(fd, buf + total_read, buf_size - total_read)) > 0) {
total_read += n_read;
}
return ((n_read < 0) ? n_read : total_read);
}
Having done something along those lines and not received an error, you can be assured that read() has not modified any element of the buffer beyond buf[total_read - 1]. It certainly has not filled the rest of the buffer with zeroes.
Note that it is not always necessary or desirable to read until the buffer is full; the example function does that for demonstration purposes, since it appears to be what you wanted.
Having done that, be aware that you are trying to extract numbers as if they were recorded in binary form in the file. That may indeed be the case, but if you're reading a text file containing formatted numbers then you need to extract the numbers differently. If that's what you're after then add a string terminator after the last byte read and use sscanf() to extract the numbers.

What could cause fwrite() function so slow

I'm writing chucks of chat *ptr into file, but it takes me so long to finish.
I don't know why.
for(int i = 1; i < 64048; i++){
if(ptr[i] != NULL){
fwrite(ptr[i], 1, strlen(ptr[i])-6, file);
free(ptr[i]);
}
}
there is array of char pointers storing 8186 bytes, and I want to write into file, but the time is so long.
I have 64048 chunks of string need to write into file.
What could cause the slowing fwrite() ??
thank you
OP is using wrong method to size fwrite(), amongst other small errors.
If "array of char pointers storing 8186 bytes" means
1 each char array has 8186 significant bytes of data, use size 8186.
2 each char array is a NUL terminated string, then a test needs to occur to insure each is at least length 6. Not sure what this 6 is all about.
Note: size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream )
I suspect that the OP's - 6 is causing a problem when strlen(ptr[i]) is less than 6. This would make the negative difference a very large size_t, which is usually unsigned for count in fwrite().
for(int i = 0; i < 64048; i++){ // start at 0
if(ptr[i] != NULL){
int result;
result = fwrite(ptr[i], 1, 8186, file);
if (result != 8186) ; handle error;
// or
size_t len = strlen(ptr[i]) + 1; /// Add 1 for the NUL byte
if (len < 6) ; handle error of whatever the OP's 6 is about.
result = fwrite(ptr[i], 1, len, file);
if (result != len) ; handle error;
free(ptr[i]);
}
}

Why does this code not output the expected output?

This can be a good question for finding bugs.
No? Okay for beginners at least.
#define SIZE 4
int main(void){
int chars_read = 1;
char buffer[SIZE + 1] = {0};
setvbuf(stdin, (char *)NULL, _IOFBF, sizeof(buffer)-1);
while(chars_read){
chars_read = fread(buffer, sizeof('1'), SIZE, stdin);
printf("%d, %s\n", chars_read, buffer);
}
return 0;
}
Using the above code, I am trying to read from a file using redirection ./a.out < data. Contents of input file:
1line
2line
3line
4line
But I am not getting the expected output, rather some graphical characters are mixed in.
What is wrong?
Hint: (Courtesy Alok)
sizeof('1') == sizeof(int)
sizeof("1") == sizeof(char)*2
So, use 1 instead :-)
Take a look at this post for buffered IO example using fread.
The type of '1' is int in C, not char, so you are reading SIZE*sizeof(int) bytes in each fread. If sizeof(int) is greater than 1 (on most modern computers it is), then you are reading past the storage for buffer. This is one of the places where C and C++ are different: in C, character literals are of type int, in C++, they are of type char.
So, you need chars_read = fread(buffer, 1, SIZE, stdin); because sizeof(char) is 1 by definition.
In fact, I would write your loop as:
while ((chars_read = fread(buffer, 1, sizeof buffer - 1)) > 0) {
buffer[chars_read] = 0; /* In case chars_read != sizeof buffer - 1.
You may want to do other things in this case,
such as check for errors using ferror. */
printf("%d, %s\n", chars_read, buffer);
}
To answer your another question, '\0' is the int 0, so {'\0'} and {0} are equivalent.
For setvbuf, my documentation says:
The size argument may be given as zero to obtain deferred optimal-size buffer allocation as usual.
Why are you commenting with \\ instead of // or /* */? :-)
Edit: Based upon your edit of the question, sizeof("1") is wrong, sizeof(char) is correct.
sizeof("1") is 2, because "1" is a char array containing two elements: '1' and 0.
Here's a byte-by-byte way to fread the lines from a file using redirection ./a.out < data.
Produces the expected output at least ... :-)
/*
Why does this code not output the expected output ?,
http://stackoverflow.com/questions/2378264/why-does-this-code-not-output-the-expected-output
compile with:
gcc -Wall -O3 fread-test.c
create data:
echo $'1line\n2line\n3line\n4line' > data
./a.out < data
*/
#include <stdio.h>
#define SIZE 5
int main(void)
{
int i=0, countNL=0;
char singlechar = 0;
char linebuf[SIZE + 1] = {0};
setvbuf(stdin, (char *)NULL, _IOFBF, sizeof(linebuf)-1);
while(fread(&singlechar, 1, 1, stdin)) // fread stdin byte-by-byte
{
if ( (singlechar == '\n') )
{
countNL++;
linebuf[i] = '\0';
printf("%d: %s\n", countNL, linebuf);
i = 0;
} else {
linebuf[i] = singlechar;
i++;
}
}
if ( i > 0 ) // if the last line was not terminated by '\n' ...
{
countNL++;
linebuf[i] = '\0';
printf("%d: %s\n", countNL, linebuf);
}
return 0;
}
char buffer[SIZE + 1] = {0};
This isn't doing what you expect, it is making buffer point to a one byte region in the programs constant data segment. I.e this will corrupt SIZE amount of bytes and possibly cause a memory protection fault. Always initialize C strings with strcpy() or equivalent.

Resources