I'am testing the PrintWriter class which can handle streams of characters and streams of bytes. Everything went smooth when i tried with streams of characters, now i was testing it with streams of bytes and whenever i print what it reads it always displays null(exception). Here's the code:
package com.files.ex1;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
public class ex1 {
public static void main(String[] args) {
PrintWriter oPW;
try {
oPW = new PrintWriter(new ObjectOutputStream(new FileOutputStream("data.txt")));
oPW.write("1\n");
oPW.write("2\n");
oPW.write("3\n");
oPW.flush();
oPW.close();
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}
This is the class that tries to read and always prints null:
package com.files.ex1;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class ex1_2 {
public static void main(String[] args) {
ObjectInputStream oOIS;
try {
oOIS = new ObjectInputStream(new FileInputStream("data.txt"));
String s = (String) oOIS.readObject();
System.out.println(s);
} catch (IOException e) {
System.out.println(e.getMessage());
} catch (ClassNotFoundException e) {
System.out.println(e.getMessage());
}
}
}
Also what are the advantages of using this class? For streams of characters i can just use BuffedReadear or BufferedWriter to optimize reads or writes respectively, and it also has flush() method.
And what is the advantage of using PrintWriter with streams of bytes? Using ObjectOutputStream alone works when i try to do the operations above.
The reason you're getting null is because you're using readObject on ObjectInputString, but you haven't serialized any Java objects. ObjectInputString.readObject is to be used with ObjectOutputString.writeObject.
The PrintWriter docs state explicitly that
It does not contain methods for writing raw bytes, for which a program should use unencoded byte streams.
You should only use PrintWriter for text. It exposes helpful methods that you may be familiar with because System.out has the print interface.
You should only really use ObjectOutput/InputStream when writing and reading serialized Java Objects. The serialization format is binary data (unlike JSON/XML for example). These objects must implement the Serializable interface.
You can improve performance of writing and reading unencoded byte streams by use BufferedOutputStream and BufferedInputStream respectively.
In general, classes with suffix "Reader" and suffix "Writer" are for text encoded streams. They contain helpful methods for parsing strings and lines from text streams. They should never be used for transferring binary data.
In your example you're only writing text data to a file and reading that text data back, so use:
oPW = new PrintWriter(new FileOutputStream("data.txt"));
oPW.println("1");
for writing and
oOIS = new BufferedReader(new FileInputStream("data.txt"));
String s = oOIS.readLine(); // "1"
for reading.
If you were reading and writing binary data, you would do this instead:
os = new FileOutputStream("data.bin");
os.write(new byte[]{ 1, 2, 3 });
and read:
is = new FileInputStream("data.bin");
byte[] buf = new byte[3];
is.read(buf); // buf now equals {1, 2, 3}
If you were reading and writing Java objects, you would do this instead:
oos = new ObjectOutputStream(new FileOutputStream("data.bin"));
Foo foo = new Foo(...);
oos.writeObject(foo);
and read:
ois = new ObjectInputStream(new FileInputStream("data.bin"));
Foo foo = (Foo) ois.readObject();
Related
From the docs:
Streams have a BaseStream.close() method and implement AutoCloseable,
but nearly all stream instances do not actually need to be closed
after use. Generally, only streams whose source is an IO channel (such
as those returned by Files.lines(Path, Charset)) will require closing.
Most streams are backed by collections, arrays, or generating
functions, which require no special resource management. (If a stream
does require closing, it can be declared as a resource in a
try-with-resources statement.)
When I create a Stream<String> using the lines() method on a BufferedReader as seen below, does closing the Stream also close the BufferedReader?
try (Stream<String> lines = new BufferedReader(new InputStreamReader(process.getInputStream())).lines()) {
// Do stuff
}
// Is the BufferedReader, InputStreamReader and InputStream closed?
Some really quick tests I've tried say no (the in field of the BufferedReader is not null), but then I'm confused by the following sentence, since this example is I/O as well, right?
Generally, only streams whose source is an IO channel (such
as those returned by Files.lines(Path, Charset)) will require closing.
If not, do I need to close both instances, or will closing the BufferedReader suffice?
Ideally, I'd like to return a Stream<String> from some method, without having the client worry about the readers. At the moment, I've created a Stream decorator which also closes the reader, but it's easier if that isn't necessary.
If you want to defer closing of the reader to the delivered Stream you need to invoke Stream.onClose():
static Stream<String> toStream(BufferedReader br){
return br.lines().onClose(asUncheckedAutoCloseable(br));
}
static Runnable asUncheckedAutoCloseable(AutoCloseable ac) {
return () -> {
try {
ac.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
};
}
No, seems it doesn't. As the stream is created using
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(
iter, Spliterator.ORDERED | Spliterator.NONNULL), false);
which doesn't pass any reference to the the BufferedReader
In your question you don't show how you create the Reader that is the argument of new BufferedReader(in). But from my own tests there is no reason to assume that the Stream closes this argument.
Doing the following should close everybody:
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.stream.Stream;
public class SOPlayground {
public static void main(String[] args) throws Exception {
try (Reader in = new InputStreamReader(new FileInputStream(new File("/tmp/foo.html")));
BufferedReader reader = new BufferedReader(in);
Stream<String> lines = reader.lines()) {
lines.forEach(System.out::println);
}
}
}
i had a input file having 45311 instance. after applying my programing task. when i m write it back in new file it actually write 43371 instance only.it is run successfully but where are my remaining instances.
package kmean;
//package greenblocks.statistics;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import weka.clusterers.SimpleKMeans;
import weka.core.Instances;
/**
*
* #author admin
*/
public class Kmean {
public static BufferedReader readDataFile(String filename) {
BufferedReader inputReader = null;
try {
inputReader = new BufferedReader(new FileReader(filename));
} catch (FileNotFoundException ex) {
System.err.println("File not found: " + filename);
}
return inputReader;
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws IOException, Exception {
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new FileWriter("perturbed1.csv"));
}
catch (IOException e) {
}
SimpleKMeans kmeans = new SimpleKMeans();
kmeans.setSeed(10);
//important parameter to set: preserver order, number of cluster.
kmeans.setPreserveInstancesOrder(true);
kmeans.setNumClusters(5);
BufferedReader datafile = readDataFile("elecNormNew.arff");
// BufferedReader datafile = readDataFile("perturbed.csv");
Instances data = new Instances(datafile);
kmeans.buildClusterer(data);
// This array returns the cluster number (starting with 0) for each instance
// The array has as many elements as the number of instances
int[] assignments = kmeans.getAssignments();
StringBuilder sb = new StringBuilder();
int i=0;
for(int clusterNum : assignments) {
// System.out.printf("Instance %d -> Cluster %d \n", i, clusterNum);
sb.append(i);
sb.append(";");
sb.append(clusterNum);
sb.append("\n");
//System.out.printf("\n");
i++;
}
System.out.println(sb.toString());
writer.write(sb.toString()+"\n");
// TODO code application logic here
}
}
The neat fact about buffered file writers are, that they take your input and keep it, until the buffer is full. This reduces the i/o operations. At best one write operation fits into one hdd write buffer so the operating system take the whole buffer as one i/o command. The downside is that if at the end if you do not flush() the buffer, the rest of the content will not be written to disk. If you call close() any pending bytes will be written and the resources be freed. In java 7 and above you can use the autoclosing feature by just opening the stream in your try statement:
try(Inputstream is = new ...) {
If you may have any data to write after your code, you can use .flush() to ensure the data is written.
The buffer size is set by default to 8k, but this may wary from jre and version.
You should call writer.close() at the end after writing all data.
insted of writer.write(sb.toString()+"\n");
try writer.write(sb.toString()+writer.newLine());
and finish your writig progress with a
writer.flush();
writer.close();
had some problems myself with "\n" maby thats the problem.
Why following code
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws IOException {
DataOutputStream out = new DataOutputStream( new FileOutputStream("plik.txt"));
String test = new String("test");
out.writeUTF(test);
out.close();
}
}
produces file with "null" and eot characters at start of the file, followed by "test"? I expected that it would produce file with only "test", without additional stuff.
From the Javadoc of DataOutputStream.writeUTF():
First, two bytes are written to the output stream as if by the
writeShort method giving the number of bytes to follow. This value is
the number of bytes actually written out, not the length of the
string. Following the length, each character of the string is output,
in sequence, using the modified UTF-8 encoding for the character.
[...]
So it's not 2 characters but just 2 bytes.
The purpose of DataOutputStream is:
A data output stream lets an application write primitive Java data
types to an output stream in a portable way. An application can then use a data input stream to read the data back in.
Also note, that's it's recommended to use the NIO2 API and the Automatic Resource Management. And don't wrap a String with a String. Also use a buffer for your streams when writing to the file system.
try (DataOutputStream out = new DataOutputStream(new BufferedOutputStream(Files.newOutputStream(Paths.get("plik.txt")))){
String test = "test";
out.writeUTF(test);
}
If you just want to write some text to a file in UTF-8, use the following code:
try (PrintWriter pw = new PrintWriter(Files.newBufferedWriter(Paths.get("plik.txt"), Charset.forName("UTF-8"))){
String test = "test";
pw.print(test);
}
I'm learning File I/O using Java.
Following are my codes from two different Java files. One is "File" with the main class, the other is "FileWrite."
I was able to implement string input and output. But the output textfile has gibberish in the beginning and I am not sure why.
[File.Java]
package file;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class File {
public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(new FileReader("B:\\fileIn.txt")))
{
String stCurrent;
while ((stCurrent = br.readLine()) != null) {
System.out.println(stCurrent);
}
} catch (IOException e) {
e.printStackTrace();
}
FileWrite fW = new FileWrite();
fW.serializeAddress("Boston", "Canada");
}
}
[FileWrite.Java]
package file;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class FileWrite {
public void serializeAddress(String city, String country) {
try {
FileOutputStream fout = new FileOutputStream("B:\\address.txt");
ObjectOutputStream obOut = new ObjectOutputStream(fout);
obOut.writeUTF(city);
obOut.writeUTF(country);
obOut.close();
System.out.println("Output Done");
} catch(Exception ex) {
ex.printStackTrace();
}
}
}
Now, on "obOut.writeUTF(city); obOut.writeUTF(country);" I separated out two string inputs. Is there a way to combine them into one? As in obOut.writeUTF(city, counry) instead of two. Or is this only achievable through making these into an object?
[Update]
Imported a couple more and I tried
PrintStream ps = new PrintStream(new FileWriter("B:\\addressPS.txt"));
ps.println(city);
ps.println(country);
ps.close();
But with errors, any clue?
You are doing the right thing keeping them separate already. City and country are different fields.
A very common mistake is not making a distinction between binary and text files/socket streams. You are a mixing the two which will lead to confusion. I suggest you only sue text Writer/Reader or binary Input/OuptutStream unless you have a very clear idea of what you are doing.
In short if you what to write text use
PrintStream ps = new PrintStream(new FileWriter(textFileName));
ps.println(city);
ps.println(country);
ps.close();
writeUTF takes strings also, you don't have to create new object for city and county.
Cant you do obOut.writeUTF(city +" "+country); ?
The gibberish is because .writUTF() writes data in a modified UTF format which is mentioned in the javadocs.
An ObjectOutputStream is generally used to output OBJECTS but I suppose you can use it for strings as well. You can use the respective .readUTF() method in the ObjectInputStream class in order to read the data in your file back.
Also, you have tried to use the try-with-resources block which is new to Java SE7. You should NOT do it the way you have done so. You should do this instead:
try (FileReader fr = new FileReader("B:\\fileIn.txt"); BufferedReader br = new BufferedReader(fr);) {
} catch (FileNotFoundException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
Splitting the FileReader and the BufferedReader will allow Java SE7 to close both the streams with ease. The way you have done it, only the BufferedReader stream will get closed after the try block finishes.
By definition, ObjectOutputStream produces 'gibberish'. It's not intended for human consumption, it is a format used to write out objects so that you can read them back. You're not supposed to be able to make sense of the results in a text editor. To make human-readable content, just use an OutputStreamWriter or even a PrintWriter. In short, your last example is correct, and if you get errors, please edit your question to tell us what the errors are.
I am working on a basic encryption program for a school project, and I want to have easily interchangable keys. As it stands, I have a encryption class and a decryption class, with multiple methods. One of those methods is the key that I want to print to a file. Because I will be making many changes to those two classes (apart from the keys), I want to be able to print just that one method to a file. I also need to be able to load it again. Is there any easy way to do this?
You could use java serialization, as you commented that you have a String array to save, you could do something like this:
// save object to file
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("/tmp/file")));
oos.writeObject(myArray); // where myArray is String[]
// load object from file
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("/tmp/file")));
String[] read = (String[]) ois.readObject();
A working example ;), saving the arguments received with the application execution.
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Arrays;
public class TestSerialization {
public static void main(final String[] array) throws FileNotFoundException, IOException, ClassNotFoundException {
// save object to file
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("/tmp/file")));
oos.writeObject(array); // where myArray is String[]
// load object from file
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("/tmp/file")));
String[] read = (String[]) ois.readObject();
System.out.println(Arrays.toString(read));
}
}
Serialization pointed out by user Speath is a very good approach I find.
If you want to be more selective in what you write into your files you can use simple File I/O to write into a file like follows:
Create a new file on the file system withe the FileWriter class and then initiate an I/O stream with BufferedWriter to write into this file:
// create a new file with specified file name
FileWriter fw = new FileWriter("myFile.log");
// create the IO strem on that file
BufferedWriter bw = new BufferedWriter(fw);
// write a string into the IO stream
bw.out("my log entry");
// don't forget to close the stream!
bw.close();
The whole thing must be surrounded with a try/catch in order to catch IO Exception.
Hope this helps.