IOException while trying to save output from ObjectInputStream to a file - java

I am new to the concept of working with streams and with files in Java.
I'm writing a piece of code, I have a very simple server that is listening for an incoming file.
Then I have a handler that deals with the incoming file.
Now, here is the code (stripped of try/catch blocks)
ObjectInputStream in;
in = new ObjectInputStream(new BufferedInputStream(
clientSocket.getInputStream()));
File f = new File(fileName);
int byteCount = in.readInt();
byte[] fileArray = (byte[]) in.readObject();
Files.write(f.toPath(), fileArray);
There comes an IOException when the program hits the ``byte[] fileArray = (byte[]) in.readObject();line. And - to be sure, theint byteCount` shows the correct number of bytes, the filename is also correct...
Stacktrace looks like this:
java.io.OptionalDataException
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1304)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)
at com.fileservice.util.ClientHandlerRunnable.run(ClientHandlerRunnable.java:85)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
Code of the client sending the file:
Socket socket = new Socket(data.getIp(), data.getTcpPort());
FileInputStream fis = null;
BufferedInputStream bis = null;
// OutputStream os = null;
// send file
File myFile = new File(data.getFileName());
String test = myFile.getAbsolutePath();
byte[] mybytearray = new byte[(int) myFile.length()];
fis = new FileInputStream(myFile);
bis = new BufferedInputStream(fis);
bis.read(mybytearray, 0, mybytearray.length);
ObjectOutputStream os = new ObjectOutputStream(
new BufferedOutputStream(socket.getOutputStream()));
os.flush();
System.out.println("Sending " + data.getFileName() + "("
+ mybytearray.length + " bytes)");
if (os != null) {
os.writeInt(mybytearray.length);
os.write(mybytearray, 0, mybytearray.length);
os.flush();
System.out.println("Done.");
}
if (bis != null) {
bis.close();
}
if (os != null) {
os.close();
}
if (socket != null) {
socket.close();
}

You're sending raw bytes, and you're reading an object. That can't work. If you read an object, then the sender must have written an object (with writeObject()). If the sender writes bytes, then you must read bytes (with read()).
Note that your file reading section is wrong as well. read() gives no guarantee that it will read the number of bytes you ask it to read. You MUST use a loop to read everything. Or you can simply use Files.readAllBytes(), which will correctly read all the bytes from the file for you.

Related

Can't open received amr/jgp file from socket on android

To send and receive file via socket over Wifi I have used following code...
Client side :
Socket socket = new Socket(dstAddress, dstPort);
int bufferSize=socket.getReceiveBufferSize();
InputStream in=socket.getInputStream();
DataInputStream clientData = new DataInputStream(in);
String fileName = clientData.readUTF();
System.out.println(fileName);
OutputStream output = new FileOutputStream("/sdcard/"+fileName);
byte[] buffer = new byte[bufferSize];
int read;
while((read = clientData.read(buffer)) != -1){
output.write(buffer, 0, read);
}
//close every thing
output.flush();
output.close();
socket.close();
Server side:
File file = new File(Environment.getExternalStorageDirectory(), "/sdcard/test.amr");
byte[] mybytearray = new byte[8092];
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
DataInputStream dis = new DataInputStream(bis);
OutputStream os;
try {
os = socket.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
dos.writeUTF(file.getName());
dos.writeLong(mybytearray.length);
int read;
while((read = dis.read(mybytearray)) != -1){
dos.write(mybytearray, 0, read);
}
os.flush();
os.close();
socket.close();
At this point I am receiving file 'test.amr' from server without change of its original size.
But when I try to play the file in client device it can't be played.
Note : mp3, avi and txt file received using above code can be opened and played perfectly.
Please suggest how to solve this issue.
Finally I have solved the above problem by just removing
dos.writeLong(mybytearray.length);
line form server code...
as per suggestion of greenapps.
My revised server code is:
File file = new File(Environment.getExternalStorageDirectory(), "/sdcard/test.amr");
byte[] mybytearray = new byte[8092];
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
DataInputStream dis = new DataInputStream(bis);
OutputStream os;
try {
os = socket.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
dos.writeUTF(file.getName());
int read;
while((read = dis.read(mybytearray)) != -1){
dos.write(mybytearray, 0, read);
}
os.flush();
os.close();
socket.close();
You're writing the buffer size as a long but you're not reading it. So the long is being read as part of the image. As writing your sending buffer size has no conceivable relevance to the receiver, you should remove the writeLong(mybytearray.length) call from the sender.

Sending file from Server to Client java

When I'm sending a small file, everything works fine. But when I'm trying to send a file about 5 megabytes, server throws such exception: java.net.socketexception: connection reset by peer: socket write error.
This is a part of my Server:
try {
File myFile = new File("E:\\work\\java\\in.pdf");
long len = myFile.length();
byte[] mybytearray = new byte[(int) myFile.length()];
output = new PrintStream(serviceSocket.getOutputStream());
output.println(clientCounter + " " + len);
bis = new BufferedInputStream(new FileInputStream(myFile));
bis.read(mybytearray, 0, mybytearray.length);
os = serviceSocket.getOutputStream();
os.write(mybytearray, 0, mybytearray.length);
os.flush();
serviceSocket.close();
}
catch(IOException e) {
System.out.println(e);
}
You're assuming that read() fills the buffer, and no doubt you're making the same mistake in the client as well. You have to loop.

Java: read from binary file, send bytes over socket

This should be easy, but I can't get my head around it right now. I wanna send some bytes over a socket, like
Socket s = new Socket("localhost", TCP_SERVER_PORT);
DataInputStream is = new DataInputStream(new BufferedInputStream(s.getInputStream()));
DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(s.getOutputStream()));
for (int j=0; j<40; j++) {
dos.writeByte(0);
}
That works, but now I dont want to writeByte to the Outputstream, but read from a binary file, then write it out. I know(?) I need a FileInputStream to read from, I just can't figure out hot to construct the whole thing.
Can someone help me out?
public void transfer(final File f, final String host, final int port) throws IOException {
final Socket socket = new Socket(host, port);
final BufferedOutputStream outStream = new BufferedOutputStream(socket.getOutputStream());
final BufferedInputStream inStream = new BufferedInputStream(new FileInputStream(f));
final byte[] buffer = new byte[4096];
for (int read = inStream.read(buffer); read >= 0; read = inStream.read(buffer))
outStream.write(buffer, 0, read);
inStream.close();
outStream.close();
}
This would be the naive approach without proper exception handling - in a real-world setting you'd have to make sure to close the streams if an error occurs.
You might want to check out the Channel classes as well as an alternative to streams. FileChannel instances, for example, provide the transferTo(...) method that may be a lot more efficient.
Socket s = new Socket("localhost", TCP_SERVER_PORT);
String fileName = "....";
create a FileInputStream using a fileName
FileInputStream fis = new FileInputStream(fileName);
create a FileInputStream File Object
FileInputStream fis = new FileInputStream(new File(fileName));
to read from the file
DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(
s.getOutputStream()));
reading from it byte after byte
int element;
while((element = fis.read()) !=1)
{
dos.write(element);
}
or reading from it buffer wise
byte[] byteBuffer = new byte[1024]; // buffer
while(fis.read(byteBuffer)!= -1)
{
dos.write(byteBuffer);
}
dos.close();
fis.close();
read a byte from the input and write the same byte to the output
or with a byte buffer it like this:
inputStream fis=new fileInputStream(file);
byte[] buff = new byte[1024];
int read;
while((read=fis.read(buff))>=0){
dos.write(buff,0,read);
}
note that you don't need to use the DataStreams for this

Java TCP Server read file name

I want to create small client-server TCP file transfer program. And I have problem with one thing. When I send file from Client to Server, for example a txt file: omg.txt, I want the Server to read the incoming file name.
So - Client send omg.txt, Server says "New file recived: omg.txt". I tried to use BufferedReader (Server) and DataOutputStream (Client, because you have to write name of the file to send it) but it didnt work.
EDIT:
Client:
Socket sock = new Socket("localhost",13267);
System.out.println("Wait...");
Scanner input = new Scanner(System.in);
while(true){
// wysylanie
System.out.println("Filename");
String p = input.nextLine();
File myFile = new File (p);
boolean exists = (new File(p)).exists();
if (exists) {
byte [] mybytearray = new byte [(int)myFile.length()];
FileInputStream fis = new FileInputStream(myFile);
BufferedInputStream bis = new BufferedInputStream(fis);
BufferedOutputStream out = new BufferedOutputStream(sock.getOutputStream());
bis.read(mybytearray,0,mybytearray.length);
OutputStream os = sock.getOutputStream();
System.out.println("Wait...");
os.write(mybytearray,0,mybytearray.length);
os.flush();
System.out.println("Done");
sock.close();
}
Server:
int filesize=6022386;
int bytesRead;
int current = 0;
ServerSocket servsock = new ServerSocket(13267);
Scanner input = new Scanner(System.in);
while (true) {
System.out.println("Wait...");
Socket sock = servsock.accept();
System.out.println("OK : " + sock);
// odbior pliku
byte [] mybytearray = new byte [filesize];
InputStream is = sock.getInputStream();
bytesRead = is.read(mybytearray,0,mybytearray.length);
current = bytesRead;
do {
bytesRead =
is.read(mybytearray, current, (mybytearray.length-current));
if(bytesRead >= 0) current += bytesRead;
} while(bytesRead > -1);
System.out.println("New filename");
String p = input.nextLine();
File plik = new File(p);
FileOutputStream fos = new FileOutputStream(plik);
BufferedOutputStream bos = new BufferedOutputStream(fos);
bos.write(mybytearray, 0 , current);
bos.flush();
System.out.println("File saved");
bos.close();
sock.close();
And I tried to do something like that:
Client addon:
DataOutputStream outToServer = new DataOutputStream(sock.getOutputStream());
sentence = input.nextLine();
outToServer.writeBytes(sentence);
Server addon:
BufferedReader inFromClient = new BufferedReader(new InputStreamReader(sock.getInputStream()));
clientSentence = inFromClient.readLine();
System.out.println(clientSentence);
...but unfortunetly I have "Wait.." all the time for Client
TCP just transfers raw data. If you want to send files with a filename, you may want to use a higher level protocol, such as FTP or TFTP.
If you really want to use plain TCP, you'll need to encode the filename in your message somehow. You could, for example, send the filename as the first line of the message, and then have the other end turn the rest of the message into a file with that name.
This may be helpful to you: http://www.adp-gmbh.ch/blog/2004/november/15.html

Socket Programming file upload issues?Complete file not uploading

Hi i am using the following code for uploding my file from android phone to the server bt the file does not upload completely..e.g i uploded a 11kb file and got only 8kb file at the server.What am i doing wrong?
Client side
Socket skt = new Socket"112.***.*.**", 3000);
String FileName=fil.getName();
PrintWriter out2 = new PrintWriter(new BufferedWriter(new OutputStreamWriter(skt.getOutputStream())),true);
out2.println("Upload");
out2.println(FileName);
out2.println(spinindx);
out2.println(singleton.arrylst_setngs.get(0).toString());
out2.println(singleton.arrylst_setngs.get(1).toString());
out2.println(singleton.arrylst_setngs.get(2).toString());
out2.println(singleton.arrylst_setngs.get(3).toString());
out2.println(singleton.arrylst_setngs.get(4).toString());
out2.flush();
//Create a file input stream and a buffered input stream.
FileInputStream fis = new FileInputStream(fil);
BufferedInputStream in = new BufferedInputStream(fis);
BufferedOutputStream out = new BufferedOutputStream(skt.getOutputStream());
//Write the file to the server socket
int i;
byte[] buf = new byte[512];
while ((i = in.read(buf)) != -1) {
out.write(buf,0,i);
publishProgress(in.available());
System.out.println(i);
}
//Close the writers,readers and the socket.
in.close();
out.flush();
out.close();
out2.close();
skt.close();
}
catch( Exception e ) {
System.out.println(e);
}
The server side
InputStream inStream = socket.getInputStream();
BufferedReader inm = new BufferedReader(new InputStreamReader(inStream));
String Request=inm.readLine();
if(Request.equals("Upload")){
fileName = inm.readLine();
chosn = inm.readLine();
lt=inm.readLine();
cs = inm.readLine();
om = inm.readLine();
o = inm.readLine();
check=inm.readLine();
//Read, and write the file to the socket
BufferedInputStream in = new BufferedInputStream(inStream);
int i=0;
File f=new File("D:/data/"+filePrefx+fileName);
if(!f.exists()){
f.createNewFile();
}
FileOutputStream fos = new FileOutputStream("D:/data/"+filePrefx+fileName);
BufferedOutputStream out = new BufferedOutputStream(fos);
byte[] buf = new byte[512];
while ((i = in.read(buf)) != -1) {
System.out.println(i);
out.write(buf,0,i);
System.out.println("Receiving data...");
}
in.close();
inStream.close();
out.close();
fos.close();
socket.close();
Looks like you are using both a BufferedReader and a BufferedInputStream on the same underlying socket at the server side, and two kinds of output stream/writer at the client. So your BufferedReader is buffering, which is what it's supposed to do, and thus 'stealing' some of the data you're expecting to read with the BufferedInputStream. Moral: you can't do that. Use DataInputStream & DataOutputStream only, and writeUTF()/readUTF() for the 8 lines you are reading from the client before the file.
You shared the same underlying InputStream between your BufferedReader and bufferedInputStream.
What happened is, when you do the reading through BufferedReader, it reads more than the a few lines you requested from the underlying InputStream into its own internal buffer. And when you create the BufferedInputStream, the data has already been read by the BufferedReader. So Apart from what EJP suggested not to use any buffered class, you can create the BufferedInputStream, and then create the Reader on Top of it. The code is something like this:
BufferedInputStream in = new BufferedInputStream(inStream);
Reader inm = new InputStreamReader(in);
Add it to the beginning of your server code and remove this line:
BufferedInputStream in = new BufferedInputStream(inStream);
See this, i never tried though
void read() throws IOException {
log("Reading from file.");
StringBuilder text = new StringBuilder();
String NL = System.getProperty("line.separator");
Scanner scanner = new Scanner(new FileInputStream(fFileName), fEncoding);
try {
while (scanner.hasNextLine()){
text.append(scanner.nextLine() + NL);
}
}
finally{
scanner.close();
}
log("Text read in: " + text);
}
Shamelessly copied from
http://www.javapractices.com/topic/TopicAction.do?Id=42

Categories

Resources