I'm creating File Transfer program that will transfer a file to client. But when I transferred the file, It missing the first letter of every lines. What's wrong with my code?
I'm pretty new at java so I don't know what to do next. I've tried changing byte size but no help. What should I do?
Server.java
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
class Server {
public static void main(String[] args) throws IOException {
FileInputStream fis = null;
BufferedInputStream bis = null;
OutputStream os = null;
ServerSocket serverSocket = null;
Scanner scan = new Scanner(System.in);
String fileSend;
System.out.print("Type the path to the file to send >> ");
fileSend = scan.nextLine();
try {
serverSocket = new ServerSocket(5467);
} catch (Exception e) {
System.out.println("Could not bind to port 5467, Maybe address is already is use or you need to run as administrator");
return;
}
System.out.println("Listening on port 5467");
System.out.println("Waiting for the connection...");
while (true) {
File FileSend = null;
Socket socket = serverSocket.accept();
OutputStream out = socket.getOutputStream();
System.out.println("Accepted connection : " + socket);
InputStream in = socket.getInputStream();
DataInputStream dataIn = new DataInputStream(in);
String login = dataIn.readUTF();
String password = dataIn.readUTF();
String result = "You credential is ";
if (login.equals("1c18b5cdef8f9b4c5d6b2ad087265e597d1d4639337b73a04a335103c00ec64b") && password.equals("1c18b5cdef8f9b4c5d6b2ad087265e597d1d4639337b73a04a335103c00ec64b13d0b73358bfa8978dfaaf180565bcfecd3dc0631cda525920865145fb3fa131")) {
result += "correct";
} else {
result += "incorrect";
}
DataOutputStream dataOut = new DataOutputStream(out);
try {
dataOut.writeUTF(result);
} catch (FileNotFoundException e) {
System.out.println("No such file or directory");
}
finally
{
FileSend = new File(fileSend);
byte[] FileByteArray = new byte[(int) FileSend.length()];
try {
fis = new FileInputStream(FileSend);
}
catch (FileNotFoundException e) {
System.out.println("No such file or directory");
return;
}
bis = new BufferedInputStream(fis);
File myFile = new File (fileSend);
byte [] mybytearray = new byte [(int)myFile.length()];
fis = new FileInputStream(myFile);
bis = new BufferedInputStream(fis);
bis.read(mybytearray,0,mybytearray.length);
os = socket.getOutputStream();
System.out.println("Sending " + fileSend + "(" + mybytearray.length + " bytes)");
os.write(mybytearray,0,mybytearray.length);
os.flush();
System.out.println("Done.");
}
}
}
}
Client.java
import java.io.*;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class Client {
public static void main(String[] args) throws IOException, NoSuchAlgorithmException {
Socket socket = null;
String PlainLogin;
String FileOut;
String PlainPassword;
Scanner scan = new Scanner(System.in);
System.out.print("What is the IP address of the server >> ");
String host = scan.nextLine();
try {
socket = new Socket(host, 5467);
} catch (ConnectException | NullPointerException e) {
System.out.println("Connection Refused, Have you run the server first?");
return;
}
OutputStream out = socket.getOutputStream();
DataOutputStream dataOut = new DataOutputStream(out);
InputStream is = socket.getInputStream();
System.out.println("Connection Established");
System.out.println("Credential Required, Please login");
System.out.print("Type your username >> ");
PlainLogin = scan.next();
System.out.print("Type your password >> ");
PlainPassword = scan.next();
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] hashInBytes = md.digest(PlainLogin.getBytes(StandardCharsets.UTF_8));
StringBuilder sb = new StringBuilder();
for (byte b : hashInBytes) {
sb.append(String.format("%02x", b));
}
String HashedLogin = sb.toString();
byte[] hashInBytesP = md.digest(PlainPassword.getBytes(StandardCharsets.UTF_8));
for (byte b : hashInBytesP) {
sb.append(String.format("%02x", b));
}
String HashedPassword = sb.toString();
dataOut.writeUTF(HashedLogin);
dataOut.writeUTF(HashedPassword);
InputStream in = socket.getInputStream();
DataInputStream dataIn = new DataInputStream(in);
String str = dataIn.readUTF();
if (str == "Your credential is incorrect") {
System.out.println(str);
return;
} else {
System.out.print("Type any file name you want >> ");
scan.nextLine();
FileOut = scan.nextLine();
OutputStream output = new FileOutputStream(FileOut);
byte[] mybytearray = new byte[1024];
is.read(mybytearray, 0, mybytearray.length);
int bytesRead;
byte[] buffer = new byte[1024];
while ((bytesRead = in.read(buffer)) > 0) {
output.write(buffer, 0, bytesRead);
}
output.close();
socket.close();
dataIn.close();
System.out.println("Done");
return;
}
}
}
I expect it to show full text like "Java", but it only show "ava"
File is Serializable, so I would suggest you should simply try to send it directly via ObjectOutputStream / ObjectInputStream.
For example on Server side :
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
...
out.writeObject(yourFileObject);
And on Client :
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
...
File receivedFile = null;
try {
receivedFile = (File) in.readObject();
}
catch (IOException e) {
...
}
I'm not entirely sure why this happens exactly, but you shouldn't be using DataInputStream which "lets an application read primitive Java data types", but an InputStreamReader which "is a bridge from byte streams to character streams".
Also, you can wrap that reader into a BufferedReader which lets you read line by line, and you'll end up with something like
try (BufferedReader reader=new BufferedReader(new InputStreamReader(inStream, UTF8));
PrintWriter writer = new PrintWriter(file)) {
reader.lines().forEach(writer::println);
}
for an upload, or
try (PrintWriter writer = new PrintWriter(outStream)) {
Files.lines().forEach(writer::println);
}
for download.
Related
I have a Raspberry pi 4 with Raspbian installed, and I have a computer with Windows 10 installed.I wrote two functions one send a file and the other one receive the file.
when I run this function that sends a file on the raspberry pi 4:
public static void sendFile(String fileName, String ip)
{
BufferedOutputStream outputStream = null;
PrintWriter writer = null;
BufferedReader reader = null;
FileInputStream filein = null;
File file = new File(fileName);
if (!file.exists())
{
System.out.println(fileName + " does not exist");
return;
}
try
{
Socket socket = new Socket(ip, port);
outputStream = new BufferedOutputStream(socket.getOutputStream());
writer = new PrintWriter(socket.getOutputStream());
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
filein = new FileInputStream(file);
long fileSize = file.length();
writer.println(fileName); // sending file name
writer.println(fileSize); // sending file size in bytes
writer.flush();
byte[] dataBuffer = new byte[1024];
int numberOfReadBytes = 0; // the number of read bytes for each read() function call
System.out.println("Entering the loop");
for(long i = 0; i < fileSize && numberOfReadBytes > -1;)
{
numberOfReadBytes = filein.read(dataBuffer); // read read() function returns the number of bytes tha has been assigned to the array or -1 if EOF(end of file) is reached
outputStream.write(dataBuffer, 0, numberOfReadBytes); // writing the bytes in dataBuffer from index 0 to index numberOfBytes
i += numberOfReadBytes;
}
outputStream.flush();
System.out.println(fileName + " sent to " + ip);
String status = reader.readLine();
System.out.println("Status: " + status + "\t file save successfully on the other machine.");
}
catch(IOException ioe)
{
System.err.println("Status: 0\n" + ioe.getMessage());
}
finally // closing streams
{
try
{
outputStream.close();
reader.close();
writer.close();
filein.close();
}
catch (IOException ioe)
{
System.err.println("Error closing the connection.");
}
}
}
it stops at this line Socket socket = new Socket(ip, port);
and this is the other function that runs on windows 10
public static void receiveFile()
{
// 1- read the file name
// 2- read the size of the file
// 3- read the file and write it
ServerSocket server = null;
Socket socket = null;
BufferedReader reader = null;
BufferedInputStream inputStream = null;
FileOutputStream fileout = null;
PrintWriter writer = null;
try
{
server = new ServerSocket(9999);
socket = server.accept();
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
inputStream = new BufferedInputStream(socket.getInputStream());
writer = new PrintWriter(socket.getOutputStream());
String fileName = reader.readLine(); // reading file name
long fileSize = Long.parseLong(reader.readLine()); // reading file size
System.out.println(fileSize);
// reading file data and write the data
File file = new File(fileName);
fileout = new FileOutputStream(file);
for (long i = 0; i < fileSize; ++i)
{
fileout.write(inputStream.read());
System.out.println(i);
}
fileout.flush();
fileout.close();
writer.println('1');
System.out.println("Status: 1");
System.out.println(fileName+ " is saved successfully");
}
catch (IOException ioe)
{
System.err.println("Status: 0");
System.err.println(ioe.getMessage());
}
finally
{
try
{
reader.close();
inputStream.close();
}
catch(IOException ioe)
{
System.err.println("Error closing connection\n" + ioe.getMessage());
}
}
}
I think windows 10 firewall blocks connection, but I am not sure.
It turns out it was the firewall blocking connection from the raspberry pi
I am writing tcp client-server program. When the client types "Hello" the server returns a list of files and directories of his current directory. When the client types "FileDownload " it downloads the selected file from the server.
When I type "Hello" it works fine, but when I type "FileDownload ", on the server side it runs twice the else if(received.contains("FileDownload")) block. Because of this the server is sending twice the data which is causing other issues on the client side.
Here is the server code:
public static void main(String[] args) throws IOException {
ServerSocket servSock = new ServerSocket(1333);
String received="";
String[] s = null;
File[] f1;
int i=0;
File f=new File(System.getProperty("user.dir"));
f1=f.listFiles();
for(File f2:f1) {
if(f2.isDirectory())
System.out.println(f2.getName() + "\t<DIR>\t" + i);
if(f2.isFile())
System.out.println(f2.getName() + "\t<FILE>\t" + i);
i++;
}
while (true) {
Socket client = servSock.accept();
InputStream in = client.getInputStream();
OutputStream out = client.getOutputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
PrintWriter pw = new PrintWriter(out, true);
s=f.list();
while(true) {
received = reader.readLine();
if(received.equals("END")) break;
if(received.equals("Hello")) {
System.out.println("Hello-Start");
int length=f1.length;
pw.println(length);
i=0;
for(File f2:f1) {
if(f2.isDirectory())
pw.println(f2.getName() + "\t<DIR>\t" + i);
if(f2.isFile())
pw.println(f2.getName() + "\t<FILE>\t" + i);
i++;
}
pw.println("Options: " + "\tFileDownload <FID>" + "\tFileUpload <name>" + "\tChangeFolder <name>");
System.out.println("Hello-End");
}
else if(received.contains("FileDownload")) {
System.out.println("FileDownload-Start");
int j=-1;
try {
j=Integer.parseInt(received.substring(13).trim());
}catch(NumberFormatException e) {
System.err.println("error: " + e);
}
if(j>0 && j<s.length) {
FileInputStream fi=new FileInputStream(s[j]);
byte[] b=new byte[1024];
System.out.println("file: "+s[j]);
pw.println(s[j]);
fi.read(b,0,b.length);
out.write(b,0,b.length);
System.out.println("FileDownload-End");
}
}
Here is the client code:
public static void main(String[] args) throws IOException {
if ((args.length != 2))
throw new IllegalArgumentException("Parameter(s): <Server> <Port>");
Socket socket = new Socket(args[0], Integer.parseInt(args[1]));
Scanner sc = new Scanner(System.in);
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
PrintWriter pw = new PrintWriter(out, true);
while(true) {
String msg="", received="";
String length;
msg = sc.nextLine();
pw.println(msg);
if(msg.equals("END")) break;
if(poraka.equals("Hello")) {
System.out.println();
length = reader.readLine();
for(int i=0;i<Integer.parseInt(length);i++) {
received = reader.readLine();
System.out.println(received);
}
System.out.println("\n"+reader.readLine());
}
else if(msg.contains("FileDownload")) {
System.out.println("FileDownload-Start");
pw.println(msg);
byte[] b=new byte[1024];
File file=new File(reader.readLine().trim());
System.out.println(file.getName().trim());
FileOutputStream fo=new FileOutputStream("D:\\Eclipse WorkSpace\\proekt\\src\\client\\"+file.getName().trim());
System.out.println("file: "+file.getName().trim());
in.read(b,0,b.length);
fo.write(b,0,b.length);
System.out.println("FileDownload-End");
}
I could not find what's causing this issue, so any help possible would be very highly appreciated!
It is because your client requests the data twice:
msg = sc.nextLine();
pw.println(msg); // <-- this is the first time
and then later
else if(msg.contains("FileDownload")) {
System.out.println("FileDownload-Start");
pw.println(msg); // <-- this is the second time
I'm writing a java-c client-server, where the server is in C and the client is in Java. The socket is reused. I don't know why but the client reads the first response from the socket then loops, it's like the client isn't getting "\n". What am I not getting?
The C server sends the response in the format (length:stringlength:string) etc
import java.io.*;
import java.net.*;
public class client {
public static void main(String[] args) {
if (args.length != 2) {
System.err.println("Use: java Client server port");
System.exit(1);
}
try{
BufferedReader fromUser = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Insert input1: ");
String input1 = fromUser.readLine();
System.out.println("Insert input2: ");
String input2 = fromUser.readLine();
Socket s = new Socket(args[0], Integer.parseInt(args[1]));
//BufferedReader fromServer = new BufferedReader(new InputStreamReader(s.getInputStream(),"UTF-8"));
InputStream is = s.getInputStream();
BufferedWriter toServer = new BufferedWriter(new OutputStreamWriter(s.getOutputStream(),"UTF-8"));
do {
String message = "(" + input1.getBytes("UTF-8").length + ":" + input1 + input2.getBytes("UTF-8").length + ":" + input2 + ")";
toServer.write(message);
toServer.flush();
/*reading result from server*/
//String buff;
String output = "";
byte[] buffer = new byte[4096];
int read;
while((read = is.read(buffer)) != -1) {
output = new String(buffer, 0, read);
System.out.print(output);
System.out.flush();
};
if(output.charAt(0) != '(' || output.charAt(output.length()-1) != ')'){
System.out.println("error using protocol");
}
if(output.indexOf(':')<0){
System.err.println("error using Canonical S-expression!");
System.exit(2);
}
for(int i=output.indexOf(":")+1;i<output.length()-2;i++){
System.out.print(output.charAt(i));
}
System.out.println();
s.close();
System.out.println("Insert input1: ('end' to exit)");
input1 = fromUser.readLine();
} while(!input1.equals("end"));
}
catch(IOException e){
System.err.println(e.getMessage());
e.printStackTrace();
System.exit(100);
}
}
}
This question already has answers here:
Java multiple file transfer over socket
(3 answers)
Closed 5 years ago.
TL;DR: How do I send (with a single connection) file, its size and its name. All examples in the internet send a file alone.
Server:
public class Server {
private static int PORT = 6667;
private ServerSocket serverSocket;
public void run() throws IOException {
System.out.println("Opening server");
serverSocket = new ServerSocket(PORT);
while(true) {
try(Socket incomingSocket = serverSocket.accept()) {
System.out.println("Accepted connection: " + incomingSocket);
incomingSocket.setSoTimeout(2000); // Don't let scanner block the thread.
InputStream inputStream = incomingSocket.getInputStream();
Scanner scanner = new Scanner(inputStream);
String command = "";
if(scanner.hasNextLine())
command = scanner.nextLine();
if(command.equals("update")) {
File file = new File("abc.txt");
sendFile(incomingSocket, file);
}
else {
// ...
System.out.println("Another command");
}
}
}
}
private void sendFile(Socket socket, File file) throws IOException {
byte[] bytes = new byte[(int)file.length()];
FileInputStream fileInputStream = new FileInputStream(file);
BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
bufferedInputStream.read(bytes, 0, bytes.length);
OutputStream outputStream = socket.getOutputStream();
PrintWriter writer = new PrintWriter(outputStream, true);
writer.println(file.length());
writer.println(file.getName());
System.out.println("Sending " + file.getName() + "(" + bytes.length + " bytes) to " + socket);
outputStream.write(bytes, 0, bytes.length);
outputStream.flush();
System.out.println("File sent");
}
public void stopRunning() {
try {
serverSocket.close();
} catch(IOException e) {
e.printStackTrace();
}
}
}
Client:
public class Client {
private static String HOST = "localhost";
private static int PORT = 6667;
public void run() throws IOException {
Socket socket = new Socket(HOST, PORT);
System.out.println("Connecting...");
OutputStream outputStream = socket.getOutputStream();
PrintWriter writer = new PrintWriter(outputStream, true);
writer.println("update"); // Example command which will determine what server sends back
receiveFile(socket);
socket.close();
}
private void receiveFile(Socket socket) throws IOException {
InputStream inputStream = socket.getInputStream();
int size = 16384;
String name = "example.txt";
Scanner scanner = new Scanner(inputStream);
size = Integer.parseInt(scanner.next());
name = scanner.next();
FileOutputStream fileOutputStream = new FileOutputStream(name);
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
byte[] buffer = new byte[size];
int bytesRead, totalRead = 0;
while ((bytesRead = inputStream.read(buffer, 0, buffer.length)) != -1) {
totalRead += bytesRead;
bufferedOutputStream.write(buffer, 0, bytesRead);
}
bufferedOutputStream.flush();
System.out.println("File " + name + " received. " + totalRead + " bytes read");
bufferedOutputStream.close();
fileOutputStream.close();
}
I want my server to send a file to the client. It should also include the file's name and its size. Name because it's quite important and the size because I don't want to make a hardcoded buffer with a huge size.
Tried it with the code above. The client's "scanner part"
Scanner scanner = new Scanner(inputStream);
size = Integer.parseInt(scanner.next());
name = scanner.next();
works just okay, but the file is not received. inputStream.read(buffer, 0, buffer.length) never reads the remaining bytes from the stream.
If i comment out the scanner part, the bytes are read correctly(size and name information + file itself)
So, the question is, how do I send it with a single connection? Or should I make 2 separate connections, in the first one asking for size and file name and sending the file in the second one?
Scanner is good for text-based work.
One way to do what you want is using DataInputStream and DataOutputStream. Only one connection is needed:
public void send(File file, OutputStream os) throws IOException {
DataOutputStream dos = new DataOutputStream(os);
// writing name
dos.writeUTF(file.getName());
// writing length
dos.writeLong(file.length());
// writing file content
... your write loop, write to dos
dos.flush();
}
public void receive(InputStream is) throws IOException {
DataInputStream dis = new DataInputStream(is);
String fileName = dis.readUTF();
long fileSize = dis.readLong();
// reading file content
... your read loop, read from dis
}
I have a server which uses the Sender class and a client which uses the Downloader class below. When the client connects to the server, it downloads the database.db and the default.docx perfectly, but when It starts to read the .png files, It throws this error:
java.io.IOException: Stream closed
at java.io.BufferedInputStream.getBufIfOpen(BufferedInputStream.java:145)
at java.io.BufferedInputStream.read(BufferedInputStream.java:308)
at java.io.DataInputStream.readFully(DataInputStream.java:178)
at java.io.DataInputStream.readLong(DataInputStream.java:399)
at data.Downloader.<init>(Downloader.java:18)
at data.Connection.<init>(Connection.java:18)
at main(Client.java:17)
Here are my only two methods:
Downloader:
public Downloader(Socket socket) {
try {
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
DataInputStream dis = new DataInputStream(bis);
int filesCount = dis.readInt();
for (int i = 0; i < filesCount; i++) {
long size = dis.readLong();
String fileName = dis.readUTF();
System.out.println(fileName);
if (fileName.equals("database.db")) {
List<String> data = new ArrayList<String>();
BufferedReader reader = new BufferedReader(new InputStreamReader(bis));
String line;
while ((line = reader.readLine()) != null) {
if (line.trim().length() > 0) {
data.add(line);
}
}
reader.close();
parse(data);
} else if (fileName.equals("default.docx")) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
for (int x = 0; x < size; x++) {
bos.write(bis.read());
}
bos.close();
document = bos.toByteArray();
} else if (fileName.contains(".png")) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
for (int x = 0; x < size; x++) {
bos.write(bis.read());
}
bos.close();
Signatures.signatures.add(bos.toByteArray());
}
}
dis.close();
} catch (Exception e) {
e.printStackTrace();
}
}
Sender:
public Sender(Socket socket) {
List<File> files = new ArrayList<File>();
files.add(new File(Directory.getDataPath("default.docx")));
files.add(new File(Directory.getDataPath("database.db")));
for (String signature : Directory.getSignaturePaths()) {
files.add(new File(signature));
}
try {
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
DataOutputStream dos = new DataOutputStream(bos);
dos.writeInt(files.size());
for (File file : files) {
System.out.println(file.getName() + file.length());
dos.writeLong(file.length());
dos.writeUTF(file.getName());
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
int theByte = 0;
while ((theByte = bis.read()) != -1) {
bos.write(theByte);
}
bis.close();
}
dos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
Also, I checked the getSignaturePaths() method and It returns the correct paths and the .png files are there.
You closed the stream and then kept using the socket. Closing either the input stream or the output stream of a socket closes the other stream and the socket.