How to trap ftp success/failure in sun.net.ftp.FtpClient? - java

I want to know if really 'put' has succeeded in putting the file to destination. If for any reason the file is not put in destination [maybe due to problems in destination server like space constraint, etc] I need to know that.
Code:
private static boolean putFile(String m_sLocalFile, FtpClient m_client) {
boolean success = false;
int BUFFER_SIZE = 10240;
if (m_sLocalFile.length() == 0) {
System.out.println("Please enter file name");
}
byte[] buffer = new byte[BUFFER_SIZE];
try {
File f = new File(m_sLocalFile);
int size = (int) f.length();
System.out.println("File " + m_sLocalFile + ": " + size + " bytes");
System.out.println(size);
FileInputStream in = new FileInputStream(m_sLocalFile);
OutputStream out = m_client.put(f.getName());
int counter = 0;
while (true) {
int bytes = in.read(buffer);
if (bytes < 0)
break;
out.write(buffer, 0, bytes);
counter += bytes;
System.out.println(counter);
}
out.close();
in.close();
} catch (Exception ex) {
System.out.println("Error: " + ex.toString());
}
return success;
}

I would expect it to throw an IOException. Do you have any reason to believe it doesn't? But you shouldn't be using that class directly, you should be using an ftp: URL and its URLConnection class to do the I/O with, after calling setDoOutput(true).

Related

Java socket getting only NUL characters after writing byte array

I'm trying to send files in chunks from a client to server via byte arrays. I'm using ObjectInputStream. The write works and the filesize matches but when I open the file, I only get a blank textfile(which when opened in a IDE, shows NUL,NUL,NUL...).
Server code:
try(
FileOutputStream fileOut = new FileOutputStream(file);
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
){
byte[] arr = new byte[chunkSize];
try {
int len = 0;
long bytesRead = 0;
byte[] bytes = new byte[chunkSize];
int chunkNo = 1;
while(true)
{
len = in.read(bytes,0, chunkSize);
System.out.println();
if(len < 0)
break;
fileOut.write(arr, 0, len);
bytesRead += len;
out.writeObject(Server.CHUNK_ACKNOWLEDGE_MSG);
String ackReply = (String) in.readObject();
if(ackReply.equalsIgnoreCase((Server.UPLOAD_ACKNOWLEDGE_RECEIVE_TIMEOUT_MSG))){
if(Server.DEBUG)
System.out.println(fileName + " send timeout.");
deleteFile();
break;
}else if (ackReply.equalsIgnoreCase(Server.UPLOAD_COMPLETE_MSG)){
if(bytesRead != fileSize){
System.out.println(fileName + " File size mismatch");
deleteFile();
break;
}else{
System.out.println( fileName + " File written");
break;
}
}
}
}catch (IOException ioe){
if(Server.DEBUG)
ioe.printStackTrace();
}
Client code:
try(
FileInputStream fileInput = new FileInputStream(file);
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
){
byte[] arr = new byte[chunkSize];
try {
int len = 0;
int bytesRead = 0;
int chunkCount = 1;
while((len = fileInput.read(arr, 0, chunkSize)) != -1)
{
out.write(arr, 0, len);
out.flush();
bytesRead += len;
}
try {
System.out.println("wait ack");
socket.setSoTimeout(timeout);
String ack = (String) in.readObject();
System.out.println(ack);
if(bytesRead >= fileSize){
out.writeObject(Server.UPLOAD_COMPLETE_MSG);
System.out.println(Server.UPLOAD_COMPLETE_MSG);
break;
}else{
out.writeObject(Server.CHUNK_ACKNOWLEDGE_MSG);
}
}catch (SocketTimeoutException e){
out.writeObject(Server.UPLOAD_ACKNOWLEDGE_RECEIVE_TIMEOUT_MSG);
System.out.println(Server.UPLOAD_ACKNOWLEDGE_RECEIVE_TIMEOUT_MSG);
break;
}finally {
socket.setSoTimeout(0);
}
}
}
}catch (IOException ioe){
ioe.printStackTrace();
}
}catch (FileNotFoundException fnfe){
System.out.println("No such file: " + fileName);
}catch (Exception e){
e.printStackTrace();
}
finally {
try {
socket.close();
}catch (Exception ex){
ex.printStackTrace();
}
}
I tried writing the byte array to another file on the client side and the copy was identical. So the problem must be during sending data over socket.
The Server.X_MSG is just a constant string. I don't know if mixing readobject() and read(bytearray) on the same ObjectInputStream causes any issues though.
Maybe it's because fileOut.write(arr, 0, len); use arr and len = in.read(bytes,0, chunkSize); use bytes? They are not the same array.

Handle specific byte from socket in Java

