Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I have write a code that transfer file in Java socket but I want to expand it. I want to select the file that I want. And I don't understand one line of code:
byte[] mybytearray = new byte[(int) myFile.length()];
Here's my real code:
import import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Main {
public static void main(String[] args) throws IOException {
ServerSocket servsock = new ServerSocket(123456);
File myFile = new File("s.pdf");
while (true) {
Socket sock = servsock.accept();
byte[] mybytearray = new byte[(int) myFile.length()];
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(myFile));
bis.read(mybytearray, 0, mybytearray.length);
OutputStream os = sock.getOutputStream();
os.write(mybytearray, 0, mybytearray.length);
os.flush();
sock.close();
}
}
}
The client module:
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.Socket;
public class Main {
public static void main(String[] argv) throws Exception {
Socket sock = new Socket("127.0.0.1", 123456);
byte[] mybytearray = new byte[1024];
InputStream is = sock.getInputStream();
FileOutputStream fos = new FileOutputStream("s.pdf");
BufferedOutputStream bos = new BufferedOutputStream(fos);
int bytesRead = is.read(mybytearray, 0, mybytearray.length);
bos.write(mybytearray, 0, bytesRead);
bos.close();
sock.close();
}
}
That line of code is attempting to make a byte array that has the same size as the file you are reading, allowing it to read the entire file into the byte array in a single read.
The second block of code 'assumes' that the file is no longer than 1024 bytes long, and reads that length maximum, no more. Do you know that the file is <= 1024 bytes long?
For a number of reasons, it is a bad idea to have a variable buffer size when dealing with streams. The beauty of streams is that you don't have the whole file in memory. Instead, use this pattern ... it is easy enough:
{
Socket sock = servsock.accept();
byte[] mybytearray = new byte[4096];
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(myFile));
OutputStream os = sock.getOutputStream();
int amt = bis.read(mybytearray, 0, 4096);
while (amt>0) {
os.write(mybytearray, 0, amt);
amt = bis.read(mybytearray, 0, 4096);
}
os.flush();
sock.close();
}
I chose 4096 as a random arbitrary size, but there is no real reason to choose any size bigger than this. This will copy a file of any size (even gigabytes), the entire file, and it will not cause an out of memory problem when the file gets big.
Have a look at The Java™ Tutorials, Trail: Learning the Java Language, Arrays.
In short: it creates an array for elements of type byte and with a size of the number of bytes in myFile. Since array creation expects an int value for the size and java.io.File offers long length() the returned long value ist cast to (int). Do a DDuckinG and look into the offered tutorials.
Related
This is a simplified version of my program.
I have a Server.java file where I read in "b.txt" into a byte array and then write it to the DataOutputStream.
import java.io.*;
import java.net.*;
class Server {
public static void main(String[] args) {
try {
ServerSocket ss = new ServerSocket(4000);
Socket s = ss.accept();
DataOutputStream dout = new DataOutputStream(s.getOutputStream());
byte[] byteArray = new byte[32];
File tempFile = new File("Files/b.txt");
FileInputStream fis = new
FileInputStream(tempFile);
fis.read(byteArray);
fis.close();
dout.write(byteArray);
dout.flush();
dout.close();
s.close();
} catch (Exception e) {
//handle exceptions
}
}
}
In Client.java I read the DataInputStream into a byteArray. Then, I create a FileOutputStream. In the commented out code fos.write(byteArray), this writes to the file, however since the actual file may not be exactly 32 bytes I am left with a corrupt file since the remaining bytes just get filled with random data (or whatever happens).
import java.io.*;
import java.net.*;
class Client {
public static void main(String[] args) {
try {
Socket s = new Socket("localhost", 4000);
DataInputStream din = new DataInputStream(s.getInputStream());
byte[] byteArray = new byte[32];
FileOutputStream fos = new FileOutputStream("Downloaded/testfile.txt");
//fos.write(byteArray);
int count;
while ((count = din.read(byteArray)) > 0) {
fos.write(byteArray, 0, count);
}
fos.close();
din.close();
s.close();
} catch (Exception e) {
//handle exceptions
}
}
}
So I looked up how to fix this and a lot of places told me to do the code I have inside the while loop: while ((count = din.read... etc.
However when I try this, testfile.txt is blank and contains 0 bytes. Am I missing something big here? I have tried sending in the correct amount of bytes from the server, however this doesn't change anything.
I would like to be able to transfer any file type, so it is important that I am able to transfer the correct amount of bytes without corrupting the data by having bytes "hanging over". Thank you.
I am trying to send pdf files over to clients using tcp connections. Somehow, the file is corrupted. I wonder if tcp support non-txt files?
this is a simple server program
import java.io.*;
import java.net.*;
class server{
public static void main (String args[]) throws Exception
{
Socket s = null;
int firsttime=1;
while(true) {
ServerSocket s_sock = new ServerSocket(3248);
Socket socket = s_sock.accept();
BufferedReader bf = new BufferedReader(new InputStreamReader(socket.getInputStream()));
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
File myFile = new File ("/Users/wchen48/Desktop/123.pdf");
byte [] mybyte = new byte[(int)myFile.length()];
OutputStream os = socket.getOutputStream();
System.out.println("sending......" + mybyte.length + "Byte");
os.write(mybyte,0,mybyte.length);
os.flush();
socket.close();
s_sock.close();
}
} //end of main
This is the client:
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.Socket;
public class client{
public static void main(String[] argv) throws Exception {
Socket sock = new Socket("127.0.0.1", 3248);
byte[] mybytearray = new byte[11536];
InputStream is = sock.getInputStream();
FileOutputStream fos = new
FileOutputStream("/Users/wchen48/Documents/123.pdf");
bos = new BufferedOutputStream(fos);
int bytesRead = is.read(mybytearray, 0, mybytearray.length);
bos.write(mybytearray, 0, mybytearray.length);
bos.close();
sock.close();
}
}
Thank you in advance.
What Zielu and Juned said, plus:
You need loops at both server and client.
At the server, choose a reasonable-size buffer and loop around. Try to read [buffer length] bytes into it from the file. Then USE THE RETURNED VALUE FROM THE READ CALL to both check for errors, (result<0), or end-of-file, (result 0), or use the value in the network write call as the number of bytes to write. DO NOT use the buffer length - it may not be full. When you get 0, close the file and socket, else loop back and read some more.
At the client, choose a reasonable-size buffer and loop around. Try to read [buffer length] bytes into it from the socket. Then USE THE RETURNED VALUE FROM THE READ CALL to both check for errors, (result<0), or socket close, (result 0), or use the value in the file write call as the number of bytes to write. DO NOT use the buffer length - it may not be full. When you get 0, exit the loop and close the file, else loop back and read some more.
you dont read content of your file into the buffer mybyte you later send through socket, so you send 00000....
The most likely reason for getting the corrupted file is the fixed number of bytes(11536) that you are trying to read. You should try to read all the bytes received on the socket rather than fixed number of bytes.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
since I dont know how to generate DataInputStream easily, I cant test but pose my questions here. I use Java1.7
I need to manipulate an arrived DataInputStream, skip some bytes, call readShort() several times and skip another bytes. and I wonder:
Q1 if we will lose the original DataInputStream after the skip
Q2 after I call readShort(), would the stream move and point to the next position or it stays at the same position
if you want to skip some bytes you can use
1.readByte() method of DataInputStream and create a for loop of n size to skip n bytes and after that
2.call readShort() method to read short values from the input stream
3.after that again call readByte() to skip again bytes.
feel free to ask your queries
I think I didnt get youre Question fully, but ill provide you 2 Examples, one for
readShort(), which reads two input bytes and returns a short value.
and the
skipBytes(int n) method, which skips over n bytes of data from the
input stream. After skipping you will not be able to read them again
Now you are able to test freely
readShort()
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
public class DataInputStreamDemo {
public static void main(String[] args) throws IOException {
InputStream is = null;
DataInputStream dis = null;
FileOutputStream fos = null;
DataOutputStream dos = null;
short[] s = {12982,3568};
try{
// create file output stream
fos = new FileOutputStream("c:\\test.txt");
// create data output stream
dos = new DataOutputStream(fos);
// for each short in short buffer
for(short j:s)
{
// write short to data output stream
dos.writeShort(j);
}
// force data to the underlying file output stream
dos.flush();
// create file input stream
is = new FileInputStream("c:\\test.txt");
// create new data input stream
dis = new DataInputStream(is);
// available stream to be read
while(dis.available()>0)
{
// read two bytes from data input, return short
short k = dis.readShort();
// print short value
System.out.print(k+" ");
}
}catch(Exception e){
// if any error occurs
e.printStackTrace();
}finally{
// releases all system resources from the streams
if(is!=null)
is.close();
if(dis!=null)
dis.close();
if(fos!=null)
fos.close();
if(dos!=null)
dos.close();
}
}
}
Output: 12982 3568
skipBytes()
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
public class DataInputStreamDemo {
public static void main(String[] args) throws IOException {
InputStream is = null;
DataInputStream dis = null;
FileOutputStream fos = null;
DataOutputStream dos = null;
byte[] b = {4,124,119,114,125,45,76,83,84};
try{
// create file output stream
fos = new FileOutputStream("c:\\test.txt");
// create data output stream
dos = new DataOutputStream(fos);
// for each byte in buffer
for(byte j:b)
{
// write byte to the output stream
dos.writeByte(j);
}
// force data to the underlying file output stream
dos.flush();
// create file input stream
is = new FileInputStream("c:\\test.txt");
// create new data input stream
dis = new DataInputStream(is);
// available stream to be read
while(dis.available()>0)
{
// reads characters encoded with modified UTF-8
int k = dis.read();
// print
System.out.print(k+" ");
// skips 1 by
dis.skipBytes(1);
}
}catch(Exception e){
// if any error occurs
e.printStackTrace();
}finally{
// releases all system resources from the streams
if(is!=null)
is.close();
if(dis!=null)
dis.close();
if(fos!=null)
fos.close();
if(dos!=null)
dos.close();
}
}
}
Output: 4 119 125 76 84
How can I do to transform from InputStream to FileItem in Java?
Thanks.
Here is a working example. Note that you must change the InputStream from the example with your InputStream, and also you might want to change the location of your work/tmp dir().
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItem;
public class TestFile {
public static void main(String args[]) throws IOException {
// This is a sample inputStream, use your own.
InputStream inputStream = new FileInputStream("c:\\Kit\\Apache\\geronimo-tomcat6-javaee5-2.1.6\\README.txt");
int availableBytes = inputStream.available();
// Write the inputStream to a FileItem
File outFile = new File("c:\\tmp\\newfile.xml"); // This is your tmp file, the code stores the file here in order to avoid storing it in memory
FileItem fileItem = new DiskFileItem("fileUpload", "plain/text", false, "sometext.txt", availableBytes, outFile); // You link FileItem to the tmp outFile
OutputStream outputStream = fileItem.getOutputStream(); // Last step is to get FileItem's output stream, and write your inputStream in it. This is the way to write to your FileItem.
int read = 0;
byte[] bytes = new byte[1024];
while ((read = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, read);
}
// Don't forget to release all the resources when you're done with them, or you may encounter memory/resource leaks.
inputStream.close();
outputStream.flush(); // This actually causes the bytes to be written.
outputStream.close();
// NOTE: You may also want to delete your outFile if you are done with it and dont want to take space on disk.
}
}
I am creating a file server application for school assignment. What I currently have is a simple Client class that sends an image through TCP and a Server class that receives it and writes it to the file.
this is my client code
import java.io.*;
import java.net.*;
class Client {
public static void main(String args[]) throws Exception {
long start = System.currentTimeMillis();
Socket clientSocket = new Socket("127.0.0.1", 6789);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
File file = new File("hot.jpg");
FileInputStream fin = new FileInputStream(file);
byte sendData[] = new byte[(int)file.length()];
fin.read(sendData);
outToServer.write(sendData, 0, sendData.length);
clientSocket.close();
long end = System.currentTimeMillis();
System.out.println("Took " + (end - start) + "ms");
}
}
and this is my server code.
import java.io.*;
import java.net.*;
class Server {
public static void main(String args[]) throws Exception {
ServerSocket serverSocket = new ServerSocket(6789);
Socket connectionSocket = serverSocket.accept();
DataInputStream dis = new DataInputStream(connectionSocket.getInputStream());
byte[] receivedData = new byte[61500]; // <- THIS NUMBER
for(int i = 0; i < receivedData.length; i++)
receivedData[i] = dis.readByte();
connectionSocket.close();
serverSocket.close();
FileOutputStream fos = new FileOutputStream("received.jpg");
fos.write(receivedData);
fos.close();
}
}
My question is how to get the size of the file that is being sent. If you check the Server code you'll see that I've hardcoded the number i.e. 61500 at the moment. How can I retrieve this number dynamically?
Or, am I doing this the wrong way? What an alternative solution would be?
Add one "length field" before sending the file. (Note that since you read the file to memory the maximum size of the file can be ~2GB.)
Before sending the file write the length of the file:
outToServer.writeInt(sendData.length);
And when receiving read the length first and use it as a length:
int dataLength = dis.readInt()
byte[] receivedData = new byte[dataLength];
A better way would be not to read the file into memory first but to transfer it directly from the FileInputStream - then you could transfer bigger files!
If you know the length, using readFully() is much more efficient than reading a byte at a time.
In this case, you don't need to know the length, you can write the loop to read/write as much data as you get.
InputStream is = connectionSocket.getInputStream();
byte[] bytes = new byte[8192];
int len;
while((len = is.read(bytes)) > 0)
fos.write(bytes, 0, len);
You can avoid reading the whole file into memory by copying the data as you read it.
FileInputStream fis = new FileInputStream(filename);
OutputStream os = socket.getOutputStream();
byte[] bytes = new byte[8192];
int len;
while((len = fis.read(bytes)) > 0)
os.write(bytes, 0, len);
You can use Apache IOUtils.copy() to perform the copy from one stream to another if you wish.
This approach has the advantage that the file can be any size (greater than 2 GB). Using an array is limited to 2 GB (and uses more memory)