I have a program that updates files on the computer using information sent by a server, using sockets. The way I had it worked, but i wanted to make it more intuitive, simpler, more reliable, etc. here is the previous code:
int filesize = 6022386; // filesize temporary hardcoded
int bytesRead;
int current = 0;
/**
* receive file
*/
try {
byte[] byteArray = new byte[filesize];
java.io.InputStream inStream = socket.getInputStream();
bytesRead = inStream.read(byteArray, 0, byteArray.length);
FileOutputStream fileOutStream = new FileOutputStream(
"C:\\Program Files\\AVTECH\\NPS\\Files\\bin\\NPS Game.txt");
BufferedOutputStream buffOutStream = new BufferedOutputStream(
fileOutStream);
current = bytesRead;
do {
bytesRead = inStream.read(byteArray, current,
(byteArray.length - current));
if (bytesRead >= 0)
current += bytesRead;
} while (bytesRead > -1);
buffOutStream.write(byteArray, 0, current);
buffOutStream.flush();
buffOutStream.close();
inStream.close();
socket.close();
} catch (Exception e) {
e.printStackTrace();
socket.close();
}
as you can see, in the do, while loop, it is using the input stream to get the data. now that i've updated my program, i have the stream sending an object called UpdateObject, which holds the byte[] array along with the file directory. here is that code:
int filesize = 6022386; // filesize temporary hardcoded
int bytesRead;
int current = 0;
try {
byte[] byteArray = o.getFile();
java.io.InputStream inStream = socket.getInputStream();
bytesRead = inStream.read(byteArray, 0, byteArray.length);
FileOutputStream fileOutStream = new FileOutputStream(o.getPath());
BufferedOutputStream buffOutStream = new BufferedOutputStream(
fileOutStream);
current = bytesRead;
do {
bytesRead = inStream.read(byteArray, current,
(byteArray.length - current));
if (bytesRead >= 0)
current += bytesRead;
} while (bytesRead > -1);
buffOutStream.write(byteArray, 0, current);
buffOutStream.flush();
buffOutStream.close();
inStream.close();
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
now my question is this: how do i change it so instead of using the instream, to use just a byte[] object in the UpdateObject sent over the socket? i've done some google searching, but i dont feel like i know the right question to ask. any help would be great! thanks in advance!!!
By replacing most of your code inside the try catch block with:
FileOutputStream fileOutStream = new FileOutputStream(
UpdateObject.getDirectory()+"\\NPS Game.txt");
fileOutStream.write(UpdateObject.getBytes()); //this is the byte[] array
fileOutStream.close();
Hope this helps.
Related
I am working on reading a file and write same file, but the problem is the downloaded file is 2kb larger than input original file.
Some piece of code
#Override
public void run() {
try {
BufferedInputStream bis;
ArrayList<byte[]> al =new ArrayList<byte[]>();
File file = new File(Environment.getExternalStorageDirectory(), "test.mp3");
byte[] bytes = new byte[2048];
bis = new BufferedInputStream(new FileInputStream(file));
OutputStream os = socket.getOutputStream();
int read ;
int fileSize = (int) file.length();
int readlen=1024;
while (fileSize>0) {
if(fileSize<1024){
readlen=fileSize;
System.out.println("Hello.........");
}
bytes=new byte[readlen];
read = bis.read(bytes, 0, readlen);
fileSize-=read;
al.add(bytes);
}
ObjectOutputStream out1 = new ObjectOutputStream(new FileOutputStream(Environment.getExternalStorageDirectory()+"/newfile.mp3"));
for(int ii=1;ii<al.size();ii++){
out1.write(al.get(ii));
// out1.flush();
}
out1.close();
File file1 = new File(Environment.getExternalStorageDirectory(), "newfile.mp3");
Don't use an ObjectOutputStream. Just use the FileOutputStream, or a BufferedOutputStream wrapped around it.
The correct way to copy streams in Java is as follows:
byte[] buffer = new byte[8192]; // or more, or even less, anything > 0
int count;
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
out.close();
Note that you don't need a buffer the size of the input, and you don't need to read the entire input before writing any of the output.
Wish I had $1 for every time I've posted this.
I think you should use ByteArrayOutputStream not an ObjectOutputStream.
I belive this is not a raw code, but the parts of the code, placed in different procedures, otherwise it is meaningless.
For example, in case you want to stream some data from a file, process this data, and then write the data to another file.
BufferedInputStream bis = null;
ByteArrayOutputStream al = new ByteArrayOutputStream();
FileOutputStream out1 = null;
byte[] bytes;
try {
File file = new File("testfrom.mp3");
bis = new BufferedInputStream(new FileInputStream(file));
int fileSize = (int) file.length();
int readLen = 1024;
bytes = new byte[readLen];
while (fileSize > 0) {
if (fileSize < readLen) {
readLen = fileSize;
}
bis.read(bytes, 0, readLen);
al.write(bytes, 0, readLen);
fileSize -= readLen;
}
bis.close();
} catch (IOException e){
e.printStackTrace();
}
//proceed the data from al here
//...
//finish to proceed
try {
out1 = new FileOutputStream("testto.mp3");
al.writeTo(out1);
out1.close();
} catch (IOException e){
e.printStackTrace();
}
Don't forget to use try-catch directives where it needed
http://codeinventions.blogspot.ru/2014/08/creating-file-from-bytearrayoutputstrea.html
I was trying to flush data in a file in my local machine to response. But at some point I get an IndexOutOfBoundsException.
FileInputStream inputStream = new FileInputStream(downloadFile);
OutputStream outStream = response.getOutputStream();
byte[] buffer = new byte[4096];
int bytesRead = -1;
while ((bytesRead = inputStream.read(buffer, 0, 4096)) != -1) {
outStream.write(buffer, 0, bytesRead);
}
inputStream.close();
outStream.close();
The above code is what I was trying. The downloadFile path given is correct and it works till the while loop. But then the IndexOutOfBoundsException occurs. I tried it with inputStream.read(buffer) but that didn't work.
Give code is working perfectlly; since there is no information is given regarding the response object I have modify the OutputStream to FileOutputStream; just to test.
Below code segment is working perfectly.
public class Test
{
public static void main(String args[]) throws IOException
{
FileInputStream inputStream = new FileInputStream("C:\\readme.txt");
FileOutputStream outputStream = new FileOutputStream("D:\\readme1.txt");
//OutputStream outStream = response.getOutputStream();
byte[] buffer = new byte[4096];
int bytesRead = -1;
while ((bytesRead = inputStream.read(buffer, 0, 4096)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
inputStream.close();
outputStream.close();
}
}
I'm trying to build a file server and file client program in Java using sockets, and I've been running into some issues when trying to send files from the server to the client. Below is the code that I use to send and receive files respectively:
private void sendFile(String filePath) {
try (BufferedInputStream fileInputStream = new BufferedInputStream(new FileInputStream(filePath))) {
BufferedOutputStream outputStream = new BufferedOutputStream(socket.getOutputStream());
byte[] buffer = new byte[4096];
while (fileInputStream.read(buffer) != -1) {
outputStream.write(buffer);
outputStream.flush();
}
}
catch (IOException e) {e.printStackTrace();}
}
private void downloadFile(String fileName, long fileSize) {
try (BufferedOutputStream fileOutputStream = new BufferedOutputStream(new FileOutputStream(downloadDir + "/" + fileName));
BufferedInputStream inputStream = new BufferedInputStream(socket.getInputStream());
OutputStreamWriter writer = new OutputStreamWriter(new BufferedOutputStream(socket.getOutputStream()), "UTF-8");) {
writer.write("GET" + fileName + System.lineSeparator());
writer.flush();
long totalReceived = 0;
int bufferSize = 4096;
byte[] buffer = new byte[bufferSize];
while (totalReceived < fileSize) {
inputStream.read(buffer);
int numOfBytesToWrite = fileSize - totalReceived > bufferSize ? buffer.length : (int)(fileSize % bufferSize);
fileOutputStream.write(buffer, 0, numOfBytesToWrite);
fileOutputStream.flush();
totalReceived += numOfBytesToWrite;
}
}
catch (IOException e) {}
}
The downloaded file does get created and seems to be of the right size, but always gets corrupted and cannot be opened by any program. However, this issue does not show itself when I run the client on the same machine and connect it to "localhost" or "127.0.0.1", then there are no problems and downloaded files are not corrupted. See any issues with my code?
In your sendFile() you need to consider the return value from the read() which may be less than 4096... This value should then be used in the write call to only write out the portion of the array that has been populated...
int bytesRead = 0;
while ((bytesRead = fileInputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
outputStream.flush();
}
A similar problem occurs in downloadFile(), return from read() is the actual number of bytes read, some value less than or equal to 4096...
long totalReceived = 0;
int bufferSize = 4096;
byte[] buffer = new byte[bufferSize];
while (totalReceived < fileSize) {
int bytesRead = inputStream.read(buffer);
fileOutputStream.write(buffer, 0, bytesRead);
fileOutputStream.flush();
totalReceived += bytesRead;
}
Why does your code work on localhost, but not over a network?
Atypical physical layer of a network is Ethernet, this will have a MTU of 1500 bytes. So you'll probably be seeing successive read() calls only filling 1500, or fewer bytes of your buffer...
However, localhost is optimized in the stack to bypass the physical layer which will not have this limitation. It is likely in this case successive calls will fill the full 4096 buffer, apart from the last, unless your file size is exact multiple of 4096.
I am working on a Web Server, I am stuck on the HTTP method PUT ... I currently can only bet 10 bytes of data from the client when he tries to upload a file, bellow is what I have so far.
InputStream stream = connection.getInputStream();
OutputStream fos = Files.newOutputStream(path);
int count = 0;
while (count < 10) {
int b = stream.read();
if (b == -1) break;
fos.write(b);
++count;
}
fos.close();
Please tell me how I can get the as much input the client writes.
You limited it to 10 by your while loop using 10. Since stream.read() returns -1 at the end of the stream, use that in the while loop as the control:
int count = 0;
int b = 0;
while ((b=stream.read()) !=-1)
{
fos.write(b);
count++;
}
public void receiveFile(InputStream is){
//Set a really big filesize
int filesize = 6022386;
int bytesRead;
int current = 0;
byte[] mybytearray = new byte[filesize];
try(FileOutputStream fos = new FileOutputStream("fileReceived.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos)){
//Read till you get a -1 returned by is.read(....)
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);
bos.write(mybytearray, 0, current);
bos.flush();
bos.close();
}
catch (FileNotFoundException fnfe){
System.err.println("File not found.");
}
catch (SecurityException se){
System.err.println("A Security Issue Occurred.");
}
}
Based on this one: FTP client server model for file transfer in Java
i'm doing a server with Java and a client with Android. Everything works fine, but when i try to receive the file on Android, the IO input freezes. I tried to do the same with a Java test app, and works fine.
My code on the client side:
int bytesRead;
long current = 0;
byte [] mybytearray = new byte[InfoPrograma.BUFFER_LENGTH];
//Receive file
InputStream is = socket.getInputStream();
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(file)
);
while (
(bytesRead = is.read(
mybytearray,
0,
mybytearray.length
)
) >= 0) {
current += bytesRead;
bos.write(mybytearray, 0 , bytesRead);
}
bos.flush();
bos.close();
The server side code:
File file = new File(fileStr);
byte[] buffer = new byte[InfoPrograma.BUFFER_LENGTH];
BufferedInputStream bis = new BufferedInputStream(
new FileInputStream(file)
);
OutputStream os = socket.getOutputStream();
long tmp = 0;
while ((count = bis.read(buffer)) > 0) {
os.write(buffer, 0, count);
tmp += count;
System.out.println(tmp);
}
os.flush();
BUFFER_LENGHT is 2000. If you need anything else, ask for it, please.
Thank you.
Done it. The only way i found is to send first the lenght of the file to the client, save it, and then do read() while (on my code) current < fileLength.