Problems with socket outputstream and inputstream - java

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.

Related

Error where FileOutputStream only writes to file after the program has been terminated

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();
}

Two outputstreams?

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.

Keep getting cast exception error when I'm reading a data file? [duplicate]

This question already has answers here:
Why does writeObject throw java.io.NotSerializableException and how do I fix it?
(4 answers)
Closed 7 years ago.
So I'm trying to write and read a data file and declare a new variable of type 'GroceryStore' after I read the data file. I keep getting cast exception errors when I'm running my program. Could someone explain to me why this is happening and how I can fix it? Thanks.
Here's my write data file method:
{
FileOutputStream file = null;
ObjectOutputStream outStream = null;
file = new FileOutputStream(new File(filename));
outStream = new ObjectOutputStream(file);
outStream.writeObject(store1);
System.out.print(filename + " was written\n");
}
Here's my read data file method
{
FileInputStream file = null;
ObjectInputStream inStream = null;
file = new FileInputStream(new File(filename));
inStream = new ObjectInputStream(file);
GroceryStore newStore = (GroceryStore) inStream.readObject();
store1 = newStore;
System.out.print(filename + " was read\n");
}
At first glance at the code for reading it seems to want to put it to fast to the class GroseryStore, probably need some parsing before you can get it in there. Try to System.out.println the input from the reader, then you know what you have, then parse / chop and slice that into what you need / want of it.
So, second make a class for the read / write operations. As an example of how the write might work for simple text output file you could use something like this:
private String file_name = "FileName";
private String file_extention = ".txt";
BufferedWriter writer = null;
public void writeTextToFile(String stuff_to_file) {
// trying to write (and read) is a bit hazardous. So, try, catch and finally
try {
File file = new File(file_name + file_extention);
FileOutputStream mFileOutputStream = new FileOutputStream(file);
OutputStreamWriter mOutputStreamWriter = new OutputStreamWriter(mFileOutputStream);
writer = new BufferedWriter(mOutputStreamWriter);
writer.write(stuff_to_file); // and finally we do write to file
// This will output the full path where the file will be written to.
System.out.println("\nFile made, can be found at: " + file.getCanonicalPath());
} catch (Exception e) { // if something went wrong we like to know it.
e.printStackTrace();
System.out.println("Problem with file writing: " + e);
} finally {
try { // Close the writer regardless of what happens...
writer.close();
} catch (Exception e) { // yes, even this can go wrong
e.printStackTrace();
} // close try / catch
} // close finally
} // close method

BufferedWriter causes break

I'm trying to make a save function for a program I'm working on, and for some reason whenever I run it, it only gets past the first line of the try{} statement.
My code is as appears below.
public void saveGame() {
System.out.println("saveGame");
try
{
System.out.println("try saveGame");
BufferedWriter b = new BufferedWriter(new FileWriter("chardata.txt"));
System.out.println("try saveGame2");
String sp = System.getProperty("line.separator");
System.out.println("try saveGame3");
b.write("Miscellaneous char data here");
b.close();
}
catch(IOException ex)
{
System.out.println("File Writing Error");
}
}
When I run the program, the only lines that get printed are "saveGame" and "try saveGame." There is no "File Writing Error" either, it simply doesn't do anything after the "try saveGame" line. I'm not sure if this is relevant, but I am doing this from a computer at a school, which may have restricted permissions. Any kind of explanation and/or help would be much appreciated.
I think a better way to write your file would be using FileOutputStream and OutputStreamWriter.
Additionaly, you should move your b.close to a finally statement because if an exception is thrown before that b.close was executed, it never will be executed.
public void saveGame() {
System.out.println("saveGame");
try
{
System.out.println("try saveGame");
String path = "./chardata.txt"; //your file path
File file = new File(path);
FileOutputStream fsal = new FileOutputStream(file);
OutputStreamWriter osw = new OutputStreamWriter(fsal);
Writer w = new BufferedWriter(osw);
System.out.println("try saveGame2");
String sp = System.getProperty("line.separator");
System.out.println("try saveGame3");
w.write("Miscellaneous char data here");
}
catch(IOException ex)
{
System.out.println("File Writing Error");
}
finally{
if(w!=null)
w.close();
}
}

java I/O, writng a array to a text file

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

Categories

Resources