I have the following code where I'm trying to create two different types of outputstreams. This doesn't seem to work. What would be the correct way to create two outputstreams? Specifically, one dataoutputstream and one objectoutputstream?
connect();
try (DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream())) {
try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream)) {
outputStream.writeUTF("saveFile");
outputStream.writeUTF(serverName);
File fileToSave = new File(localName);
byte[] fileContent = Files.readAllBytes(fileToSave.toPath());
objectOutputStream.writeObject(fileContent);
return true;
}
} catch (IOException e) {
return false;
} finally {
disconnect();
}
After doing some debugging it seems just like the outputstream isn't working. If I only have one of the two, the two "writeUTF" statements will execute.
If I keep both of the outputstreams, the message never reaches the server.
The solution was to move the two "writeUTF" statements above the second try block.
connect();
try (DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream())) {
outputStream.writeUTF("saveFile");
outputStream.writeUTF(serverName);
try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream)) {
File fileToSave = new File(localName);
byte[] fileContent = Files.readAllBytes(fileToSave.toPath());
objectOutputStream.writeObject(fileContent);
return true;
}
} catch (IOException e) {
return false;
} finally {
disconnect();
}
Now the code executes properly.
The problem with your code is that new ObjectOutputStream(...) writes a header to the stream, and evidently your reading code isn't symmetrical with this code, i.e. it does the readUTF() steps before constructing the ObjectInputStream, so the header isn't consumed yet, so the readUTF() steps see it, and barf.
The solution is that you don't need to do this at all. The DataOutputStream is completely pointless here. ObjectOutputStream has all the methods of DatataOutputStream, and more, and similarly for the input streams.
In general this kind of thing is not possible when one or more of the streams is buffered, as ObjectInputStream is.
Related
I've had this error in the past but never fully understood it. After closing an OutputStream, regardless of the location of the java file or the manner in which it is called, completely screws up all sequential runs or attempts to write to another file, even if a different method of writing to a file is used. For this reason I avoid closing streams even though it is a horrible habit not to. In my program, I created was trying a test case that had a close statement which destroyed all of my previous streams, making it for some reason that they only write to files after the program has been terminated.
I kept the file location open and it writes the Text in the text file at the appropriate time, however the "Preview" panel in Windows does not detect it (which used to happen). Note that this all worked perfectly before the stream was accidentally closed. Is there a manner to reset the stream? I've tried flushing it during the process but is still does not run as it did prior.
Here is the method used to create the file:
protected void createFile(String fileName, String content) {
try {
String fileLoc = PATH + fileName + ".txt";
File f = new File(fileLoc);
if(!f.isFile())
f.createNewFile();
FileOutputStream outputStream = new FileOutputStream(fileLoc);
byte[] strToBytes = content.getBytes();
outputStream.write(strToBytes);
} catch (IOException e) {
e.printStackTrace();
return;
}
}
as well as the method used to read the file:
protected String readFile(String fileName) {
try {
StringBuilder sb = new StringBuilder("");
String fileLoc = PATH + fileName + ".txt";
File f = new File(fileLoc);
if(!f.exists())
return "null";
Scanner s = new Scanner(f);
int c = 0;
while(s.hasNext()) {
String str = s.nextLine();
sb.append(str);
if(s.hasNext())
sb.append("\n");
}
return sb.toString();
} catch(Exception e) {
e.printStackTrace();
return "null";
}
}
I'd be happy to answer any clarification questions if needed. Thank you for the assistance.
without try-resource, you need close in final clause to make sure no leak. Or use Stream.flush() if you need more 'in-time' update.
} catch (IOException e) {
e.printStackTrace();
return;
} finally {
outputStream.close();
}
You need to call flush() on the stream to write the bytes to the stream.
You're currently calling write() by itself, like this:
FileOutputStream outputStream = new FileOutputStream(fileLoc);
outputStream.write(content.getBytes());
What you want to do is this:
FileOutputStream outputStream = new FileOutputStream(fileLoc);
outputStream.write(content.getBytes());
outputStream.flush();
From the Javadoc (https://docs.oracle.com/javase/8/docs/api/java/io/OutputStream.html#flush--) for OutputStream (where FileOutputStream is an OutputStream), this is what it says for flush():
Flushes this output stream and forces any buffered output bytes to be written out. The general contract of flush is that calling it is an indication that, if any bytes previously written have been buffered by the implementation of the output stream, such bytes should immediately be written to their intended destination.
Even better would be to close the stream in a finally block, so that no matter what your code always tries to free up any open resources, like this:
FileOutputStream outputStream = null;
try {
outputStream = new FileOutputStream(fileLoc);
outputStream.write(content.getBytes());
outputStream.flush();
} finally {
if (outputStream != null) {
outputStream.close();
}
}
or use automatic resource management, like this:
try (FileOutputStream outputStream = new FileOutputStream(fileLoc)) {
outputStream.write(content.getBytes());
outputStream.flush();
}
I would like to know is it possible to detect the end of the binary file while using readUTF()/readInt()/etc. functions (DataInputStream methods). Here's the code
try(DataInputStream reader = new DataInputStream(new BufferedInputStream(new FileInputStream("file.dat")))){
String input;
while((input = br.readUTF()) != null){ //something like that
//some code
}
}catch(IOException error){
//handling exception
}
If not what's recommended solution for such cases? Thanks for any help!
Based on readUTF from the docs, I don't see an elegant way to do it, maybe you could read until it hits EOFException like this:
while(true){
try{
input = reader.readUTF();
}
catch(EOFException e) {
//....
}
}
I'm trying to develop client-server connection between phone and pc using sockets. During the developing i met a problem and cannnot fix it yet. The problem is with outputstream. I use an ObjectoutputStream to send a String array to client and it works when I use this code:
try
{
// отправка пакета с файлами
DataInputStream dir = new DataInputStream(conn.getInputStream());
OutputStream dos = conn.getOutputStream();
ObjectOutputStream objectOutput = new ObjectOutputStream(dos);
byte messageType = dir.readByte();
switch(messageType) {
case 1:
try {
textArea.append("\nClient sends a command: " + dir.readUTF());
objectOutput.writeObject(results);
objectOutput.close();
} catch(Exception e) {
e.printStackTrace();
}
}
dir.close();
} catch (IOException e) {
......
but when I move ObjectOutputStream to the switcher:
try
{
// отправка пакета с файлами
DataInputStream dir = new DataInputStream(conn.getInputStream());
OutputStream dos = conn.getOutputStream();
byte messageType = dir.readByte();
switch(messageType) {
case 1:
try {
ObjectOutputStream objectOutput = new ObjectOutputStream(dos);
textArea.append("\nClient sends a command: " + dir.readUTF());
objectOutput.writeObject(results);
objectOutput.close();
} catch(Exception e) {
e.printStackTrace();
}
}
dir.close();
} catch (IOException e) {
....
my program freezes. I need to do like this, because i also need to do another commands, like sending and receiving files. Any solutions for this problem?
I've solved a problem. I just use BufferedReader & Writer for it, because it will be also used for transferring files.
So now code works fine and looks like this:
// отправка пакета с файлами
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream(), ENCODING));
String messageType = br.readLine();
switch(messageType) {
case "connect": {
List<String> results = new ArrayList<String>();
File[] files = new File("C:/Tenzor_Denis/ServerFiles/").listFiles();
//If this pathname does not denote a directory, then listFiles() returns null.
for (File file : files) {
if (file.toString().endsWith(".txt")) {
results.add(file.getName());
}
}
try {
for(int i = 0; i < results.size(); i++) {
bw.write(results.get(i));
bw.newLine();
//textArea.append(" " + results.get(i));
}
textArea.append("\nClient sends a command: " + messageType);
} catch(Exception e) {
e.printStackTrace();
}
bw.close();
br.close();
}
break;
}
}
Thx to all for answers.
Which line does it freeze on? It seems like reading from the input stream causes the output stream to block until everything is consumed. Look at the documentation for your conn object. What class is this? Perhaps moving the dir.readUTF() call before creating the ObjectOutputStream might solve it.
You can't do it either way. Closing the ObjectOutputStream will close the socket. You need to keep it open for the life of the socket. So moving it inside the case is futile anyway.
But your code doesn't make sense. You're writing with ObjectOutputStream, yet all you're reading from the peer is a single byte. If you're writing objects, you need to read objects, with an ObjectInputStream, not a DataInputStream, and when using both object input and output streams you must always construct the ObjectOutputStream first, at both ends to be safe.
i am using the following code to write an array to the file:
FileWriter fstream1=new FileWriter("outx.txt");
BufferedWriter out1= new BufferedWriter(fstream1);
FileWriter fstream2=new FileWriter("outy.txt");
BufferedWriter out2= new BufferedWriter(fstream2);
for(int i=0;i<320*240;i++)
{
out1.write(0+System.getProperty("line.separator"));//
// out1.write("\n");
out2.write(0+System.getProperty("line.separator"));
//out2.write("\n");
}
: here in the above code i am putting all zeros
the file should be containing 76800 lines( 0s) but my file is having only 69932 lines.
what is the problem and if you can suggest some other way to do this.
Did you remember to close the output streams? Your example doesn't list the calls to close(), which should flush the streams as well. BufferedWriter's default behavior is to flush (write) its remaining contents before closing the stream it is buffering.
You should probably add:
out1.close();
out2.close();
It is a very common case when the end of a file is being cut off that you forgot to close the writer used to create the file, especially when you have used a BufferedOutputStream or BufferedWriter that may not flush its buffer (write it to the file) until it has been explicitly flushed (or more commonly, closed).
It is a very good habit to get into to immediately write the close() call after opening the stream, and then write all of your code for working with the stream between the calls. Taking exceptions into account, the standard calls use the following idiom:
Writer myOutWriter = null;
try {
myOutWriter = new BufferedWriter(new FileWriter("..."));
// Write to myOutWriter here
} catch (IOException ioe) {
// Handle any exceptions here
} finally {
try {
if (myOutWriter != null) {
myOutWriter.close();
}
} catch (IOException ioe) {
// Not much you can do here
}
}
The Apache Commons IO Project (http://commons.apache.org/io/) has a nice utility called IOUtils.closeQuietly() that cleans up the finally block by including the try catch, null check, and call to close into one method call. An example using that library would look like this:
Writer myOutWriter = null;
try {
myOutWriter = new BufferedWriter(new FileWriter("..."));
// Write to myOutWriter here
} catch (IOException ioe) {
// Handle any exceptions here
} finally {
IOUtils.closeQuietly(myOutWriter);
}
Add:
out1.flush();
out2.flush();
After the for loop.
It is likely that your program is exiting before the buffers in the BufferedReader have been flushed, a common problem with working with buffered output.
Edit: The more correct solution would be:
public static void main(String[] args) throws IOException {
final String outputString = "0" + System.getProperty("line.separator");
BufferedWriter out1 = null;
BufferedWriter out2 = null;
try {
out1 = new BufferedWriter(new FileWriter("outx.txt"));
out2 = new BufferedWriter(new FileWriter("outy.txt"));
for(int i = 0; i < 320 * 240; i++) {
out1.write(outputString);
out2.write(outputString);
}
out1.flush(); // Not really needed as close will flush, but it is
out2.flush(); // useful for describing the intent of the code
} finally {
closeQuietly(out1);
closeQuietly(out2);
}
}
private static void closeQuietly(Closeable c) {
try {
if (c != null) {
c.close();
}
} catch (Exception e) {
// No-op
}
}
As others have pointed out, it is likely that there is unflushed data in your buffers.
An acceptable way to rewrite your code would be like this:
Writer out1 = new FileWriter("outx.txt");
try {
out1 = new BufferedWriter(out1);
Writer out2 = new FileWriter("outy.txt");
try {
out2 = new BufferedWriter(out2);
for (int i = 0; i < 320 * 240; i++) {
out1.write(0 + System.getProperty("line.separator"));
out2.write(0 + System.getProperty("line.separator"));
}
} finally {
out2.close();
}
} finally {
out1.close();
}
This code:
will flush data via close
will always release file handles via close, even if an error occurs (by using finally)
obeys the contract for the Closeable classes
doesn't muck around with null or swallow exceptions
I'm having a problem writing to a file:
FileInputStream fin;
try
{
fin = new FileInputStream ("c:/text.txt");
PrintStream p = new PrintStream(fin);
p.println ("test");
fin.close();
}
catch (IOException ioe)
{
System.err.println (ioe.getMessage);
}
Is there a problem with this code?
You need to use a FileOutputStream.
Get used to the following structure. You'll use it a lot in Java.
PrintStream out = null;
try {
out = new PrintStream(new FileOutputStream("c:/text.txt"));
out.println ("test");
} catch (IOException e) {
System.err.println (e.getMessage);
} finally {
if (out != null) {
try { out.close(): } catch (Exception e) { }
}
out = null; // safe but not strictly necessary unless you reuse fin in the same scope
}
At least until ARM blocks hopefully eventuate in Java 7.
As noted, you should close the PrintStream and not the FileOutputStream so the above is a better form to use.
Problems with that code that immediately strike me:
Non-standard formatting.
Awkward variable names.
The exception handling is not good.
Failure to close the file in the case of exceptions. (Use acquire(); try { use(); } finally { release(); }.
Hidden use of default character encoding.
PrintStream swallows exceptions. BufferedOutputStream is better.
Failure to flush the decorator. It may still have data buffered. Although actually in this case you have left the PrintStream in auto-flush mode, which can be a performance issue.
Use / for a Windows path separator. You might be able to get away with it, but it's not good.
So:
FileOutputStream fileOut = new FileOutputStream(
"c:\\text.txt"
);
try {
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(
fileOut,
"UTF-8" // Or, say, Charset.defaultCharset()
));
out.write("test");
out.newLine()
out.flush();
} finally {
fileOut.close();
}
The class: FileInputStream is used to read input from a file. If you want to write to the file, you can use: FileOutputStream. If you want to make your life really easy, you can use a BufferedOutputStream as well.
As pointed out, you should close your streams in the finally block. The reason why you want to do that is say your program isn't really small, and it's a larger application. If you forget to close file streams, for example, the application will hold on to it and if you try to do something to it on the file system (read: at least in Windows) you won't be able to it. We've all seen the 'File cannot be deleted because it's still in use' error.
Here's an example of using the FileOutputStream + BufferedOutputStream: http://www.javadb.com/write-to-file-using-bufferedoutputstream.