/*
* Copyright (c) 2012, Codename One and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Codename One designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Codename One through http://www.codenameone.com/ if you
* need additional information or have any questions.
*/
package java.io;
import java.util.Arrays;
/**
* A PrintStream adds functionality to another output stream, namely the ability to print representations of various data values conveniently. Two other features are provided as well. Unlike other output streams, a PrintStream never throws an IOException; instead, exceptional situations merely set an internal flag that can be tested via the checkError method.
* All characters printed by a PrintStream are converted into bytes using the platform's default character encoding.
* Since: JDK1.0, CLDC 1.0
*/
public class PrintStream extends FilterOutputStream {
/**
* indicates whether or not this PrintStream has incurred an error.
*/
private boolean ioError;
/**
* indicates whether or not this PrintStream should flush its contents after
* printing a new line.
*/
private boolean autoFlush;
private String encoding;
/**
* Constructs a new {@code PrintStream} with {@code out} as its target
* stream. By default, the new print stream does not automatically flush its
* contents to the target stream when a newline is encountered.
*
* @param out
* the target output stream.
* @throws NullPointerException
* if {@code out} is {@code null}.
*/
public PrintStream(OutputStream out) {
super(out);
if (out == null) {
throw new NullPointerException("out == null");
}
}
/**
* Constructs a new {@code PrintStream} with {@code out} as its target
* stream. The parameter {@code autoFlush} determines if the print stream
* automatically flushes its contents to the target stream when a newline is
* encountered.
*
* @param out
* the target output stream.
* @param autoFlush
* indicates whether to flush contents upon encountering a
* newline sequence.
* @throws NullPointerException
* if {@code out} is {@code null}.
*/
public PrintStream(OutputStream out, boolean autoFlush) {
super(out);
if (out == null) {
throw new NullPointerException("out == null");
}
this.autoFlush = autoFlush;
}
/**
* Constructs a new {@code PrintStream} with {@code out} as its target
* stream and using the character encoding {@code charsetName} while writing. The
* parameter {@code autoFlush} determines if the print stream automatically
* flushes its contents to the target stream when a newline is encountered.
*
* @param out
* the target output stream.
* @param autoFlush
* indicates whether or not to flush contents upon encountering a
* newline sequence.
* @param charsetName
* the non-null string describing the desired character encoding.
* @throws NullPointerException
* if {@code out} or {@code charsetName} are {@code null}.
* @throws UnsupportedEncodingException
* if the encoding specified by {@code charsetName} is not supported.
*/
public PrintStream(OutputStream out, boolean autoFlush, String charsetName)
throws UnsupportedEncodingException {
super(out);
if (out == null) {
throw new NullPointerException("out == null");
} else if (charsetName == null) {
throw new NullPointerException("charsetName == null");
}
this.autoFlush = autoFlush;
/*try {
if (!Charset.isSupported(charsetName)) {
throw new UnsupportedEncodingException(charsetName);
}
} catch (IllegalCharsetNameException e) {
throw new UnsupportedEncodingException(charsetName);
}*/
encoding = charsetName;
}
/**
* Constructs a new {@code PrintStream} with {@code file} as its target. The
* VM's default character set is used for character encoding.
*
* @param file
* the target file. If the file already exists, its contents are
* removed, otherwise a new file is created.
* @throws FileNotFoundException
* if an error occurs while opening or creating the target file.
*/
/*public PrintStream(File file) throws FileNotFoundException {
super(new FileOutputStream(file));
}*/
/**
* Constructs a new {@code PrintStream} with {@code file} as its target. The
* character set named {@code charsetName} is used for character encoding.
*
* @param file
* the target file. If the file already exists, its contents are
* removed, otherwise a new file is created.
* @param charsetName
* the name of the character set used for character encoding.
* @throws FileNotFoundException
* if an error occurs while opening or creating the target file.
* @throws NullPointerException
* if {@code charsetName} is {@code null}.
* @throws UnsupportedEncodingException
* if the encoding specified by {@code charsetName} is not supported.
*/
/*public PrintStream(File file, String charsetName) throws FileNotFoundException,
UnsupportedEncodingException {
super(new FileOutputStream(file));
if (charsetName == null) {
throw new NullPointerException("charsetName == null");
}
encoding = charsetName;
}*/
/**
* Constructs a new {@code PrintStream} with the file identified by
* {@code fileName} as its target. The VM's default character
* set is used for character encoding.
*
* @param fileName
* the target file's name. If the file already exists, its
* contents are removed, otherwise a new file is created.
* @throws FileNotFoundException
* if an error occurs while opening or creating the target file.
*/
/*public PrintStream(String fileName) throws FileNotFoundException {
this(new File(fileName));
}*/
/**
* Constructs a new {@code PrintStream} with the file identified by
* {@code fileName} as its target. The character set named {@code charsetName} is
* used for character encoding.
*
* @param fileName
* the target file's name. If the file already exists, its
* contents are removed, otherwise a new file is created.
* @param charsetName
* the name of the character set used for character encoding.
* @throws FileNotFoundException
* if an error occurs while opening or creating the target file.
* @throws NullPointerException
* if {@code charsetName} is {@code null}.
* @throws UnsupportedEncodingException
* if the encoding specified by {@code charsetName} is not supported.
*/
/*public PrintStream(String fileName, String charsetName)
throws FileNotFoundException, UnsupportedEncodingException {
this(new File(fileName), charsetName);
}*/
/**
* Flushes this stream and returns the value of the error flag.
*
* @return {@code true} if either an {@code IOException} has been thrown
* previously or if {@code setError()} has been called;
* {@code false} otherwise.
* @see #setError()
*/
public boolean checkError() {
OutputStream delegate = out;
if (delegate == null) {
return ioError;
}
flush();
return ioError;// || delegate.checkError();
}
/**
* Sets the error state of the stream to false.
* @since 1.6
*/
protected void clearError() {
ioError = false;
}
/**
* Closes this print stream. Flushes this stream and then closes the target
* stream. If an I/O error occurs, this stream's error state is set to
* {@code true}.
*/
@Override
public synchronized void close() {
flush();
if (out != null) {
try {
out.close();
out = null;
} catch (IOException e) {
setError();
}
}
}
/**
* Ensures that all pending data is sent out to the target stream. It also
* flushes the target stream. If an I/O error occurs, this stream's error
* state is set to {@code true}.
*/
@Override
public synchronized void flush() {
if (out != null) {
try {
out.flush();
return;
} catch (IOException e) {
// Ignored, fall through to setError
}
}
setError();
}
/**
* Put the line separator String onto the print stream.
*/
private void newline() {
print("\n");
}
/**
* Prints the string representation of the character array {@code chars}.
*/
public void print(char[] chars) {
print(new String(chars, 0, chars.length));
}
/**
* Prints the string representation of the char {@code c}.
*/
public void print(char c) {
print(String.valueOf(c));
}
/**
* Prints the string representation of the double {@code d}.
*/
public void print(double d) {
print(String.valueOf(d));
}
/**
* Prints the string representation of the float {@code f}.
*/
public void print(float f) {
print(String.valueOf(f));
}
/**
* Prints the string representation of the int {@code i}.
*/
public void print(int i) {
print(String.valueOf(i));
}
/**
* Prints the string representation of the long {@code l}.
*/
public void print(long l) {
print(String.valueOf(l));
}
/**
* Prints the string representation of the Object {@code o}, or {@code "null"}.
*/
public void print(Object o) {
print(String.valueOf(o));
}
/**
* Prints a string to the target stream. The string is converted to an array
* of bytes using the encoding chosen during the construction of this
* stream. The bytes are then written to the target stream with
* {@code write(int)}.
*
* <p>If an I/O error occurs, this stream's error state is set to {@code true}.
*
* @param str
* the string to print to the target stream.
* @see #write(int)
*/
public synchronized void print(String str) {
if (out == null) {
setError();
return;
}
if (str == null) {
print("null");
return;
}
try {
if (encoding == null) {
write(str.getBytes());
} else {
write(str.getBytes(encoding));
}
} catch (IOException e) {
setError();
}
}
/**
* Prints the string representation of the boolean {@code b}.
*/
public void print(boolean b) {
print(String.valueOf(b));
}
/**
* Prints a newline.
*/
public void println() {
newline();
}
/**
* Prints the string representation of the character array {@code chars} followed by a newline.
*/
public void println(char[] chars) {
println(new String(chars, 0, chars.length));
}
/**
* Prints the string representation of the char {@code c} followed by a newline.
*/
public void println(char c) {
println(String.valueOf(c));
}
/**
* Prints the string representation of the double {@code d} followed by a newline.
*/
public void println(double d) {
println(String.valueOf(d));
}
/**
* Prints the string representation of the float {@code f} followed by a newline.
*/
public void println(float f) {
println(String.valueOf(f));
}
/**
* Prints the string representation of the int {@code i} followed by a newline.
*/
public void println(int i) {
println(String.valueOf(i));
}
/**
* Prints the string representation of the long {@code l} followed by a newline.
*/
public void println(long l) {
println(String.valueOf(l));
}
/**
* Prints the string representation of the Object {@code o}, or {@code "null"},
* followed by a newline.
*/
public void println(Object o) {
println(String.valueOf(o));
}
/**
* Prints a string followed by a newline. The string is converted to an array of bytes using
* the encoding chosen during the construction of this stream. The bytes are
* then written to the target stream with {@code write(int)}.
*
* <p>If an I/O error occurs, this stream's error state is set to {@code true}.
*
* @param str
* the string to print to the target stream.
* @see #write(int)
*/
public synchronized void println(String str) {
print(str);
newline();
}
/**
* Prints the string representation of the boolean {@code b} followed by a newline.
*/
public void println(boolean b) {
println(String.valueOf(b));
}
/**
* Sets the error flag of this print stream to true.
*/
protected void setError() {
ioError = true;
}
/**
* Writes {@code count} bytes from {@code buffer} starting at {@code offset}
* to the target stream. If autoFlush is set, this stream gets flushed after
* writing the buffer.
*
* <p>This stream's error flag is set to {@code true} if this stream is closed
* or an I/O error occurs.
*
* @param buffer
* the buffer to be written.
* @param offset
* the index of the first byte in {@code buffer} to write.
* @param length
* the number of bytes in {@code buffer} to write.
* @throws IndexOutOfBoundsException
* if {@code offset < 0} or {@code count < 0}, or if {@code
* offset + count} is bigger than the length of {@code buffer}.
* @see #flush()
*/
@Override
public void write(byte[] buffer, int offset, int length) {
//Arrays.checkOffsetAndCount(buffer.length, offset, length);
synchronized (this) {
if (out == null) {
setError();
return;
}
try {
out.write(buffer, offset, length);
if (autoFlush) {
flush();
}
} catch (IOException e) {
setError();
}
}
}
/**
* Writes one byte to the target stream. Only the least significant byte of
* the integer {@code oneByte} is written. This stream is flushed if
* {@code oneByte} is equal to the character {@code '\n'} and this stream is
* set to autoFlush.
* <p>
* This stream's error flag is set to {@code true} if it is closed or an I/O
* error occurs.
*
* @param oneByte
* the byte to be written
*/
@Override
public synchronized void write(int oneByte) {
if (out == null) {
setError();
return;
}
try {
out.write(oneByte);
int b = oneByte & 0xFF;
// 0x0A is ASCII newline, 0x15 is EBCDIC newline.
boolean isNewline = b == 0x0A || b == 0x15;
if (autoFlush && isNewline) {
flush();
}
} catch (IOException e) {
setError();
}
}
/**
* Appends the char {@code c}.
* @return this stream.
*/
public PrintStream append(char c) {
print(c);
return this;
}
/**
* Appends the CharSequence {@code charSequence}, or {@code "null"}.
* @return this stream.
*/
public PrintStream append(CharSequence charSequence) {
if (charSequence == null) {
print("null");
} else {
print(charSequence.toString());
}
return this;
}
/**
* Appends a subsequence of CharSequence {@code charSequence}, or {@code "null"}.
*
* @param charSequence
* the character sequence appended to the target stream.
* @param start
* the index of the first char in the character sequence appended
* to the target stream.
* @param end
* the index of the character following the last character of the
* subsequence appended to the target stream.
* @return this stream.
* @throws IndexOutOfBoundsException
* if {@code start > end}, {@code start < 0}, {@code end < 0} or
* either {@code start} or {@code end} are greater or equal than
* the length of {@code charSequence}.
*/
/*public PrintStream append(CharSequence charSequence, int start, int end) {
if (charSequence == null) {
charSequence = "null";
}
print(charSequence.subSequence(start, end).toString());
return this;
}*/
}