streams binary and text

B

Bill Cunningham

Do the functions fread and fwrite specifically deal with binary data and
not text? Can fgetc and fputc be used to deal with binary or are they only
for text streams. I know *nixs do not discriminate in texual or binary data
but the 'b' in fopen statements for opening streams is portabile across
platforms. But with a linux can I alter the data of an AVI? It is binary
isn't it and I would want to open a stream and use fprintf would I with the
%x conversion.

Bill
 
B

Bill Cunningham

Don't make my brown eyes China Blue said:
[snip]

Whether
the resulting file is still an AVI depends on whether your changes
conform to the AVI format.

Say the file signature of an AVI is RIFF which represents four bytes. I
have to find where that is in the stream with for example fseek. How would I
do that? Simple enough with a hex editor but lives streams is harder.

Bill
 
M

Malcolm McLean

בת×ריך ×™×•× ×¨×‘×™×¢×™, 29 ב×וגוסט 2012 03:27:46 UTC+1, מ×ת Bill Cunningham:
Say the file signature of an AVI is RIFF which represents four bytes. I
have to find where that is in the stream with for example fseek. How would I
do that? Simple enough with a hex editor but lives streams is harder.
/*
find a tag / string in a stream.
Params: fp - pointer to open file
tag - return for tag.
Returns: 0 = no tag in file, 1 = seek to tag , -1 error or some sort
Notes: Not tag structure aware, so some tags may be be spurious.
Notes: untested
*/
int seektag(FILE *fp, char *tag)
{
int ch;
char *buff;
int N;
long pos;

N = strlen(tag);
buff = malloc(N);
if(!buff)
return -1;
while( (ch = fgetc(fp)) != EOF)
{
if(ch == buff[0])
{
ungetc(ch, fp);
pos = ftell(fp);
if( fread(buff, 1, N, fp) != N)
{
free(buff);
return -1;
}
if(!strncmp(buff, tag, N))
{
fseek(fp, pos, SEEK_SET);
free(buff);
return 1;
}
}
}
/* weve got to the end without finding the tag */
free(buff);
if(ferror(fp))
return -1;
return 0;
}
 
B

Barry Schwarz

?????? ??? ?????, 29 ??????? 2012 03:27:46 UTC+1, ??? Bill Cunningham:
Say the file signature of an AVI is RIFF which represents four bytes. I
have to find where that is in the stream with for example fseek. How would I
do that? Simple enough with a hex editor but lives streams is harder.
/*
find a tag / string in a stream.
Params: fp - pointer to open file
tag - return for tag.
Returns: 0 = no tag in file, 1 = seek to tag , -1 error or some sort
Notes: Not tag structure aware, so some tags may be be spurious.
Notes: untested
*/
int seektag(FILE *fp, char *tag)
{
int ch;
char *buff;
int N;
long pos;

N = strlen(tag);
buff = malloc(N);
if(!buff)
return -1;
while( (ch = fgetc(fp)) != EOF)
{
if(ch == buff[0])

At this point, isn't buff[0] indeterminate during the first iteration
of the while loop? buff doesn't receive a value until the fread
below.
 
B

Ben Bacarisse

Malcolm McLean said:
בת×ריך ×™×•× ×¨×‘×™×¢×™, 29 ב×וגוסט 2012 03:27:46 UTC+1, מ×ת Bill Cunningham:
/*
find a tag / string in a stream.
Params: fp - pointer to open file
tag - return for tag.
Returns: 0 = no tag in file, 1 = seek to tag , -1 error or some sort
Notes: Not tag structure aware, so some tags may be be spurious.
Notes: untested
*/
int seektag(FILE *fp, char *tag)

A note the anyone learning C: Malcolm objects to both "const" and
"size_t" so this function won't work with const char * arguments
(without a cast) and it contains a lot of needless signed/unsigned int
conversions. I'd add const above and declare N below as size_t.

(Malcolm: I'm not trying to convert you, but I think your opinion is
singular enough to merit being pointed out.)
{
int ch;
char *buff;
int N;
long pos;

N = strlen(tag);
buff = malloc(N);
if(!buff)
return -1;
while( (ch = fgetc(fp)) != EOF)
{
if(ch == buff[0])

Typo: you mean tag[0] of course.
{
ungetc(ch, fp);
pos = ftell(fp);
if( fread(buff, 1, N, fp) != N)
{
free(buff);
return -1;
}
if(!strncmp(buff, tag, N))
{
fseek(fp, pos, SEEK_SET);
free(buff);
return 1;
}
}
}
/* weve got to the end without finding the tag */
free(buff);
if(ferror(fp))
return -1;
return 0;
}

I think this is working too hard. I'd match as we go, mainly because it
avoid using a buffer. I think the result is clearer:

int seektag(FILE *fp, const char *tag)
{
int ch;
size_t match = 0, tlen = strlen(tag);
long pos;

while (match < tlen && (ch = fgetc(fp)) != EOF)
if (ch == tag[match]) {
if (match == 0) {
ungetc(ch, fp);
pos = ftell(fp);
fgetc(fp);
}
match += 1;
}
else match = 0;

if (match == tlen) {
fseek(fp, pos, SEEK_SET);
return 1;
}
if (ferror(fp))
return -1;
return 0;
}

I'd be inclined protect against empty tag strings, but your code did not
so I copied that decision.

It's even simpler if you are prepared to rely on SEEK_CUR (i.e. a binary
stream):

int seektag(FILE *fp, const char *tag)
{
int ch;
size_t match = 0, tlen = strlen(tag);

while (match < tlen && (ch = fgetc(fp)) != EOF)
if (ch == tag[match])
match += 1;
else match = 0;

if (match == tlen) {
fseek(fp, -(long)tlen, SEEK_CUR);
return 1;
}
if (ferror(fp))
return -1;
return 0;
}
 

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