I am trying to write a program to transfer a file between client and server using java tcp sockets I am using buffer size of 64K but The problem I am facing is that when when the tcp sometimes fail to send the whole 64K it sends the remaing part for example 32K in anther go
There for A garbage data of some Spaces or so is being taken by the buffer at reading side to make 64K complete and thus unnecessary data is making the file useless at receiving side.
Is there any solution to overcome this problem ???
I am using TCP protocol this code is using to send data to client
Server-side code
File transferFile = new File ("Document.txt");
byte [] bytearray = new byte [1024];
int byRead=0;
FileInputStream fin = new FileInputStream(transferFile);
BufferedInputStream bin = new BufferedInputStream(fin);
OutputStream os = socket.getOutputStream();
while(byRead>-1) {
byRead=bin.read(bytearray,0,bytearray.length);
os.write(bytearray,0,bytearray.length);
os.flush();
}
Client-side code
byte [] bytearray = new byte [1024];
InputStream is = socket.getInputStream();
FileOutputStream fos = new FileOutputStream("C:\\Users\\NetBeansProjects\\"+filename);
BufferedOutputStream bos = new BufferedOutputStream(fos);
bytesRead = is.read(bytearray,0,bytearray.length);
currentTot = bytesRead; System.out.println("Data is being read ...");
do {
bytesRead = is.read(bytearray, 0, (bytearray.length));
if(bytesRead == 0) continue;
if(bytesRead >= 0) currentTot += bytesRead;
bos.write(bytearray,0,bytearray.length);
} while(bytesRead > -1);
here I tried to skip the loop if the byte is empty by continue; statement but it is not
working.
bos.write(bytearray,0,bytearray.length);
This should be
bos.write(bytearray,0,bytesRead);
The region after 'bytesRead' in the buffer is undisturbed by the read. It isn't 'garbage'. It's just whatever was there before.
use CLIENT Side Code as below to get the total write bytes without garbage
int availableByte = socket.available();
if (availableByte > 0) {
byte[] buffer = new byte[availableByte];
int bytesRead = socketInputStream.read(buffer);
FileOutputStream fileOutputStream = new FileOutputStream(FilePath, true);
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream);
BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);
bufferedWriter.write(buffer.toString());
bufferedWriter.close();
}
Related
Using Java, I am trying to send some file data over a DatagramSocket. I need to read a file in 1000-byte chunks and send them over as packets. My code:
reads a file into a byte array wrapped in a byte buffer
places the data in a packet and sends it
has the receiver open the packet and re-write the contents to a new file.
I am having a problem with writing the byte array back to a file. Please see my code below.
Client/Sender:
byte[] data = new byte[1000];
ByteBuffer b = ByteBuffer.wrap(data);
DatagramPacket pkt;
File file = new File(sourceFile);
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
CRC32 crc = new CRC32();
while(true){
b.clear();
b.putLong(0); // I need to put the checksum at the beginning for easy retrieval
bytesRead = bis.read(data);
if(bytesRead==-1) { break; }
crc.reset();
crc.update(data, 8, data.length-8);
long chksum = crc.getValue();
b.rewind();
b.putLong(chksum);
pkt = new DatagramPacket(data, 1000, addr); // addr is valid, works fine
sk.send(pkt);
}
bis.close();
fis.close();
Server/Receiver:
DatagramSocket sk = new DatagramSocket(port);
File destfile = new File("hello.txt");
FileOutputStream fos = new FileOutputStream(destfile);
BufferedOutputStream bos = new BufferedOutputStream(fos);
PrintStream ps = new PrintStream(fos);
byte[] data = new byte[1000];
DatagramPacket pkt = new DatagramPacket(data, data.length);
ByteBuffer b = ByteBuffer.wrap(data);
CRC32 crc = new CRC32();
while(true) {
pkt.setLength(data.length);
sk.receive(pkt);
b.rewind();
// compare checksum, print error if checksum is different
// if checksum is the same:
bos.write(data); // Where the problem seems to be occurring.
// send acknowledgement packet.
}
bos.close();
fos.close();
Here, I am mainly having issues with writing the file back. With a small text file that says Hello World!, I get a strange output that says vˇ]rld!. Also, the input file is only 12 bytes but the file that the receiver creates is 1KB.
I think my issue is dealing with a byte buffer - I've written a program that copies files using file streams and buffered streams, which worked well. But I'm confused with how streams work in this sort of situation, and I would really appreciate any help. Thanks!
In the sender's data[] you overwrite the text, which was read from the file by the crc! You have to read the text in a position after the long. When correcting this in the Sender, it works:
//int bytesRead = bis.read(data); --old code
int bytesRead=bis.read(data,8,data.length-8);
Furthermore you send 1000 bytes, so will receive 1000 bytes, which will go into the destfile.
BTW: you do not check the crc in the server.... so why send it ?
i am trying to make a java server that will send images stored in a database to android device.
for now am trying with simple image that stored on the hard disk for the server to send.
my question is can i send an image from java server as a byte array to android via TCP sockets.
Yes, you can, using TCP sockets.
Read the file as bytes and send it as bytes, don't try to load it as a BufferedImage.
Then, on the receiving end, use a function that allows you to load an image from an array of bytes.
Sure, you can, but you will need to invent your own protocol for that. You may find using HTTP more, either setting up a web-server like Tomcat with your application deployed there, or use something embedded like Jetty
The fastest and easiest approach for sending image is as follows...
Try this
// Server Side code for image sending
ServerSocket servsock = new ServerSocket(13250);
System.out.println("Main Waiting...");
Socket sock = servsock.accept();
System.out.println("Accepted connection : " + sock);
File myFile = new File ("\sdcard\ab.jpg");
byte [] mybytearray = new byte [(int)myFile.length()];
FileInputStream fis = new FileInputStream(myFile);
BufferedInputStream bis = new BufferedInputStream(fis);
bis.read(mybytearray,0,mybytearray.length);*/
byte [] mybytearray =new byte[count];
System.arraycopy(Copy, 0, mybytearray, 0, count);
OutputStream os = sock.getOutputStream();
System.out.println("Sending...");
os.write(mybytearray,0,mybytearray.length);
os.flush();
os.close();
sock.close();
servsock.close();
//Client side code for image reception
try
{
int filesize=6022386; // filesize temporary hardcoded
long start = System.currentTimeMillis();
int bytesRead;
int current = 0;
// localhost for testing
ServerSocket servsocket = new ServerSocket(13267);
System.out.println("Thread Waiting...");
Socket socket = servsocket.accept();
System.out.println("Accepted connection : " + socket);
System.out.println("Connecting...");
File f=new File("\sdcard\ab.jpg");
f.createNewFile();
// receive file
byte [] mybytearray = new byte [filesize];
InputStream is = socket.getInputStream();
FileOutputStream fos = new FileOutputStream(f);
BufferedOutputStream bos = new BufferedOutputStream(fos);
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);
count=current;
Copy=mybytearray.clone();
bos.write(mybytearray, 0 , current);
bos.flush();
long end = System.currentTimeMillis();
System.out.println(end-start);
bos.close();
fos.close();
socket.close();
servsocket.close();
}
} catch(IOException e)
{
System.out.println("errorr");
}
My application is unable to transfer data properly over a socket connection and write it to a file properly. Files over about 65,535 bytes get corrupted and are no longer recognized by the programs designed to run them.
I have been able to send small .doc and .txt files successfully, but .mp3 .wmv .m4a .avi and just about anything else does not work. Neither do larger docs.
I have looked all over the internet for a solution to this problem. I have repeatedly tweaked the I/O code to fix the problem but it still doesn't work! Here is the I/O code in the super class that handles sending and receiving files. If you need anymore information/other parts of code, let me know.
protected void sendFile() throws IOException {
byte[] bytes = new byte[(int) file.length()];
buffin = new BufferedInputStream(new FileInputStream(file));
int bytesRead = buffin.read(bytes,0,bytes.length);
System.out.println(bytesRead);
out = sock.getOutputStream();
out.write(bytes,0,fileBytes);
out.flush();
out.close();
}
protected void receiveFile() throws IOException {
byte[] bytes = new byte[fileBytes];
in = sock.getInputStream();
for(int i=0;i<fileBytes;i++) {
in.read(bytes);
}
fos = new FileOutputStream("/Datawire/"+fileName);
buffout = new BufferedOutputStream(fos);
buffout.write(bytes,0,fileBytes);
buffout.flush();
buffout.close();
}
UPDATED CODE (that works):
protected void sendFile() throws IOException {
if((file.length())<63000) {
byte[] bytes = new byte[(int)file.length()];
buffin = new BufferedInputStream(new FileInputStream(file));
buffin.read(bytes,0,bytes.length);
out = sock.getOutputStream();
out.write(bytes,0,bytes.length);
out.close();
} else {
byte[] bytes = new byte[32000];
buffin = new BufferedInputStream(new FileInputStream(file));
out = sock.getOutputStream();
int bytesRead;
while((bytesRead = buffin.read(bytes))>0) {
out.write(bytes,0,bytesRead);
}
out.close();
}
}
protected void receiveFile() throws IOException {
if(fileBytes<63000) {
byte[] bytes = new byte[32000];
in = sock.getInputStream();
System.out.println(in.available());
in.read(bytes,0,fileBytes);
fos = new FileOutputStream("/Datawire/"+fileName);
buffout = new BufferedOutputStream(fos);
buffout.write(bytes,0,bytes.length);
buffout.close();
} else {
byte[] bytes = new byte[16000];
in = sock.getInputStream();
fos = new FileOutputStream("/Datawire/"+fileName);
buffout = new BufferedOutputStream(fos);
int bytesRead;
while((bytesRead = in.read(bytes))>0) {
buffout.write(bytes,0,bytesRead);
}
buffout.close();
}
}
The issue is that you are sending only chunks of it. That is, you are only sending 64k of the file ever. If the file is ever larger then 64k the other end will never see it.
You want to continously read from the BufferedInputStream until the read() returns either less then the length or -1.
Your code is completely wrong. This is how to copy a stream in Java:
int count;
byte[] buffer = new byte[8192]; // more if you like but no need for it to be the entire file size
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
You should use this both when sending the file and when receiving the file. At present your sending method hopes that the entire file fits into memory; fits into INTEGER_MAX bytes; and is read in one chunk by the read method, without even checking the result. You can't assume any of those things. Your receive method is complete rubbish: it just keeps overwriting the same array, again without checking any read() results.
EDIT: Your revised code is just as bad, or worse. You are calling read() to check for EOS and then throwing that byte away, and then calling read() again and throwing away the read count it returns. You pointlessly have a different path for files < 64000, or 63000, or whatever it is, that has zero benefit except to give you two code paths to test, or possibly four, instead of one. The network only gives you 1460 bytes at a time at best anyway so what is the point? You already have (a) a BufferedInputStream with a default buffersize of 8192, and (b) my code that uses a byte[] buffer of any size you like. My code above works for any amount of data in two lines of executable code. Yours is 20. QED.
I suggest that you use some good library to read and write file contents as well as socket read/write. For example Apache Commons IO. If you insist on writig code yourself, do it smaller chunks rather than the whole file at once.
You have to consider that InputStream.read returns the number of bytes read which may be less than the total number of bytes in the file.
You would probably be better off just letting something like CopyUtils.copy take care of this for you.
You need to loop until bytesRead < 0. You need to make sure that fileBytes is => than the transferred file.
protected void receiveFile() throws IOException {
byte [] bytes = new byte [fileBytes];
InputStream is = sock.getInputStream();
FileOutputStream fos = new FileOutputStream("/Datawire/"+fileName);
BufferedOutputStream bos = new BufferedOutputStream(fos);
int bytesRead = is.read(bytes,0,bytes.length);
int current = bytesRead;
do {
bytesRead =
is.read(bytes, current, (bytes.length-current));
if(bytesRead >= 0) current += bytesRead;
} while(bytesRead > -1);
bos.write(bytes, 0 , current);
bos.flush();
bos.close();
}
I have written a java code which sends a .exe file from the server to the client using FileInputStream and BufferedInputStream, but the file gets corrupted at the client side.
What could be the reason?
command1= ServerFrame.msg1+".exe";
File p=new File(command1);
FileInputStream f=new FileInputStream(p);
BufferedInputStream bis=new BufferedInputStream(f);
Integer d=bis.available();
int d1=d;
byte b[]=new byte[d];
bis.read(b,0,d1);
System.out.println(d1);
dos=new DataOutputStream(s.getOutputStream());
BufferedOutputStream bos=new BufferedOutputStream(s.getOutputStream());
dos.writeUTF(d.toString()); // sending length in long
bos.write(b,0,d1); // sending the bytess
bos.flush();
bis.close();
bos.close();
dos.close();
I suppose that s is your socket. There are few thing that can be wong in your code:
bis.available() returns the number of bytes that can be read without bocking, not the total size of the file, you should use a loop to read the file
you use the output stream in two different buffers and you write to both of them without flushing; also, why are you writing UTF?
Here is what you intend to do:
private void copy(InputStream in, OutputStream out) {
byte[] buf = new byte[0x1000];
int r;
while ((r = in.read(buf)) >= 0) {
out.write(b, 0, r);
}
}
InputStream in = new BufferedInputStream(new FileInputStream(path));
OutputStream out = new BufferedOutputStream(s.getOutputStream());
copy(in, out);
in.close();
out.close();
bis.available() returns the bytes available for read, it may not be the full content size, u have to read in a loop till it reaches EOF.
in case someone stuck with same problem, buffer size is the culprit in this case :
Integer d=bis.available();
byte b[]=new byte[d];
It should be lesser try 1024 or something:
byte b[]=new byte[1024];
hope this helps..
I want to send files as well as some other information through sockets. I am using the following code
public void receiveFile(Socket socket,int filesize,String filename) throws IOException
{
//after receiving file send ack
System.out.println("waiting ");
// int filesize=70; // filesize temporary hardcoded
long start = System.currentTimeMillis();
int bytesRead;
int current = 0;
// localhost for testing
System.out.println("Connecting...");
// receive file
byte [] mybytearray = new byte [filesize];
InputStream is = socket.getInputStream();
FileOutputStream fos = new FileOutputStream(filename);
BufferedOutputStream bos = new BufferedOutputStream(fos);
bytesRead = is.read(mybytearray,0,mybytearray.length);
current = bytesRead;
System.out.println("recv..."+mybytearray.length);
do {
bytesRead =
is.read(mybytearray, current, (mybytearray.length-current));
System.out.println(bytesRead);
if(bytesRead > 0) current += bytesRead;
} while(bytesRead > 0);
bos.write(mybytearray, 0 , current);
bos.flush();
long end = System.currentTimeMillis();
System.out.println(end-start);
bos.close();
System.out.println(" File received");
}
After receiving the file, I have to receive some other strings. But when I try to read the input stream, I am getting the contents of the file. How to flush the contents of the file from the inputstream.
BufferedReader inFromServer =
new BufferedReader(new InputStreamReader(
webServerSocket.getInputStream()));
receiveFile(webServerSocket,filesize,filename);
while(true)
{
msg = inFromServer.readLine(); //here i receive the contents of the file again
System.out.println(msg);
}
Pass the socket's inputstream to the receivefile-method, instead of the socket itself:
InputStream is = webServerSocket.getInputStream();
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(is));
receiveFile(webServerSocket,filesize,filename);
The problem lies, I believe, in the fact that you have two inputstreams from the same socket made at the same point in time (before any data has actually been read). They point to the same stream but reading from one does not move the other as well, thus after reading from inputstreamBA that one is marked in position 15 (for example) while inpustream A is still in poisition 0, at the beginning of the stream.
(EDIT:)
Ofcourse, you have to use the inputstream in the receiveFile method instead of getting one from the socket. Another solution would be to get the inputstream from the socket after the call to receive file, as in
receiveFile(webServerSocket,filesize,filename);
BufferedReader inFromServer =
new BufferedReader(new InputStreamReader(webServerSocket.getInputStream()));
By reading the file to completion, you will have read the whole file. If you are still getting the contents of the file, you haven't read the whole file.