I'm using the code below to read a Unix socket:
Boolean flag = false;
while (!flag) {
try {
File socketFile = new File("./RISP");
AFUNIXSocket sock = AFUNIXSocket.newInstance();
sock.connect(new AFUNIXSocketAddress(socketFile));
System.out.println("!!!!!!!!!!CONNECTED!!!!!!!!!");
flag = true;
BufferedReader input = new BufferedReader(new InputStreamReader(sock.getInputStream()));
String line = null;
while ((line = input.readLine())!=null) {
System.out.println(line);
}
} catch (IOException e) {
System.out.println("NOT CONNECTED....." + e);
}
try {
Thread.sleep(2000);
} catch (InterruptedException inter) {
System.out.println(inter);
}
}
I need to read the first 4 bytes of each pack and convert them from binary to integer.
I've read many posts but I'm still looking for the best solution to my problem.
Reader and Writer are designed for reading text.
For binary, you should try InputStream and OutputStream, in this case, you want DataInputStream, possibly buffered.
DataInputStream in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
int len = in.readInt(); // read big-endian.
if (LITTLE_ENDIAN)
len = Integer.reverseBytes(len);
byte[] bytes = new byte[len];
in.readFully(bytes);
seems it works
DataInputStream in = new DataInputStream(new BufferedInputStream(sock.getInputStream()));
int len = -1;
while ((len = in.readInt()) != -1) {
len = Integer.reverseBytes(len);
byte[] bytes = new byte[len];
in.readFully(bytes);
if (bytes.length > 4) {
System.out.println(" BYTE0: " + bytes[0] +
" BYTE1: " + bytes[1] +
" BYTE2: " + bytes[2] +
" BYTE2: " + bytes[3] +
" LENGHT: " + bytes.length);
}
}
please let me know is i miss something.
thanks a lot to you guys.

java file receive stops

