How to display binary file contents if it is stored in an integer array?

L

loudking

Dear all,

I am writing a client-server application and the client should upload
a file to the server, then the server should display the content of
the file in stdout.

Because I have to deal with binary files, I cannot use character
strings, so I chose integer array instead.

But the problem is that how can I display them in stdout? I tried "%c"
and "%d", but neither will work.

Client side:

int fdin;
int *up_file;
struct stat buf;

fdin = open(file, O_RDONLY);
fstat(fdin, &buf);
up_file = (int *)malloc(buf.st_size * sizeof(int));
up_file = mmap(0, buf.st_size, PROT_READ, MAP_SHARED, fdin, 0)

Server Side:

for (int i = 0; i < iarray_len; i++)
printf("%d", iarray_val);

The uploading procedure will be handled by Sun RPC.

Thanks!
 
C

Chris Dollin

loudking said:
I am writing a client-server application and the client should upload
a file to the server, then the server should display the content of
the file in stdout.

(The details of the client-server interaction are off-topic here.)
Because I have to deal with binary files, I cannot use character
strings, so I chose integer array instead.

Why not a character array?
But the problem is that how can I display them in stdout? I tried "%c"
and "%d", but neither will work.

Both will work (for some value of "work") /if you do them right/.

What do you expect to display on stdout? The characters, the decimal
representation of their values, or what?

What actually happened?
Client side:

int fdin;
int *up_file;
struct stat buf;

fdin = open(file, O_RDONLY);
fstat(fdin, &buf);

Non-standard magic; I can't speak to it.
up_file = (int *)malloc(buf.st_size * sizeof(int));

You don't need, and should not use, that cast, if you're programming
in C.

Assuming that `fstat` puts the file size in `buf.st_size`, you
should realise that you're probably allocating `sizeof(int)`
times too much space.

You should check that `malloc` hasn't returned null.
up_file = mmap(0, buf.st_size, PROT_READ, MAP_SHARED, fdin, 0)

More unspeakable magic. It doesn't seem to have anything to do
with `up_file`. Is that deliberate?
Server Side:
for (int i = 0; i < iarray_len; i++)
printf("%d", iarray_val);


Presumably some more magic has copied the file mentioned above
into `iarray_val`, whose type you have not told us.

If -- I say "if" because there is so much magic buzzing around
my ears are dizzy -- `iarray_val` (a name from hell, surely) has
the bytes of the file you mention, you're going to be printing
out (the decimal representation of) `sizeof(int)` bytes at a
time. So you'll see numbers like 12386359126 rather than 42
and 96.
The uploading procedure will be handled by Sun RPC.

Not just magic -- sorcery!
 
L

loudking

Well, what I actually mean is that the client is going to upload a
file to the server and the server will store the file content in the
memory. Later, the client will fetch the file from the server and
display it in stdout.

So the test script will be

../client add server test.pdf
../client fetch server > test_2.pdf
diff test.pdf test_2.pdf

So in my case, neither printf("%c") nor printf("%d") will work ...

int i;
for (i=0; i < integer_array_len; i++)
printf("%c", integer_array_val);
 
N

Nick Keighley

this may be off-topic to comp.lang.c. comp.programming may be better.
I am writing a client-server application and the client should upload
a file to the server, then the server should display the content of
the file in stdout.

Because I have to deal with binary files, I cannot use character
strings, so I chose integer array instead.

so on the server you load the data into an int[]. Consider using
unsigned char[].

But the problem is that how can I display them in stdout? I tried "%c"
and "%d", but neither will work.

what does "will work" mean? Did it display anything? Or just not what
you
expected.
Client side:

int fdin;
int *up_file;
struct stat buf;

fdin = open(file, O_RDONLY);
fstat(fdin, &buf);
up_file = (int *)malloc(buf.st_size * sizeof(int));
up_file = mmap(0, buf.st_size, PROT_READ, MAP_SHARED, fdin, 0)

lots of not standard C stuff there.

Server Side:

for (int i = 0; i < iarray_len; i++)
printf("%d", iarray_val);

The uploading procedure will be handled by Sun RPC.


would %x (hex) in the printf() solve your problem?
 
L

loudking

I finally realize that I should use write(STDOUT_FILENO) instead of
printf !!

Thank you for your messages!
 
R

Richard Tobin

loudking said:
I finally realize that I should use write(STDOUT_FILENO) instead of
printf !!

It seems unlikely that this is really the solution. Apart from
buffering and the text/binary distinction, there is little difference
between using C's fwrite() and Unix's write(). Buffering can be
defeated with fflush(), and on a Unix system there's no difference
between text and binary mode.

