How to save files over socket into list - java

I have a method that works perfectly, but instead of having it write to a file, how do I have it add each line of the file to a list? (Some files are .docx and some are .txt)
private static void saveMultiple(Socket socket) {
try {
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
DataInputStream dis = new DataInputStream(bis);
int filesCount = dis.readInt();
File[] files = new File[filesCount];
for (int i = 0; i < filesCount; i++) {
long fileLength = dis.readLong();
String fileName = dis.readUTF();
files[i] = new File("/Users/.../Desktop/Data/" + fileName);
FileOutputStream fos = new FileOutputStream(files[i]);
BufferedOutputStream bos = new BufferedOutputStream(fos);
for (int x = 0; x < fileLength; x++) {
bos.write(bis.read());
}
bos.close();
}
dis.close();
} catch (Exception e) {
e.printStackTrace();
}
}

This part of you code:
bos.write(bis.read());
Basically read 1 byte from the socket and writes it into file. Now instead of doing this, you can buffer the bytes into a byte array, and use java.util.String String(byte[] bytes) constructor to turn it into a String. Consider using ByteInputStream.read(byte[] b, int off, int len) method.
You have to take into account the character encoding and memory consumption too.

Related

Fast way to read file from input stream when we know the size with low memory usage

Is there any faster way to read from an inputstream when we know the size of the data?
This code that I have is very slow:
File file = new File("file.jar");
if(!file.exists)file.createNewFile();
String url = "https://launcher.mojang.com/v1/objects/3870888a6c3d349d3771a3e9d16c9bf5e076b908/client.jar";
int len = 8461484;
InputStream is = new URL(url).openStream();
if(!file.exists())
file.createNewFile();
PrintWriter writer = new PrintWriter(file);
for(long i = 0;i < len;i ++) {
writer.write(is.read());
writer.flush();
System.out.println(i);
}
writer.close();
Use Buffered Input & Output Streams together with try-with-resources
(which ensures the Streams are all closed at EOJ)
Something like this:
try(final InputStream ist = new URL(url).openStream ();
final InputStream bis = new BufferedInputStream (ist);
final OutputStream ost = new FileOutputStream(file);
final OutputStream bos = new BufferedOutputStream(ost))
{
final byte[] bytes = new byte[64_000]; // <- as large as possible!
/**/ int count;
while ((count = bis.read(bytes)) != -1) {
bos.write(bytes, 0, count);
}
}

I want to download all files from PC's folder from my android for this m doing java sockets but achieved 1st file correctly others are garbage

*i have have a folder in my pc in c:/ name share and in that i have 4 pictures after running my client and server code i got all 4 picture downloaded in my android emulator but only first image is correctly download other 3 are garbage
here is my code
SERVER SIDE
public class Multiplefilessending
{
public static void main(String[] args) throws IOException,EOFException
{
FileOutputStream fos;
BufferedOutputStream bos;
OutputStream output;
int len;
int smblen;
InputStream in;
boolean flag=true;
DataInputStream clientData;
BufferedInputStream clientBuff;
System.out.println("Waiting for Connection");
ServerSocket serverSocket = new ServerSocket(5991);
Socket clientSocket = null;
clientSocket = serverSocket.accept();
////////////////////////
File myFile = new File("C:/share");
File[] Files = myFile.listFiles();
OutputStream os = clientSocket.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
dos.writeInt(Files.length);
for (int count=0;count<Files.length;count ++)
{
dos.writeUTF(Files[count].getName());
}
for (int count=0;count<Files.length;count ++)
{
int filesize = (int) Files[count].length();
dos.writeInt(filesize);
}
for (int count=0;count<Files.length;count ++)
{
int filesize = (int) Files[count].length();
byte [] buffer = new byte [filesize];
//FileInputStream fis = new FileInputStream(myFile);
FileInputStream fis = new FileInputStream(Files[count].toString());
BufferedInputStream bis = new BufferedInputStream(fis);
//Sending file name and file size to the server
bis.read(buffer, 0, buffer.length); //This line is important
dos.write(buffer, 0, buffer.length);
dos.flush();
//dos.close();
}
if (flag==false){
clientSocket = serverSocket.accept();
flag = true;
}
//Closing socket
//dos.close();
clientSocket.close();
}
}
And
CLIENT SIDE
Socket sock = new Socket("10.0.2.2", 5991);
System.out.println("Connecting.........");
FileOutputStream fos;
BufferedOutputStream bos;
OutputStream output;
DataOutputStream dos;
int len;
int smblen;
InputStream in;
boolean flag=true;
DataInputStream clientData;
BufferedInputStream clientBuff;
while (true)
{
//while(true && flag==true){
while(flag==true)
{
in = sock.getInputStream(); //used
clientData = new DataInputStream(in); //use
clientBuff = new BufferedInputStream(in); //use
int fileSize = clientData.read();
ArrayList<File>files=new ArrayList<File>(fileSize); ArrayList<Integer>sizes = new ArrayList<Integer>(fileSize); //store file size from client
//Start to accept those filename from server
for (int count=0;count < fileSize;count ++){
File ff=new File(clientData.readUTF());
files.add(ff);
}
for (int count=0;count < fileSize;count ++){
sizes.add(clientData.readInt());
}
for (int count =0;count < fileSize ;count ++)
{
if (fileSize - count == 1)
{
flag =false;
}
len=sizes.get(count);
//System.out.println("File Size ="+len);
output = new FileOutputStream("/mnt/sdcard/" + files.get(count));
dos=new DataOutputStream(output);
bos=new BufferedOutputStream(output);
byte[] buffer = new byte[1024];
bos.write(buffer, 0, buffer.length); //This line is important
while (len > 0 && (smblen = clientData.read(buffer)) > 0)
{
dos.write(buffer, 0, smblen);
len = len - smblen;
dos.flush();
}
dos.close(); //It should close to avoid continue deploy by resource under view
}
}
if (flag==false)
{
sock = new Socket("10.0.2.2", 5991);
flag = true;
}
} }
catch (UnknownHostException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
Your read loop is incorrect. You need to constrain the read length so you don't over-run into the next file:
while (len > 0 && (smblen = clientData,read(buffer, 0, len > buffer.length ? buffer.length : (int)len)) > 0)
{
bos.write(buffer, 0, smblen);
len -= smblen;
}
Other comments:
File lengths are longs, not ints.
Use a bigger buffer, at least 8192, and declare it once at the top of the method. You don't need a new one per file.
Don't flush inside the loop.
Don't keep recreating the streams. Use the same ones for the life of the socket, at both ends.
You should be writing to 'bos', not 'dos'. In fact you don't need the DataOutputStream to write to the file at all. Just the BufferedOutputStream and the FileOutputStream.
You should send one filename, one length, then one file, then the next filename, ... That way the sender can stop any time. That gets rid of the initial count, and it also gets rid of all that 'flag' nonsense. If you get EOFException reading the next name, the peer has closed the connection.

java send file using sockets

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 ");
}
}

