This is a follow up question to How to speed up writing a file to a WifiClient?
I modified the old code to read from one Stream
and write to another which looked like this and worked fine albite being a bit slow
while (file.available() > 0)
{
client.print((char)file.read());
}
client.flush();
to use a buffer, like so
char buffer[300];
size_t bufferSize = sizeof(buffer);
// ...
while (file.available() > 0)
{
memset(buffer, 0, bufferSize);
file.read(buffer, bufferSize);
client.print(buffer);
}
client.flush();
Now, if the buffer size is> 15 (in the above case, it's 300), two additional characters Øb
are introduced after the buffer size amount of characters. If the buffer size is <= 15, this does not happen.
If the file to be read contains abcdefg
repeated several times, I get the following result for a buffer size of 32:
|-------- 32 characters -------|Øb|-------- 32 characters -------|Øb|-----
abcdefgabcdefgabcdefgabcdefgabcdØbefgabcdefgabcdefgabcdefgabcdefgaØbbcdefg
What's causing those additional characters to appear?
The above output is produced in the browser If I do not specify a charset. if I do, I get �
instead of Øb
.
2 Answers 2
Try recording the actual number of bytes read and only write that number of bytes:
size_t nr = file.read(buffer, bufferSize);
client.write(buffer, nr);
-
That worked, btw. what's the matter with the downvotes? How can I improve my questions?cross– cross2016年10月27日 12:26:50 +00:00Commented Oct 27, 2016 at 12:26
-
@cross Who knows? This place can be a bit fickle sometimes...Majenko– Majenko2016年10月27日 13:00:47 +00:00Commented Oct 27, 2016 at 13:00
-
1Since you are doing this for speed drop the
memset()
it's a waste of CPU cycles in this situationAndrew– Andrew2016年10月27日 13:28:06 +00:00Commented Oct 27, 2016 at 13:28 -
You are quite right there. I have removed it from my example for clarification too.Majenko– Majenko2016年10月27日 13:28:51 +00:00Commented Oct 27, 2016 at 13:28
If the buffer is full of data then there is no null terminator on your data to output, the client.print will keep going past the end of the buffer until it hits a 0. Because of the way the compiler is placing things in memory you happen to always get 0b and nothing else (does your code happen to have some other variable with a value of 11?)
There are two solutions: Either only output the number of bytes you read (in which case the memset instruction is no longer needed) or limit the file.read to one less than your buffer size so that there is always a 0 left at the end of the buffer.
const int buffersize = 32;
char buffer[buffersize];
while (file.available() > 0)
{
int bytes = file.read(buffer, bufferSize);
client.write(buffer,bytes);
}
or
while (file.available() > 0)
{
memset(buffer, 0, bufferSize);
file.read(buffer, bufferSize-1);
client.print(buffer);
}
Also it's more a personal preference than a requirement but I don't like to use sizeof(<array>)
, it only works within the same scope as the array definition and doesn't work if the array is passed to a function. This site is full of examples of people getting caught out by that and wondering why their array is always giving them a size of 4. So while it works fine in this instance I avoid using it if at all possible.
-
I am aware of the pitfalls of
sizeof
and had tried it with a macro definition to double check, but the result was the same. I will try your suggestions regarding the null termination. The question still stands: Why does this only happen ifbufferSize > 15
?cross– cross2016年10月27日 11:45:07 +00:00Commented Oct 27, 2016 at 11:45 -
If the issue does turn out to be a lack of termination (the second option is the best way to prove that) then the reason is that the behavior without the termination is completely undefined. It could well be that with a smaller buffer the compiler placed things in memory in a different way such that there always happened to be a 0 in the byte after the buffer.Andrew– Andrew2016年10月27日 11:51:34 +00:00Commented Oct 27, 2016 at 11:51