I'm using sockets for file transfer in java.
Here is the Client code
for(int i = 0;i < fileList.size();i++) {
String filename = (String)fileList.get(i);
RequestFile(filename);
try {
BufferedOutputStream fileWriter = new BufferedOutputStream(
new FileOutputStream(
new File(PROGRAM_PATH + "/" +
filename)));
int packet;
int count = 0;
while((packet = fileReader.read()) != -1) {
fileWriter.write(packet);
count++;
}
System.out.println(filename + " receiver complete. (count : " + count + ")");
fileWriter.flush();
fileWriter.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
And here is the Server code
public void SendFile(String filename) {
try {
fileReader = new BufferedInputStream(new FileInputStream(CLIENT_PATH + "/" + filename));
int packet;
int count = 0;
while((packet = fileReader.read()) != -1) {
count++;
fileWriter.write(packet);
}
fileWriter.write(-1);
System.out.println(count);
fileReader.close();
}
catch (IOException ioe) {
ioe.printStackTrace();
}
}
When I checked the server's count, it was 635. It means the server had sent data 635 times.
However, the client's print count is only 512. (from 0 to 511) I think it's stopped at read(), because
System.out.println(filename + " receiver complete. (count : " + count + ")");
is not printed. Can someone tell me the reason and solution?
At the server side you can't send a byte with value -1 to the client. This line:
fileWriter.write(-1);
It does not do what you want. The write() method will take the lowest 8 bits of the parameter and send that as one byte (which in this case will be 0xff). At the client side fileReader.read() will receive this as 0xff (of type int) and not as -1 (of type int).
-1 is a special value indicating that end of stream has been reached. It is not a valid data to be written or read. If you send -1, the client will read that as 0xff=255. The values that can be sent and received is 0..255 both inclusive. Again, -1 is a special value for end-of-stream.
At the server side you don't flush or close the output stream. That might explain the difference (data hold in the buffer might not get through to the client).

Reading JPEG Stream over socket gives Null characters

I am reading a .jpg file over InputStream using this code but I am receiving NULNUL...n stream after some text. Ii am reading this file link to file and link of file that I received , link is Written File link.
while ((ret = input.read(imageCharArray)) != -1) {
packet.append(new String(imageCharArray, 0, ret));
totRead += ret;
imageCharArray = new char[4096];
}
file = new File(
Environment.getExternalStorageDirectory()
+ "/FileName_/"
+ m_httpParser.filename + ".jpg");
PrintWriter printWriter = new PrintWriter(file);
// outputStream = new FileOutputStream(file); //also Used FileoutputStream for writting
// outputStream.write(packet.toString().getBytes());//
// ,
printWriter.write(packet.toString());
// outputStream.close();
printWriter.close();
}
I have also tried FileoutputStream but hardlucj for this too as commented in my code.
Edit
I have used this also. I have a content length field upto which i am reading and writing
byte[] bytes = new byte[1024];
int totalReadLength = 0;
// read untill we have bytes
while ((read = inputStream.read(bytes)) != -1
&& contentLength >= (totalReadLength)) {
outputStream.write(bytes, 0, read);
totalReadLength += read;
System.out.println(" read size ======= "
+ read + " totalReadLength = "
+ totalReadLength);
}
String is not a container for binary data, and PrintWriter isn't a way to write it. Get rid of all, all, the conversions between bytes and String and vice versa, and just transfer the bytes with input and output streams:
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
If you need to constrain the number of bytes read from the input, you have to do that before calling read(), and you also have to constrain the read() correctly:
while (total < length && (count = in.read(buffer, 0, length-total > buffer.length ? buffer.length: (int)(length-total))) > 0)
{
total += count;
out.write(buffer, 0, count);
}
I tested it in my Nexus4 and it's working for me. Here is the snippet of code what I tried :
public void saveImage(String urlPath)throws Exception{
String fileName = "kumar.jpg";
File folder = new File("/sdcard/MyImages/");
// have the object build the directory structure, if needed.
folder.mkdirs();
final File output = new File(folder,
fileName);
if (output.exists()) {
output.delete();
}
InputStream stream = null;
FileOutputStream fos = null;
try {
URL url = new URL(urlPath);
stream = url.openConnection().getInputStream();
// InputStreamReader reader = new InputStreamReader(stream);
DataInputStream dis = new DataInputStream(url.openConnection().getInputStream());
byte[] fileData = new byte[url.openConnection().getContentLength()];
for (int x = 0; x < fileData.length; x++) { // fill byte array with bytes from the data input stream
fileData[x] = dis.readByte();
}
dis.close();
fos = new FileOutputStream(output.getPath());
fos.write(fileData);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Just Call the above function in a background thread and pass your url. It'll work for sure. Let me know if it helps.
You can check below code.
destinationFile = new File(
Environment.getExternalStorageDirectory()
+ "/FileName_/"
+ m_httpParser.filename + ".jpg");
BufferedOutputStream buffer = new BufferedOutputStream(new FileOutputStream(destinationFile));
byte byt[] = new byte[1024];
int i;
for (long l = 0L; (i = input.read(byt)) != -1; l += i ) {
buffer.write(byt, 0, i);
}
buffer.close();

What is the reason for java.io.IOException: Underlying input stream returned zero bytes

Here is my code, imageFile is a pdf file, intent is to get Base64 encoded file for image file. I am using Java6 and no possibility to upgrade to Java7
Base64Inputstream is of type org.apache.commons.codec.binary.Base64InputStream
private File toBase64(File imageFile) throws Exception {
LOG.info(this.getClass().getName() + " toBase64 method is called");
System. out.println("toBase64 is called" );
Base64InputStream in = new Base64InputStream(new FileInputStream(imageFile), true );
File f = new File("/root/temp/" + imageFile.getName().replaceFirst("[.][^.]+$" , "" ) + "_base64.txt" );
Writer out = new FileWriter(f);
copy(in, out);
return f;
}
private void copy(InputStream input, Writer output)
throws IOException {
InputStreamReader in = new InputStreamReader(input);
copy(in, output);
}
private int copy(Reader input, Writer output) throws IOException {
long count = copyLarge(input, output);
if (count > Integer.MAX_VALUE) {
return -1;
}
return (int) count;
}
private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
private long copyLarge(Reader input, Writer output) {
char[] buffer = new char[DEFAULT_BUFFER_SIZE];
long count = 0;
int n = 0;
try {
while (-1 != (n = input.read(buffer))) {
output.write(buffer, 0, n);
count += n;
System.out.println("Count: " + count);
}
} catch (IOException e) {
e.printStackTrace();
}
return count;
}
I was using IOUtils.copy(InputStream input, Writer output) method. But for some pdf files (note, not all) it throws exception. So, in the process of debugging I copied IOUtils.copy code locally and exception is thrown after Count: 2630388. This is the stack trace:
Root Exception stack trace:
java.io.IOException: Underlying input stream returned zero bytes
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:268)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:306)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:158)
Under what situations can this block above said throw exception:
while (-1 != (n = input.read(buffer))) {
output.write(buffer, 0, n);
count += n;
System.out.println("Count: " + count);
}
Please help me understand the cause and how can I fix it
You should not use Reader/Writer which are text oriented and not binary, at least without encoding. They use an encoding. And PDF is binary. Either explicitly given, or the default OS encoding (unportable).
For InputStream use readFully.
And then do always a close(). The copy method, maybe leaving the close to the callers, could at least call flush() in that case.
In Java 7 there already exists a copy, but needs a Path and an extra option.
private File toBase64(File imageFile) throws Exception {
LOG.info(this.getClass().getName() + " toBase64 method is called");
System.out.println("toBase64 is called");
Base64InputStream in = new Base64InputStream(new FileInputStream(imageFile),
true);
File f = new File("/root/temp/" + imageFile.getName()
.replaceFirst("[.][^.]+$", "") + "_base64.txt");
Files.copy(in, f.toPath(), StandardCopyOption.REPLACE_EXISTING);
in.close();
return f;
}

Categories

Resources