public interface IonWriter extends Closeable, Flushable
WARNING: This interface should not be implemented or extended by code outside of this library. We still have some work to do before this interface is stable. See issue amznlabs/ion-java#10
A value is written via the set of typed write*()
methods such as
writeBool(boolean)
and writeInt(long)
.
Each of these methods outputs a single Ion value, and afterwards the writer
is prepared to receive the data for the next sibling value.
Any type annotations must be set before the value is written. Once the value has been written the "pending annotations" are erased, so they are must be set again if they need to be applied to the next value.
Similarly the field name must be set before the value is written (assuming the value is a field in a structure). The field name is also "erased" once used, so it must be set for each field.
To write a container, first write any annotations and/or field name
applicable to the container itself.
Then call stepIn(IonType)
with the desired container type.
Then write each child value in order.
Finally, call stepOut()
to complete the container.
Once all the top-level values have been written (and stepped-out back to
the starting level), the caller must close()
the writer
(or at least finish()
it) before accessing
the data written to the underlying data sink
(for example, via ByteArrayOutputStream.toByteArray()
).
The writer may have internal buffers and without closing or finishing it,
it may not have written everything to the underlying data sink. In addition,
flush()
isn't guaranteed to be sufficient for all implementations.
IonWriter
is a generic interface for generating Ion data, and it's
not possible to fully specify the set of exceptions that could be thrown
from the underlying data sink. Thus all failures are thrown as instances
of IonException
, wrapping the originating cause. If an application
wants to handle (say) IOException
s specially, then it needs to
extract that from the wrappers; the documentation of IonException
explains how to do that.IonStreamUtils
,
IonTextWriterBuilder
Modifier and Type | Method and Description |
---|---|
void |
addTypeAnnotation(String annotation)
Adds a given string to the list of pending annotations.
|
void |
close()
Closes this stream and releases any system resources associated with it.
|
void |
finish()
Indicates that writing is completed and all buffered data should be
written and flushed as if this were the end of the Ion data stream.
|
void |
flush()
Flushes this writer by writing any buffered output to the underlying
output target.
|
SymbolTable |
getSymbolTable()
Gets the symbol table that is currently in use by the writer.
|
boolean |
isInStruct()
Determines whether values are being written as fields of a struct.
|
void |
setFieldName(String name)
Sets the pending field name to the given text.
|
void |
setFieldNameSymbol(SymbolToken name)
Sets the pending field name to the given token.
|
void |
setTypeAnnotations(String... annotations)
Sets the full list of pending annotations to the given text symbols.
|
void |
setTypeAnnotationSymbols(SymbolToken... annotations)
Sets the full list of pending annotations to the given symbols.
|
void |
stepIn(IonType containerType)
Writes the beginning of a non-null container (list, sexp, or struct).
|
void |
stepOut()
Writes the end of the current container, returning this writer to the
context of parent container.
|
void |
writeBlob(byte[] value)
write the byte array out as an IonBlob value.
|
void |
writeBlob(byte[] value,
int start,
int len)
Writes a portion of the byte array out as an IonBlob value.
|
void |
writeBool(boolean value)
writes a non-null boolean value (true or false) as an IonBool
to output.
|
void |
writeClob(byte[] value)
write the byte array out as an IonClob value.
|
void |
writeClob(byte[] value,
int start,
int len)
Writes a portion of the byte array out as an IonClob value.
|
void |
writeDecimal(BigDecimal value)
Writes a BigDecimal value as an Ion decimal.
|
void |
writeFloat(double value)
writes a 64 bit binary floating point value, a Java double,
as an IonFloat.
|
void |
writeInt(BigInteger value)
writes a BigInteger value as an IonInt.
|
void |
writeInt(long value)
writes a signed 64 bit value, a Java long, as an IonInt.
|
void |
writeNull()
Writes a value of Ion's null type (
null aka null.null ). |
void |
writeNull(IonType type)
Writes a null value of a specified Ion type.
|
void |
writeString(String value)
Writes a
String as an Ion string. |
void |
writeSymbol(String content)
Writes the text of an Ion symbol value.
|
void |
writeSymbolToken(SymbolToken content)
Writes the content of an Ion symbol value.
|
void |
writeTimestamp(Timestamp value)
Writes a timestamp value.
|
void |
writeValue(IonReader reader)
Writes the current value from a reader.
|
void |
writeValues(IonReader reader)
Writes a reader's current value, and all following values until the end
of the current container.
|
SymbolTable getSymbolTable()
Note that the table may be replaced during processing. For example, the stream may start out with a system table that's later replaced by a local table in order to store newly-encountered symbols.
When this method returns a local table, it may be
mutable, meaning that additional
symbols may be interned until it is
made read-only. Note that
manually mutating local symbol tables is a deprecated feature;
please instead use
IonSystem.newBinaryWriter(java.io.OutputStream, SymbolTable...)
or IonSystem.newTextWriter(java.io.OutputStream, SymbolTable...)
to provide custom symbol table(s) to writers upon construction.
void flush() throws IOException
For some implementations this may have no effect even when some data is buffered, because it's not always possible to fully write partial data. In particular, when writing binary Ion data, Ion's length-prefixed encoding requires a complete top-level value to be written at once.
Furthermore, when writing binary Ion data, nothing can be
flushed until the writer knows that no more local symbols can be
encountered. This can be accomplished via finish()
or by
making the local symbol table
read-only.
flush
in interface Flushable
IOException
- if thrown by the underlying output target.finish()
void finish() throws IOException
This method may only be called when all top-level values are completely written and stepped-out.
Implementations should allow the application to continue writing further
top-level values following the semantics for concatenating Ion data
streams. If another top-level value is written, the result must behave
as if it were preceded by an Ion version marker, resetting the stream
context as if this were a new stream. (Whether or not an IVM is written
may depend upon the writer's configuration; see
IvmMinimizing
.)
This feature can be used to flush reliably before writing more values. Think about a long-running stream of binary values: without finishing, all the values would continue to buffer since the encoder keeps expecting more local symbols (which must be written into the local symbol table that precedes all top-level values). Such an application can finish occasionally to flush the data out, then continue writing more data using a fresh local symbol table.
IOException
- if thrown by the underlying output target.IllegalStateException
- when not between top-level values.flush()
,
close()
void close() throws IOException
If the cursor is between top-level values, this method will
finish()
before closing the underlying output stream.
If not, the resulting data may be incomplete and invalid Ion.
In other words: unless you're recovering from a failure condition, don't close the writer until you've stepped-out back to the starting level.
close
in interface AutoCloseable
close
in interface Closeable
IOException
- if thrown by the underlying output target.finish()
void setFieldName(String name)
The pending field name is cleared when the current value is
written via stepIn()
or one of the
write*()
methods.
name
- text of the field nameIllegalStateException
- if the current container isn't a struct,
that is, if isInStruct()
is false.NullPointerException
- if name
is null.EmptySymbolException
- if name
is empty.void setFieldNameSymbol(SymbolToken name)
The pending field name is cleared when the current value is
written via stepIn()
or one of the
write*()
methods.
name
- text of the field nameIllegalStateException
- if the current container isn't a struct,
that is, if isInStruct()
is false.NullPointerException
- if name
is null.void setTypeAnnotations(String... annotations)
annotations
array are copied into this
writer, so the caller does not need to preserve the array.
The list of pending annotations is cleared when the current value is
written via stepIn()
or one of the
write*()
methods.
annotations
- string array with the annotations.
If null or empty, any pending annotations are cleared.void setTypeAnnotationSymbols(SymbolToken... annotations)
annotations
array are copied into this
writer, so the caller does not need to preserve the array.
The list of pending annotations is cleared when the current value is
written via stepIn()
or one of the
write*()
methods.
This is an "expert method": correct use requires deep understanding of the Ion binary format. You almost certainly don't want to use it.
annotations
- If null or empty, any pending annotations are cleared.void addTypeAnnotation(String annotation)
The list of pending annotations is cleared when the current value is
written via stepIn()
or one of the
write*()
methods.
annotation
- string annotation to append to the annotation listvoid stepIn(IonType containerType) throws IOException
stepOut()
after the last
child value.
This method is not used to write null.list
et al.
To write null values use writeNull(IonType)
.
containerType
- must be one of
IonType.LIST
, IonType.SEXP
, or IonType.STRUCT
.IOException
void stepOut() throws IOException
stepIn(IonType)
.IOException
boolean isInStruct()
void writeValue(IonReader reader) throws IOException
This method also writes annotations and field names (if in a struct), and performs a deep write, including the contents of any containers encountered.
IOException
void writeValues(IonReader reader) throws IOException
IonReader.next()
to get going.
This method iterates until IonReader.next()
returns null
and does not step out to the container
of the current cursor position.
This method also writes annotations and field names (if in a struct), and performs a deep write, including the contents of any containers encountered.
IOException
void writeNull() throws IOException
null
aka null.null
).IOException
void writeNull(IonType type) throws IOException
type
- type of the null to be writtenIOException
void writeBool(boolean value) throws IOException
value
- true or false as desiredIOException
void writeInt(long value) throws IOException
value
- signed int to writeIOException
void writeInt(BigInteger value) throws IOException
value
- BigInteger to writeIOException
void writeFloat(double value) throws IOException
value
- double to writeIOException
void writeDecimal(BigDecimal value) throws IOException
To write a negative zero value, pass this method a
Decimal
instance.
value
- may be null to represent null.decimal
.IOException
void writeTimestamp(Timestamp value) throws IOException
value
- may be null to represent null.timestamp
.IOException
void writeSymbol(String content) throws IOException
content
- may be null to represent null.symbol
.IllegalArgumentException
- if the value contains an invalid UTF-16
surrogate pair.IOException
void writeSymbolToken(SymbolToken content) throws IOException
content
- may be null to represent null.symbol
.IllegalArgumentException
- if the value contains an invalid UTF-16
surrogate pair.IOException
void writeString(String value) throws IOException
String
as an Ion string. Since Ion strings are
UTF-8 and Java Strings are Unicode 16. As such the resulting
lengths may not match. In addition some Java strings are not
valid as they may contain only one of the two needed surrogate
code units necessary to define the Unicode code point to be
output, an exception will be raised if this case is encountered.value
- may be null to represent null.string
.IllegalArgumentException
- if the value contains an invalid UTF-16
surrogate pair.IOException
void writeClob(byte[] value) throws IOException
value
- may be null to represent null.clob
.IOException
void writeClob(byte[] value, int start, int len) throws IOException
value
- bytes to be written.
May be null
to represent null.clob
.start
- offset of the first byte in value to writelen
- number of bytes to write from valueIOException
void writeBlob(byte[] value) throws IOException
value
- may be null to represent null.blob
.IOException
void writeBlob(byte[] value, int start, int len) throws IOException
value
- bytes to be written.
May be null
to represent null.blob
.start
- offset of the first byte in value to writelen
- number of bytes to write from valueIOException