-- Richard
 
C

Chris Dollin

loudking said:
Well, what I actually mean is that the client is going to upload a
file to the server and the server will store the file content in the
memory. Later, the client will fetch the file from the server and
display it in stdout.

So the test script will be

./client add server test.pdf
./client fetch server > test_2.pdf
diff test.pdf test_2.pdf

So in my case, neither printf("%c") nor printf("%d") will work ...

You keep saying that, but you don't say why you think it's true.
int i;
for (i=0; i < integer_array_len; i++)
printf("%c", integer_array_val);


Did you read Chris-Dollin-at-HP's reply? Because he points out that
if you write the wrong thing out, you'll get the wrong answer.

Try a simple test case first, for heavens sake. Make sure you can
write out zero bytes, one byte, two, three, four; five bytes, six
bytes, seven bytes, eight. At the moment your problem is nothing to
do with client-server communication: it's about rendering data to
the output.

Try some data like:

unsigned char someData[] =
{ 1, 2, 0, 17, 127, 128, 254, 255, 31, 32 };

and write it out with loops like:

for (i = 0; i < sizeof (someData); i += 1)
writeOutMyData( &someData[0], &someData );
 
M

Martin Ambuhl

loudking said:
Dear all,

I am writing a client-server application and the client should upload
a file to the server, then the server should display the content of
the file in stdout.

Because I have to deal with binary files, I cannot use character
strings, so I chose integer array instead.

char is an integer type. You are guaranteed that you can store any
integral value in the range 0...255 in an unsigned char, and -127...127
in a signed char. Plain char could be either. There is nothing about a
stream being 'binary' that keeps you from using char arrays.

But the problem is that how can I display them in stdout? I tried "%c"
and "%d", but neither will work.

You display them as they are meant to be interpreted. "Neither will
work" is a useless description of your problem.
Client side:

int fdin;
int *up_file;
struct stat buf;

"struct stat" is, of course, not provided by any standard C header or
library.
fdin = open(file, O_RDONLY);

"open" is, of course, not provided by any standard C header or library.
Nor is "O_RDONLY". The standard function is fopen, when the type of
fdin would be "FILE *", not "int". The standard attempt to open fdin
for binary input would be
#include <stdio.h>
{
FILE *fdin;
fdin = fopen(file, "rb");
/* error checking here */
}
Note the "b" for binary. Perhaps your non-standard "O_RDONLY" needs an
additional flag for binary input.

fstat(fdin, &buf);
up_file = (int *)malloc(buf.st_size * sizeof(int));

Had you followed this newsgroup at all before posting, expected behavior
in all newsgroups, you would know that casting the return value is
unneeded and poor programming practice.
#include <stdlib.h>
{
T* up_file; /* char T is the type of the desired array */
up_file = malloc(buf.st_size * sizeof *up_file);
/* error checking here */
}
up_file = mmap(0, buf.st_size, PROT_READ, MAP_SHARED, fdin, 0)

"mmap" is, of course, not provided by any standard C header or library.
Nor are "PROT_READ" or "MAP_SHARED".

Server Side:

for (int i = 0; i < iarray_len; i++)
printf("%d", iarray_val);


What doesn't work (other than the declaration of 'int' here if your
compiler is a C89 one)? You store values in an int array, you fprintf
the contents of that int array as ints. If that doesn't "work" your
implementation is hopelessly broken.

I suspect that the reality is that you really haven't thought through
your problem enough to know what correct behavior might be.

The uploading procedure will be handled by Sun RPC.

Who cares?
 
M

Martin Ambuhl

loudking said:
I finally realize that I should use write(STDOUT_FILENO) instead of
printf !!

If "write(STDOUT_FILENO)" is right, then you are in the wrong newsgroup.
That is not standard C and is an implementation-provided invasion of
the program's namespace.
 
K

Keith Thompson

loudking said:
for (int i = 0; i < iarray_len; i++)
printf("%d", iarray_val);

[...]

Successive printfs will print successive values from your array with
no blanks between them. For example, if the values in your array are

123, 234, -987654321, 0

then your output will be:

123234-9876543210

The output will be identical if your first two numbers are any of:

1, 23234
12, 3234
1232, 34
12323, 4

Perhaps that's what you meant when you told us that it doesn't work.
Tell us *how* it doesn't work would have been extremely helpful.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,731
Messages
2,569,432
Members
44,832
Latest member
GlennSmall

Latest Threads

Top