
Signature
Rhino
---
rhino1 AT sympatico DOT ca
"There are two ways of constructing a software design. One way is to make it
so simple that there are obviously no deficiencies. And the other way is to
make it so complicated that there are no obvious deficiencies." - C.A.R.
Hoare
> I have to admit I've never fully understood the different Java I/O streams
> so I've been reviewing them in the Java Tutorial. Am I correct in believing
> that the definition of the getScratchpad() and setScratchpad() methods means
> that I am definitely dealing with byte streams and that classes for
> reading/writing character streams are not something I should even consider
> for my program?
Characters are a higher-level abstraction than bytes. This database API
of yours provides the ability to work with byte arrays, which means you
can store anything you like there. The database apparently doesn't
intend to try to interpret what you put into the field, so storing and
retrieving data is entirely up to you.
However, there are several ways of storing characters as bytes (almost
analogous to how there are several ways of storing images -- gif, jpeg,
etc.). It's important to be consistent in how you do it. The ways of
storing characters as binary data are called encodings. Common
encodings for characters include ASCII, UTF-8, or ISO8859-1.
> The reason I am asking is that I would like to be able to write both
> primitives and Strings to my scratchpad and I'm having trouble finding an
> appropriate way to both read and write a String using the
> bytestream-oriented classes.
If you've got a String, you can get a byte[] from it using:
byte[] bytes = myString.getBytes("UTF-8");
setScratchPage(bytes);
and then:
byte[] bytes = getScratchPad();
String myString = new String(bytes, "UTF-8");
(And, of course, UTF-8 can be replaced with any other character encoding
name recognized by Java, as well.) Since your database API is dealing
with in-memory representations, you don't really gain too much by using
streams for this task... but if you want to use a stream, then it looks
like this:
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
OutputStreamWriter writer =
new OutputStreamWriter(byteOut, "UTF-8");
try
{
writer.write(myString);
}
finally
{
writer.close();
}
byte[] bytes = byteOut.toByteArray();
And...
ByteArrayInputStream byteIn =
new ByteArrayInputStream(getScratchpad());
InputStreamReader reader =
new InputStreamReader(byteIn, "UTF-8");
StringBuffer sb = new StringBuffer();
try
{
int i;
while ((i = reader.read()) != -1)
{
sb.append((char) i);
}
}
finally
{
reader.close();
}
String myString = sb.toString();
As a third option, if you're mixing primitives and text together, you
may want to look at DataOutputStream. It is more limited in how it can
choose forms of storage (it only allows UTF-8 preceded by a 16-bit byte
count), but makes it easy to read and write various types. That looks
like this:
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
DataOutputStream dataOut = new DataOutputStream(byteOut);
try
{
dataOut.writeUTF(myString);
dataOut.writeInt(42);
dataOut.writeDouble(3.14159265);
}
finally
{
dataOut.close();
}
byte[] bytes = byteOut.toByteArray();
And:
ByteArrayInputStream byteIn = new ByteArrayInputStream();
DataInputStream dataIn = new DataInputStream(byteIn);
try
{
myString = dataIn.readUTF();
myInt = dataIn.readInt();
myDouble = dataIn.readDouble();
}
finally
{
dataIn.close();
}
> For example, the DataOutputStream class has a method called writeChars()
> which seems to write a String to a byte array just fine. But I can't find
> any method to read that same String back from the byte array in the
> DataInputStream class. I've tried to do a readChar() loop instead and got
> EOFException.
I can't explain your EOFException without seeing the code. That should
have worked as well.
> I tried to do a readFully() but that didn't work either; I
> don't remember what error that causes.
It's wrong, in any case. readFully reads bytes. It is possible to
convert those bytes back into characters, but you're going the hard way
about it if you do so.

