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.
Related
i am trying to transfer large file over java socket transfer happen sucessfully but the file recieved miss some data or some bytes in my opinion. (completely new to the sockets)
Server Side Code
try {
File img = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/abc.mkv");
byte[] mybytearr = new byte[8192];
FileInputStream fis = new FileInputStream(img);
BufferedInputStream bis = new BufferedInputStream(fis);
DataInputStream dis = new DataInputStream(bis);
long len = fis.read();
DataOutputStream dos = new DataOutputStream(outputStream);
int read;
while ((read = dis.read(mybytearr)) != -1) {
dos.write(mybytearr, 0, read);
}
} catch (IOException e) {
e.printStackTrace();
}
Client Side Code
try {
if (inputStream.available() != 0) {
int bytesRead;
int bufferSize = 0;
bufferSize = socket.getReceiveBufferSize();
DataInputStream dis = new DataInputStream(inputStream);
String name = dis.readUTF();
File db = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "abc.mkv");
FileOutputStream output = new FileOutputStream(db);
byte[] buffer = new byte[bufferSize];
int read;
while((read = dis.read(buffer)) !=-1) {
output.write(buffer,0,read);
}
}
} catch (IOException e) {
e.printStackTrace();
}
I have written code for one file content copy to another file. but i didn't able to copy second file content to third file .
for that i written following code :
try {
File infile = new File("d:\\vijay.txt");
File outfile = new File("d:\\ajay.txt");
FileInputStream instream = new FileInputStream(infile);
FileOutputStream outstream = new FileOutputStream(outfile);
byte[] buffer = new byte[1024];
int length;
while ((length = instream.read(buffer)) > 0) {
outstream.write(buffer, 0, length);
}
instream.close();
outstream.close();
System.out.println("File Copied successfully");
} catch (IOException ioe) {
ioe.printStackTrace();
}
Please help me ,Thanks in advance.
If you have Java 7, I would suggest you use the Files utils. For example:
Path source1 = Paths.get("src1.txt");
Path source2 = Paths.get("src2.txt");
Path destination = Paths.get("dest.txt");
out = Files.newOutputStream(destination, CREATE, APPEND);
Files.copy(source1, destination, StandardCopyOption.REPLACE_EXISTING);
Files.copy(source2, destination);
Do it as below:
try {
// the files to be copied
String[] filePaths = {"file1.txt", "file2.txt"};
// out file
File outfile = new File("d:\\ajay.txt");
FileOutputStream outstream = new FileOutputStream(outfile);
// loop to all files copied
for (String filePath : filePaths) {
FileInputStream instream = new FileInputStream(new File(filePath));
byte[] buffer = new byte[1024];
int length;
while ((length = instream.read(buffer)) > 0) {
outstream.write(buffer, 0, length);
}
// close each file on copy finished
instream.close();
}
// at the end close the output stream
outstream.close();
System.out.println("File Copied successfully");
} catch (IOException ioe) {
ioe.printStackTrace();
}
Now you can copy n files to one file.
You can try this:
try {
File infile = new File("/home/bobo/test/a.txt");
File infile1 = new File("/home/bobo/test/b.txt");
//The third file
File outfile = new File("/home/bobo/test/c.txt");
FileInputStream instream = new FileInputStream(infile);
FileInputStream instream1 = new FileInputStream(infile1);
FileOutputStream outstream = new FileOutputStream(outfile);
byte[] buffer = new byte[1024];
int length;
while ((length = instream.read(buffer)) > 0) {
outstream.write(buffer, 0, length);
}
while ((length = instream1.read(buffer)) > 0) {
outstream.write(buffer, 0, length);
}
instream.close();
instream1.close();
outstream.close();
System.out.println("File Copied successfully");
} catch (IOException ioe) {
ioe.printStackTrace();
}
just give it a try
public class Filescombining
{
public static void main(String[] args) throws IOException
{
ArrayList<String> list = new ArrayList<String>();
try
{
BufferedReader br = new BufferedReader(new FileReader( "input1.txt"));
BufferedReader r = new BufferedReader(new FileReader( "input2.txt"));
String s1 =null;
String s2 = null;
while ((s1 = br.readLine()) != null)
{
list.add(s1);
}
while((s2 = r.readLine()) != null)
{
list.add(s2);
}
}
catch (IOException e)
{
e.printStackTrace();
}
BufferedWriter writer=null;
writer = new BufferedWriter(new FileWriter("output.txt"));
String listWord;
for (int i = 0; i< list.size(); i++)
{
listWord = list.get(i);
writer.write(listWord);
writer.write("\n");
}
System.out.println("completed");
writer.close();
}
}
hope my help works happy coding
I have been writing an updater for my game.
It checks a .version file on drop box and compares it to the local .version file.
If there is any link missing from the local version of the file, it downloads the required link one by one.
This is the error that it shows
Exception in thread "Thread-9" java.lang.OutOfMemoryError: Java heap space
at com.fox.listeners.ButtonListener.readFile(ButtonListener.java:209)
at com.fox.listeners.ButtonListener.readFile(ButtonListener.java:204)
at com.fox.listeners.ButtonListener.UpdateStart(ButtonListener.java:132)
at com.fox.listeners.ButtonListener$1.run(ButtonListener.java:58)
It only shows for some computers though and not all of them this is the readFile method
private byte[] readFile(URL u) throws IOException {
return readFile(u, getFileSize(u));
}
private static byte[] readFile(URL u, int size) throws IOException {
byte[] data = new byte[size];
int index = 0, read = 0;
try {
HttpURLConnection conn = null;
conn = (HttpURLConnection) u.openConnection();
conn.addRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)");
InputStream is = conn.getInputStream();
progress_a = 0;
progress_b = data.length;
while(index < data.length) {
read = is.read(data, index, size-index);
index += read;
progress_a = index;
}
} catch(Exception e) {
e.printStackTrace();
}
return data;
}
private byte[] readFile(File f) {
byte[] data = null;
try {
data = new byte[(int)f.length()];
#SuppressWarnings("resource")
DataInputStream dis = new DataInputStream(new FileInputStream(f));
dis.readFully(data);
} catch (IOException e) {
e.printStackTrace();
}
return data;
}
This is the main method that is ran
public void UpdateStart() {
System.out.println("Starting Updater..");
if(new File(cache_dir).exists() == false) {
System.out.print("Creating cache dir.. ");
while(new File(cache_dir).mkdir() == false);
System.out.println("Done");
}
try {
version_live = new Version(new URL(version_file_live));
} catch(MalformedURLException e) {
e.printStackTrace();
}
version_local = new Version(new File(version_file_local));
Version updates = version_live.differences(version_local);
System.out.println("Updated");
int i = 1;
try {
byte[] b = null, data = null;
FileOutputStream fos = null;
BufferedWriter bw = null;
for(String s : updates.files) {
if(s.equals(""))
continue;
System.out.println("Reading file "+s);
AppFrame.pbar.setString("Downloading file "+ i + " of "+updates.files.size());
if(progress_b > 0) {
s = s + " " +(progress_a * 1000L / progress_b / 10.0)+"%";
}
b = readFile(new URL(s));
progress_a = 0;
progress_b = b.length;
AppFrame.pbar.setString("Unzipping file "+ i++ +" of "+updates.files.size());
ZipInputStream zipStream = new ZipInputStream(new ByteArrayInputStream(b));
File f = null, parent = null;
ZipEntry entry = null;
int read = 0, entry_read = 0;
long entry_size = 0;
progress_b = 0;
while((entry = zipStream.getNextEntry()) != null)
progress_b += entry.getSize();
zipStream = new ZipInputStream(new ByteArrayInputStream(b));
while((entry = zipStream.getNextEntry()) != null) {
f = new File(cache_dir+entry.getName());
if(entry.isDirectory())
continue;
System.out.println("Making file "+f.toString());
parent = f.getParentFile();
if(parent != null && !parent.exists()) {
System.out.println("Trying to create directory "+parent.getAbsolutePath());
while(parent.mkdirs() == false);
}
entry_read = 0;
entry_size = entry.getSize();
data = new byte[1024];
fos = new FileOutputStream(f);
while(entry_read < entry_size) {
read = zipStream.read(data, 0, (int)Math.min(1024, entry_size-entry_read));
entry_read += read;
progress_a += read;
fos.write(data, 0, read);
}
fos.close();
}
bw = new BufferedWriter(new FileWriter(new File(version_file_local), true));
bw.write(s);
bw.newLine();
bw.close();
}
} catch(Exception e) {
e.printStackTrace();
return;
}
System.out.println(version_live);
System.out.println(version_local);
System.out.println(updates);
CacheUpdated = true;
if(CacheUpdated) {
AppFrame.pbar.setString("All Files are downloaded click Launch to play!");
}
}
I don't get why it is working for some of my players and then some of my other players it does not i have been trying to fix this all day and i am just so stumped at this point but this seems like its the only big issue left for me to fix.
Either increase the memory allocated to your JVM (How can I increase the JVM memory?), or make sure that the file being loaded in memory isn't gigantic (if it is, you'll need to find an alternate solution, or just read chunks of it at a time instead of loading the entire thing in memory).
Do your update in several steps. Here's some pseudo-code with Java 8. It's way shorter than what you wrote because Java has a lot of built-in tools that you re-write much less efficiently.
// Download
Path zipDestination = Paths.get(...);
try (InputStream in = source.openStream()) {
Files.copy(in, zipDestination);
}
// Unzip
try (ZipFile zipFile = new ZipFile(zipDestination.toFile())) {
for (ZipEntry e: Collections.list(zipFile.entries())) {
Path entryDestination = Paths.get(...);
Files.copy(zipFile.getInputStream(e), entryDestination);
}
}
// Done.
I am trying to transfer a large file from a server to a client. My code so far works but only if I set the buffer size in the client code to the exact size of the file. I won't always know what the file size is going to be. I keep finding examples that claim it doesn't matter what the size of the file or buffer is because it will just keep reading from the input stream...? However, when I implement the code that supposedly does this, it transfers 0 bytes.
Client:
public static void main (String [] args ) throws IOException {
int bytesRead;
int current = 0;
FileOutputStream fos = null;
BufferedOutputStream bos = null;
Socket sock = null;
try {
sock = new Socket(hostname, 20000);
System.out.println("Connecting...");
// receive file
InputStream is = sock.getInputStream();
fos = new FileOutputStream(FILE_TO_RECEIVE);
bos = new BufferedOutputStream(fos);
//////////// replaced this ////////////////////////////
byte[] buffer = new byte[BUFFER_SIZE];
bytesRead = is.read(buffer,0,buffer.length);
current = bytesRead;
do {
bytesRead = is.read(buffer, current, (buffer.length-current));
if(bytesRead >= 0){ current += bytesRead;}
} while(bytesRead > 0);
bos.write(buffer, 0 , current);
///////////////////////////////////////
// with this:
// int count;
// byte[] buffer = new byte[8192];
// while ((count = is.read(buffer)) > 0)
// {
// bos.write(buffer, 0, count);
// }
//////////// transfers 0 bytes ///////////
bos.flush();
System.out.println("File " + FILE_TO_RECEIVE
+ " downloaded (" + current + " bytes read)");
}
finally {
if (fos != null){ fos.close();}
if (bos != null){ bos.close();}
if (sock != null){ sock.close();}
}
}
Server:
public static void main(String[] args) throws IOException{
FileInputStream fis = null;
BufferedInputStream bis = null;
OutputStream os = null;
ServerSocket servsock = null;
Socket sock = null;
try {
servsock = new ServerSocket(20000);
while (true) {
System.out.println("Waiting...");
try {
sock = servsock.accept();
System.out.println("Accepted connection : " + sock);
// send file
File myFile = new File (FILE_TO_SEND);
byte [] mybytearray = new byte [(int)myFile.length()];
fis = new FileInputStream(myFile);
bis = new BufferedInputStream(fis);
bis.read(mybytearray,0,mybytearray.length);
os = sock.getOutputStream();
System.out.println("Sending " + FILE_TO_SEND + "(" + mybytearray.length + " bytes)");
os.write(mybytearray,0,mybytearray.length);
os.flush();
System.out.println("Done.");
}
finally {
if (bis != null){ bis.close();}
if (os != null){ os.close();}
if (sock!=null){ sock.close();}
}
}
}
finally {
if (servsock != null){
servsock.close();
}
}
}
Thank you for your help
Your copy loops are both different, and both nonsense. One of them isn't even a loop. Try this:
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
This works for any buffer of size >= one byte.
Use this at both ends.
I am trying to send a file from one computer to another using Java. I have written the code below, it works fine if both sender and receiver are started in the same computer but if they work on different machines received file size is bigger than the original file and it is corrupted.
Note: I am trying to transfer files which are max 10 MBs.
How can I fix this?
Sender:
ServerSocket server_socket = new ServerSocket(8989);
File myFile = new File(myPath);
Socket socket = server_socket.accept();
int count;
byte[] buffer = new byte[1024];
OutputStream out = socket.getOutputStream();
BufferedInputStream in = new BufferedInputStream(new FileInputStream(myFile));
while ((count = in.read(buffer)) > 0) {
out.write(buffer, 0, count);
out.flush();
}
socket.close();
Receiver:
Socket socket = new Socket(address, 8989);
FileOutputStream fos = new FileOutputStream(anotherPath);
BufferedOutputStream out = new BufferedOutputStream(fos);
byte[] buffer = new byte[1024];
int count;
InputStream in = socket.getInputStream();
while((count=in.read(buffer)) >0){
fos.write(buffer);
}
fos.close();
socket.close();
On the client side you write up to count bytes and send them:
while ((count = in.read(buffer)) > 0) {
out.write(buffer, 0, count);
on the server side you read up to count bytes - but then you write the whole buffer to file!
while((count=in.read(buffer)) > 0){
fos.write(buffer);
Just change it to:
fos.write(buffer, 0, count);
and you'll be on the safe side. BTW your program has another small bug: read() can return 0 which doesn't mean InputStream ended. Use >= instead:
count = in.read(buffer)) >= 0
Have you considered IOUtils.copy(InputStream, OutputStream) from Apache Commons? It would reduce your whole while loops to:
OutputStream out = socket.getOutputStream();
InputStream in = new FileInputStream(myFile);
IOUtils.copy(in, out);
socket.close();
Less code to write, less code to test. And buffering is done internally.
Remember that in.read(buffer) not necessarily fills up the whole buffer with new data. Therefore you should make sure you don't write the whole buffer. Change
while((count=in.read(buffer)) >0){
fos.write(buffer);
}
to
while((count=in.read(buffer)) >0){
fos.write(buffer, 0, count);
}
sender
Socket sock = new Socket("127.0.0.1", 5991);
System.out.println("Connecting.........");
File myFile = new File("/root/qrcode/");
File[] files = myFile.listFiles();
OutputStream os = sock.getOutputStream();
BufferedOutputStream bos = new BufferedOutputStream(os);
DataOutputStream dos = new DataOutputStream(bos);
dos.writeInt(files.length);
long totalBytesRead = 0;
int percentCompleted = 0;
for(File file : files)
{
long length = file.length();
dos.writeLong(length);
String name = file.getName();
dos.writeUTF(name);
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
int theByte = 0;
while((theByte = bis.read()) != -1)
{
totalBytesRead += theByte;
bos.write(theByte);
}
// System.out.println("file read");
bis.close();
}
dos.close();
//Closing socket
sock.close();
receiver
ServerSocket serverSocket = new ServerSocket(5991);
while(true) {
Socket clientSocket = null;
System.out.println("Starting...");
clientSocket = serverSocket.accept();
InputStream in = clientSocket.getInputStream(); //used
BufferedInputStream bis = new BufferedInputStream(in);
String dirPath ;
dirPath = "/root/NewFolder";
try{
DataInputStream dis = new DataInputStream(bis);
int filesCount = dis.readInt();
File[] files = new File[filesCount];
long f_l = 0;
int count =0 ;
long totalBytesRead = 0;
int percentCompleted = 0;
for(int i = 0; i < filesCount; i++)
{
long fileLength = dis.readLong();
String fileName = dis.readUTF();
f_l = f_l +fileLength;
files[i] = new File(dirPath + "/" + fileName);
FileOutputStream fos = new FileOutputStream(files[i]);
BufferedOutputStream bos = new BufferedOutputStream(fos);
int tot = 0;
for(int j = 0; j < fileLength; j++) {
bos.write(bis.read());
}
bos.close();
}
}catch(Exception ex)
{
System.out.println("error in socket programming ");
}
}