Why doesn't it read the line-termination ''\n'

This code is trying to read a file then reverse it to an output file.
When it writes it (without reversing) the output is the same.
But when it is reversed the output is written ALL on ONE line in the output file.
int i;
int x = 0;
int[] ar = new int[9999];
BufferedInputStream fin;
BufferedOutputStream fout;
try {
File f1 = new File("C:/Users/NetBeansProjects/QuestionOne/input.txt");
File f2 = new File("C:/Users/NetBeansProjects/QuestionOne/output.txt");
fin = new BufferedInputStream(new FileInputStream(f1));
fout = new BufferedOutputStream(new FileOutputStream(f2));
while ((i = fin.read()) != -1) { //reads file into an array
ar[x] = i;
x++;
}
for(int y = (x-1); y >= 0; y--){
//writes to a file from the end of the array
fout.write(ar[y]);
}
System.out.println();
fin.close();
fout.close();
} catch (FileNotFoundException e) {
System.out.println("File is NOT found.");
}
I'm using BufferedInputStream and BufferedOutputStream
Probably you are reading \r\n and writing back \n\r.
You have to handle \r\n as a separate entity.

To convert the file into byte array

I am creating one directory i.e file and storing the bitmap images into that file,now how to convert it into byte array
File myDir = new File(root + "/saved_images");
myDir.mkdirs();
Random generator = new Random();
int n = 10000;
n = generator.nextInt(n);
String fname = "Image-"+ n +".jpg";
File file = new File (myDir, fname);
if (file.exists ()) file.delete ();
try {
FileOutputStream out = new FileOutputStream(file);
bmp.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
If you just want to modify your existing code to write the image to a byte array instead of a file, then replace the try block with this code:
ByteArrayOutputStream out = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.JPEG, 90, out);
bytes = out.getBytes();
... where bytes has type byte[], and get rid of the code that generates the filename and deletes the existing file if it exists. Since you writing to a ByteArrayOutputStream, there is not need to call flush() or close() on out. (They won't do anything.)
Not exactly sure what you're trying to do, but you can try something like:
InputStream is = ...
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[some huge number, power of 2 preferably];
while ((nRead = is.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
buffer.flush();
byte[] byteArray = buffer.toByteArray();
Just Use this to read the file where you kept.
// Returns the contents of the file in a byte array.
public static byte[] getBytesFromFile(File file) throws IOException {
InputStream is = new FileInputStream(file);
// Get the size of the file
long length = file.length();
// You cannot create an array using a long type.
// It needs to be an int type.
// Before converting to an int type, check
// to ensure that file is not larger than Integer.MAX_VALUE.
if (length > Integer.MAX_VALUE) {
// File is too large
}
// Create the byte array to hold the data
byte[] bytes = new byte[(int)length];
// Read in the bytes
int offset = 0;
int numRead = 0;
while (offset = 0) {
offset += numRead;
}
// Ensure all the bytes have been read in
if (offset
Courtesy : http://www.exampledepot.com
I have used this code for converting image file into byte araay,
Bitmap bm = BitmapFactory.decodeResource(getResources(),R.drawable.abc);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 40 , bos);
public byte[] bitmapdata = bos.toByteArray();
Log.w("Image Conversion", String.valueOf(bitmapdata.length));
String converted_txt="";
for (int i = 0; i < bitmapdata.length; i++)
{
Log.w("Image Conversion", String.valueOf(bitmapdata[i]));
ba = bitmapdata[i];
converted_txt=converted_txt+bitmapdata[i];
}
try
{
File myFile = new File("/sdcard/myImageToByteFile.jpg");
myFile.createNewFile();
fOut = new FileOutputStream(myFile);
OutputStreamWriter myOutWriter = new OutputStreamWriter(fOut);
myOutWriter.write(ba);
myOutWriter.close();
fOut.close();
}
catch (Exception e)
{
Toast.makeText(getApplicationContext(), e.getMessage(),5000).show();
}

Categories

Resources