I have been trying to create a Messenger with file transfer capabilities, but I keep having too many null characters at the end. any time I use the file length to strip them, for some reason more of the file gets stripped and it just becomes a total mess. I'm not using any Java 7 or higher elements as I want it compatible with Java 6, and Windows 98 (grandma's PC).
I also get a lot of random null characters added into the file, im not sure how to avoid this
This is my code:
Transmit
package com.androdome.lunacoffee.management;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import com.androdome.lunacoffee.ErrorScreen;
import com.androdome.lunacoffee.SendScreen;
public class FileTransmitter implements Runnable{
String adds;
FileInputStream message;
int filecut = 4096;
byte[] fileName;
long fileSize;
SendScreen send;
public FileTransmitter(String address, FileInputStream msg, byte[] fnme, SendScreen snd, long l) {
adds = address;
send = snd;
message = msg;
fileName = fnme;
fileSize = l;
}
public void run()
{
try {
InetAddress add = InetAddress.getByName(adds);
Socket sock = new Socket(add, 11001);
DataOutputStream da = new DataOutputStream(sock.getOutputStream());
PrintWriter output = new PrintWriter(da);
da.write(fileName);
da.writeLong(message.getChannel().size());
byte[] filebuffer = new byte[filecut];
int g = 0;
int back = 0;
while((g = message.read(filebuffer)) != -1)
{
if(g != filecut && g > 0)
{
back = g;
}
da.write(filebuffer);
filebuffer = new byte[filecut];
}
da.writeInt(back);
System.out.print(back);
output.flush();
output.close();
send.incrementSent();
} catch (UnknownHostException e) {
send.incrementError();
// TODO Auto-generated catch block
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
new ErrorScreen("Unable to send file", "Your file was not able to send because the host \"" + adds + "\" was not availible!", sw.toString());
pw.close();
try {
sw.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
} catch (IOException e) {
send.incrementError();
// TODO Auto-generated catch block
new ErrorScreen("Unable to send file", "Your file was not able to send due to a bad output stream!", e.getMessage());
}
}
}
Recieve:
package com.androdome.lunacoffee.management;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Arrays;
import com.androdome.lunacoffee.ErrorScreen;
import com.androdome.lunacoffee.FileScreen;
import com.androdome.lunacoffee.Main;
public class FileReciever implements Runnable {
int bufferSize = 4096;
int headerSize = 32;
byte[] filebuffer = new byte[bufferSize];
byte[] fileheader = new byte[headerSize];
Main main;
File downloadfile = new File("tmp");
File transferFile = new File("dnl.ldf");
public FileReciever(Main mn)
{
main = mn;
}
static byte[] trim(byte[] bytes)
{
int i = bytes.length - 1;
while (i >= 0 && bytes[i] == 0)
{
--i;
}
return Arrays.copyOf(bytes, i + 1);
}
public void run() {
try {
ServerSocket recieveSocket = new ServerSocket(11001);
while (this != null) {
try{
downloadfile.createNewFile();
Socket connectionSocket = recieveSocket.accept();
DataInputStream reader = new DataInputStream(connectionSocket.getInputStream());
reader.read(fileheader);
long fileSize = reader.readLong();
System.out.println(bufferSize);
filebuffer = new byte[bufferSize];
String fileName = new String(fileheader);
fileheader = new byte[headerSize];
FileOutputStream fw = new FileOutputStream(downloadfile);
while(reader.read(filebuffer) != -1)
{
fw.write(filebuffer);
filebuffer = new byte[bufferSize];
}
//reader.readInt();
reader.close();
fw.close();
//RandomAccessFile file = new RandomAccessFile(downloadfile, "Rwd");
//file.setLength(fileSize); // Strip off the last _byte_, not the last character
//file.close();
connectionSocket.close();
FileScreen fs = new FileScreen(downloadfile, fileName, connectionSocket.getInetAddress().getHostName());
fs.setVisible(true);
fs.setLocationRelativeTo(null);
}
catch(Exception ex)
{}
}
} catch (IOException e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
new ErrorScreen("Unable to start the File Recieve Thread", "Luna Messenger may already be running, or another program is using port 11001. Please close any program running on port 11001.", sw.toString());
pw.close();
try {
sw.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
}
In your above code,i think it makes following mistake.
The first,you should add a number which indicate the filename's length.like this:
da.writeInt(fileName.length); //the added code
da.write(fileName);
On the FileReciever,the receive code is :
int fileNameLength = reader.readInt();
fileheader=new byte[fileNameLength];
read(reader,fileheader,0,fileNameLength);
the read method can read up to length bytes from input stream into a array of bytes until the stream is end.
public static int read(InputStream in, byte[] b, int off, int len) throws IOException {
if (len < 0) {
throw new IndexOutOfBoundsException("len is negative");
}
int total = 0;
while (total < len) {
int result = in.read(b, off + total, len - total);
if (result == -1) {
break;
}
total += result;
}
return total;
}
The second,it is not correctly that the FileTransmitter translate the file date to the FileReciever,and should not add a number at end.The appropriate approach is just writing file data to socket outputstream in FileTransmitter,and don't do any other things.Like this:
while((g = message.read(filebuffer)) != -1)
{
da.write(filebuffer,0,g);
}
On the orther hand,and how many bytes should be readed depend on the length of bytes that your readed from the socket's inputstream ago, when you read the bytes from socket oupustream into filebuffer.the receiver code:
int readLength;
int sumLength=0;
while((readLength=reader.read(filebuffer,0,(int)(fileSize-sumLength>filebuffer.length?filebuffer.length:fileSize-sumLength))) != -1){
sumLength+=readLength;
fw.write(filebuffer,0,readLength);
if(sumLength==fileSize){
break;
}
}
Related
I want to implement an application that will allow me to transfer files between client and server.
The client requests a file, if the file is not used by another client the server will send the file, otherwise the thread id will be saved in the queue.
My question is how i can check if the file is used by another thread ?
here is my code :
ClientFile.java
import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
public class ClientFile {
public static void main(String[] args) {
try {
Socket socket = new Socket("localhost", 43333);
System.out.println(socket.getInetAddress().getHostName());
//Read and write on socket.
PrintWriter printWriter = new PrintWriter(socket.getOutputStream(), true);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//Read from console.
BufferedReader bfIn = new BufferedReader(new InputStreamReader(System.in));
String line = null;
while ((bufferedReader.read()) != '~') {
System.out.println(bufferedReader.readLine());
}
//DemanderF
System.out.print("Enter File Id: ");
int response = bfIn.read();
printWriter.println(response);
//From ASCII TO INT.
int fileId = Character.getNumericValue(response);
//System.out.println("blabla " + fileId);
/*-----------------Receive F------------------*/
//The inputStream class will capture the streams which has been sent by the server.
InputStream inputStream = socket.getInputStream();
receiveF(inputStream, fileId);
/*---------------------------------------*/
bufferedReader.close();
printWriter.close();
socket.close();
} catch(IOException e) {
e.printStackTrace();
//System.out.println("IOException Client ---> "+ e.getStackTrace());
}
}
public static void receiveF(InputStream inputStream, int fileId)
{
try {
//Create File inside desired folder
FileOutputStream fileOutputStream = new FileOutputStream("D:\\newFile.txt");
//byte array (size of the file).
byte []b = new byte[2002];
//Read a Stream.
inputStream.read(b, 0, b.length);
//Write the whole content into file.
fileOutputStream.write(b, 0, b.length);
fileOutputStream.close();
} catch(IOException e) {
e.printStackTrace();
}
}
}
ServerFile.java
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.rmi.UnknownHostException;
import java.util.Arrays;
public class ServerFile {
public static void main(String[] args) {
try {
//create ServerSocket on port 43333.
ServerSocket serverSocket = new ServerSocket(43333);
while(true)
{
System.out.println("Running...");
//accept incoming Client request.
Socket clientSocket = serverSocket.accept();
System.out.println("\nClient connected");
//System.out.println("Id Client : " +clientSocket);
System.out.println("Assigning new thread for this client");
Thread t = new ClientHandler(clientSocket);
t.start();
}
} catch(UnknownHostException e) {
System.out.println("UnknownHostException ---> " + e.getMessage());
}
catch(IOException e1) {
System.out.println("IOException ---> " + e1.getMessage());
}
}
static class ClientHandler extends Thread {
Socket clientSocket;
public ClientHandler(Socket clientSocket)
{
this.clientSocket = clientSocket;
}
#Override
public void run() {
try {
//Read and write on socket.
PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(clientSocket.getOutputStream()), true);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
//Send File list.
String directoryName = "C:\\Users\\AZZEM\\Documents\\Master 1\\Système répartis\\Files";
File file = new File(directoryName);
File fileList[] = file.listFiles();
int c = 0;
for(int i=0; i<fileList.length; i++)
{
if(fileList[i].canRead() && (fileList[i].toString().endsWith(".txt")))
{
c++;
}
//System.out.println("File list : " + fileList[i].getName() + " and Size = " + fileList[i].length() + "bytes");
}
printWriter.println(" " + c + " .txt files, listed A-Z \n");
for(int i=0; i<fileList.length; i++)
{
printWriter.println(" " + fileList[i].getName() + " and Size = " + fileList[i].length() + "bytes");
}
printWriter.println("~");
String response = bufferedReader.readLine();
int fid = Integer.parseInt(response);
//From ASCII TO INT.
int fileId = Character.getNumericValue(fid);
int threadId = (int) Thread.currentThread().getId();
System.out.println("My id is " + threadId + " and I want the file "+ fileId);
boolean isExist = false;
if(fileId >=0 && fileId<=fileList.length)
{
isExist = true;
}
else
{
isExist = false;
System.out.println("File not exist");
}
if(isExist == true)
{
System.out.println("The file " + fileId + "is used");
/*--------------------------Send File to Client------------------------------*/
File fileToSend = new File(fileList[fileId].getAbsolutePath());
FileReader fileReader = new FileReader(fileToSend);
//Read File.
FileInputStream fileInputStream = new FileInputStream(fileList[fileId].getAbsolutePath());
//Byte Array is used to include the size of the array.
byte[]b = new byte[2002];
//The read method --> Start reading the file from 0 to the end of the file (length).
//And store it in new variable which is b.
fileInputStream.read(b, 0, b.length);
//Convert file into streams.
OutputStream outputStream = clientSocket.getOutputStream();
//Send the whole file using outputStream class.
System.out.println("Sending File...");
outputStream.write(b, 0, b.length);
System.out.println("File Transferred");
fileInputStream.close();
/*---------------------------------------------------------------------------------*/
}
bufferedReader.close();
printWriter.close();
clientSocket.close();
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}
}
I have send a image that is about 500kb but in the server ,the image that receive is more than 500kb.I wonder that is there any logical problems I had made? the speed of the network is about 100kb/s.
the client
package client;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.OutputStreamWriter;
import java.net.Socket;
public class client {
public static void main(String[] args) {
Socket s = null;
BufferedOutputStream bo = null;
BufferedInputStream bi = null;
try {
s = new Socket("127.0.0.1",12349);
bo = new BufferedOutputStream(s.getOutputStream());
bi = new BufferedInputStream(new FileInputStream("1.jpg"));
byte [] bys =new byte[1024];
while((bi.read(bys))!=-1){
bo.write(bys);
}
bo.flush();
System.out.println("already post the image");
bi.close();
} catch (IOException e) {
}finally{
try {
s.close();
} catch (IOException e) {
System.out.println("close failed");
}
}
}
}
server
package server;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class sserver {
public static void main(String[] args) {
ServerSocket ss = null;
Socket s = null;
BufferedOutputStream bo = null;
BufferedInputStream bs = null;
try {
ss = new ServerSocket(12349);
s = ss.accept();
bo = new BufferedOutputStream(new FileOutputStream("2.jpg"));
bs = new BufferedInputStream(s.getInputStream());
byte [] bys =new byte[1024];
while((bs.read(bys))!=-1){
bo.write(bys);
}
bo.flush();
System.out.println("upload success");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
ss.close();
} catch (IOException e) {
System.out.println("close failed");
}
}
}
}
The problem is that you are disregarding the number of bytes read:
while((bi.read(bys))!=-1){
bo.write(bys);
}
This means that you always write 1024 bytes to bo, even if you read fewer than 1024 bytes from bi.
You need to assign the number of bytes read to a variable, and pass that to the write call:
int bytesRead;
while((bytesRead = bi.read(bys))!=-1){
bo.write(bys, 0, bytesRead);
}
Please write exacte byte which you received like below
int len= 0 ;
while( ( len = bi.read(bys))!=-1){
bo.write(bys,0, len);
}
Same code change required in both client and server side. I tested at my end and found that both file has same size afterthis change
Your server code is always writing full length of bys array into output stream.
Proper way to do it:
byte [] bys =new byte[1024];
while(true) {
int numRead = bs.read(bys);
if (numRead == -1)
break;
bo.write(bys, 0, numRead);
}
So I am kinda stuck on a program where I have to read a text file, using FileInputStream and divide that text into chunks of n-bytes. I have to issue one System.out.write(); call for each chunk, so I am wondering if there is a simple way to do this. Thanks!
package test;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.*;
import java.io.*;
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
int size=0;
FileInputStream fstream = null;
Scanner console = new Scanner(System.in);
String inputFile = console.next();
System.out.println("Chunk size?");
Scanner in = new Scanner(System.in);
size = in.nextInt();
try {
fstream = new FileInputStream(inputFile);
System.out.println("Size in bytes : "
+ fstream.available());
int content;
while ((content = fstream.read()) != -1) {
//System.out.write(); for every chunk of *size* bytes
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fstream != null)
fstream.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
use
byte[] bytes = new byte[size];
int byteCount;
while((byteCount = fstream.read(bytes)) != -1)
...
you can simply create a string this way:
new String(bytearray);
PS. sry for the missing codehighlighting, didn't work properly for some reason...
I'm trying to develop a simple Java file transfer application using TCP.
My current server code is as follows:
package tcp.ftp;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class FTPServer {
public static void main(String[] args) {
new FTPServer().go();
}
void go() {
try {
ServerSocket server = new ServerSocket(2015);
System.out.println("server is running ....!");
while (true) {
Socket socket = server.accept();
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String file = reader.readLine();
System.out.println("file to be downloaded is : " + file);
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
while (true) {
int octet = bis.read();
if (octet == -1) {
break;
}
bos.write(octet);
}
bos.flush();
//bos.close();
}
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
}
}
Using my current server code above, the downlloding does not work as expected. the above code sends part of the file to the client , not the entire file. Note that I used the flush method to flush the buffer. but when I replace the flush () method by the close () method, the file is fully sent to the client whithout any loss. Could anyone please explain this behavior!
UPDATE: Here is the code of my client:
package tcp.ftp;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
/**
*
* #author aaa
*/
public class FTPClient {
public static void main(String[] args) {
String file = "JasperReports-Ultimate-Guide-3.pdf";
try {
InetAddress address = InetAddress.getLocalHost();
Socket socket = new Socket(address, 2015);
System.out.println("connection successfully established ....!");
PrintWriter pw = new PrintWriter(socket.getOutputStream());
pw.println(file);
pw.flush();
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy" + file));
while (true) {
int octet = bis.read();
if (octet == -1) {
break;
}
bos.write(octet);
}
bos.flush();
System.out.println("file download is complete ...!");
} catch (UnknownHostException ex) {
System.out.println(ex.getMessage());
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
}
}
Another behavior without the use of Socket. take the following code that copy a file from a source to a destination:
public class CopieFile {
static void fastCopy(String source, String destination) {
try {
FileInputStream fis = new FileInputStream(source);
BufferedInputStream bis = new BufferedInputStream(fis);
FileOutputStream fos = new FileOutputStream(destination);
BufferedOutputStream bos = new BufferedOutputStream(fos);
while (true) {
int octet = bis.read();
if (octet == -1) {
break;
}
bos.write(octet);
}
bos.flush();
} catch (FileNotFoundException ex) {
System.out.println(ex.getMessage());
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
}
public static void main(String[] args) throws IOException {
String source = "...";
String destination = "...";
fastCopy(source, destination);
}// end main
}// end class
the above code to copy a file from one location to another without any loss. Note well that I did not close the stream.
If you never close the stream the client wil never get end of stream so it will never exit the read loop.
In any case the stream and the socket are about to go out of scope, so if you don't close them you have a resource leak.
I have a Client-Server programm. The Client-programm sends a file to the server and the server receives the file. my problem is, that the file is not really receiving on the server...I't creates a file.txt in the server-directory, but it is empty...(yes i'm sure that ne file.txt in the client-directory is not empty ;) )
I think the problem is the while-loop in Client.java, because it is never embarrassed....
For the future i implements now on the server side one thread per receiving file.
The client-programm:
package controller;
public class Main {
public static void main(String[] args) {
new Controller();
}
}
-
package controller;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class Controller {
public Controller() {
try {
sendFileToServer();
} catch (IOException e) {
e.printStackTrace();
}
}
public void sendFileToServer() throws UnknownHostException, IOException {
Socket socket = null;
String host = "localhost";
socket = new Socket(host, 5555);
String filename = "file.txt";
File file = new File(filename);
OutputStream outText = socket.getOutputStream();
PrintStream outTextP = new PrintStream(outText);
outTextP.println(filename);
long filesize = file.length();
byte[] bytes = new byte[(int) filesize];
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
BufferedOutputStream out = new BufferedOutputStream(socket.getOutputStream());
int count;
System.out.println("Start sending file...");
while ((count = bis.read(bytes)) > 0) {
System.out.println("count: " + count);
out.write(bytes, 0, count);
}
System.out.println("Finish!");
out.flush();
out.close();
fis.close();
bis.close();
socket.close();
}
}
-
The server-programm:
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {
new Server();
}
}
-
public class Server {
private ServerSocket serverSocket;
public Server() {
try {
serverSocket = new ServerSocket(5555);
waitForClient();
} catch (IOException e) {
e.printStackTrace();
}
}
private void waitForClient() {
Socket socket = null;
try {
while(true) {
socket = serverSocket.accept();
Thread thread = new Thread(new Client(socket));
thread.start();
}
} catch (IOException ex) {
System.out.println("serverSocket.accept() failed!");
}
}
}
-
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Socket;
public class Client implements Runnable{
private Socket socket;
public Client(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
receiveFile();
}
private void receiveFile() {
try {
InputStream is = null;
FileOutputStream fos = null;
BufferedOutputStream bos = null;
int bufferSize = 0;
InputStream outText = socket.getInputStream();
// Get filename
InputStreamReader outTextI = new InputStreamReader(outText);
BufferedReader inTextB = new BufferedReader(outTextI);
String dateiname = inTextB.readLine();
System.out.println("Dateiname: " + dateiname);
try {
is = socket.getInputStream();
bufferSize = socket.getReceiveBufferSize();
System.out.println("Buffer size: " + bufferSize);
} catch (IOException ex) {
System.out.println("Can't get socket input stream. ");
}
try {
fos = new FileOutputStream(dateiname);
bos = new BufferedOutputStream(fos);
} catch (FileNotFoundException ex) {
System.out.println("File not found.");
}
byte[] bytes = new byte[bufferSize];
int count;
while ((count = is.read(bytes)) > 0) {
bos.write(bytes, 0, count);
System.out.println("This is never shown!!!"); // In this while-loop the file is normally receiving and written to the directory. But this loop is never embarrassed...
}
bos.flush();
bos.close();
is.close();
socket.close();
}catch(IOException e) {
e.printStackTrace();
}
}
}
When you do these kind of transfers you have to keep in mind that there is a difference between a socket's close and shutdown, in your code you close the socket in the client.
So lets see what happens : you fill in the buffers then you tell the socket to close which will discard the operation you just asked for.
When you shutdown you tell the socket "I won't send more data but send what's left to be sent and shut down" so what you need to do is to shut down the socket before you close it so the data will arrive.
So instead of this
out.flush();
out.close();
fis.close();
bis.close();
socket.close();
Try it with this
out.flush();
socket.shutdownInput(); // since you only send you may not need to call this
socket.shutdownOutput(); // with this you ensure that the data you "buffered" is sent
socket.close();
Generally if you want a graceful close, you should do it like this in all cases even for the server, so what you did is usually okay if there is an error and you just close the connection since you cant recover from an error.