Signature
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.
Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
Rhino - 15 Mar 2005 20:39 GMT
> > I have to admit I've never fully understood the different Java I/O streams
> > so I've been reviewing them in the Java Tutorial. Am I correct in believing
[quoted text clipped - 32 lines]
> (And, of course, UTF-8 can be replaced with any other character encoding
> name recognized by Java, as well.)
Okay, that's fine so far but it is only writing a single String to the
scratchpad. I'm not quite clear on how I would write an int *and* a String
to the scratchpad and then parse the scratchpad to get the int and String
back out again. Or two Strings. Or a String, an int, and another String,
etc. I'm not clear on how you'd write the separate values to the scratchpad
and then find the start and end of each of the separate values in the
scratchpad when you tried reading it again.
Essentially, I want to be able to write a structure of some kind to the
scratchpad if that becomes necessary. Now, I know that structures translate
to classes and that there are streams for handling Objects, namely
ObjectInputStream and ObjectOutputStream but I'm not sure if these are
overkill in my situation. The different bits of data that I want to write to
the scratchpad are not necessarily going to be related in any significant
way so I don't know if I should be making a class just to contain them. I'd
be content with just being able to write any arbitrary number and
combination of primitives and Strings and then parse them back out again
when I need them. The scratchpad is typically intended for only a small
amount of data that needs to be saved across multiple iterations of a
function so I don't want to go crazy with structures, classes, etc. if it
isn't necessary.
> Since your database API is dealing
> with in-memory representations, you don't really gain too much by using
[quoted text clipped - 39 lines]
>
> String myString = sb.toString();
So, clearly, there is no problem with wrapping a Character Stream within a
Byte Stream.
> As a third option, if you're mixing primitives and text together, you
> may want to look at DataOutputStream. It is more limited in how it can
[quoted text clipped - 33 lines]
> dataIn.close();
> }
I suspect that the preceding is the way that I need to proceed then,
following this example to write and then read my ints, Strings, etc. from
the scratchpad. The only thing is that I get back to the problem I had
before: I can use DatatOutputStream.writeChars() to write a String but I
can't quite figure out how to parse the String back out with DataInputStream
since there doesn't seem to be a counterpart readChars() method for getting
a String from a byte array. Should I be using the String.getBytes("UTF-8")
method to do this??
> > For example, the DataOutputStream class has a method called writeChars()
> > which seems to write a String to a byte array just fine. But I can't find
[quoted text clipped - 4 lines]
> I can't explain your EOFException without seeing the code. That should
> have worked as well.
It might just have been a coding error on my part.
> > I tried to do a readFully() but that didn't work either; I
> > don't remember what error that causes.
>
> It's wrong, in any case. readFully reads bytes. It is possible to
> convert those bytes back into characters, but you're going the hard way
> about it if you do so.
Yeah, I thought so; that's why I abandoned trial-and-error methods at that
point and returned to the tutorial and this newsgroup ;-)
Okay, I'm going to go back and try some of these approaches now while I
await your reply to my followup questions.
Thanks for your help with this, Chris!
Rhino
Rhino - 15 Mar 2005 20:45 GMT
"> > As a third option, if you're mixing primitives and text together, you
> > may want to look at DataOutputStream. It is more limited in how it can
> > choose forms of storage (it only allows UTF-8 preceded by a 16-bit byte
[quoted text clipped - 41 lines]
> a String from a byte array. Should I be using the String.getBytes("UTF-8")
> method to do this??
Sorry, I just reread your remarks and the answer is obvious from your
example: instead of using writeChars() I should be using writeUTF() and its
counterpart readUTF() to get it out again.
That should solve all my problems and be as flexible as I need to do what I
want to do.
Okay, now I'm off to 'play' in full confidence that I know what to do ;-)
Thanks again for your help with this, Chris!
Rhino
Chris Smith - 15 Mar 2005 21:09 GMT
> I suspect that the preceding is the way that I need to proceed then,
> following this example to write and then read my ints, Strings, etc. from
[quoted text clipped - 4 lines]
> a String from a byte array. Should I be using the String.getBytes("UTF-8")
> method to do this??
You can use writeUTF and readUTF, and avoid writeChars entirely. The
problem with writeChars is that it gives no indication of how many
characters you intend to write, so you need to know that externally
somehow. writeUTF writes a byte count, which its counterpart readUTF is
capable of reading, and avoids the trouble on your part.

Signature
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.
Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation