Reading JPEG Stream over socket gives Null characters - java

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();

Related

File md5 hash changes when chunking it (for netty transfer)

Question at the bottom
I'm using netty to transfer a file to another server.
I limit my file-chunks to 1024*64 bytes (64KB) because of the WebSocket protocol. The following method is a local example what will happen to the file:
public static void rechunck(File file1, File file2) {
FileInputStream is = null;
FileOutputStream os = null;
try {
byte[] buf = new byte[1024*64];
is = new FileInputStream(file1);
os = new FileOutputStream(file2);
while(is.read(buf) > 0) {
os.write(buf);
}
} catch (IOException e) {
Controller.handleException(Thread.currentThread(), e);
} finally {
try {
if(is != null && os != null) {
is.close();
os.close();
}
} catch (IOException e) {
Controller.handleException(Thread.currentThread(), e);
}
}
}
The file is loaded by the InputStream into a ByteBuffer and directly written to the OutputStream.
The content of the file cannot change while this process.
To get the md5-hashes of the file I've wrote the following method:
public static String checksum(File file) {
InputStream is = null;
try {
is = new FileInputStream(file);
MessageDigest digest = MessageDigest.getInstance("MD5");
byte[] buffer = new byte[8192];
int read = 0;
while((read = is.read(buffer)) > 0) {
digest.update(buffer, 0, read);
}
return new BigInteger(1, digest.digest()).toString(16);
} catch(IOException | NoSuchAlgorithmException e) {
Controller.handleException(Thread.currentThread(), e);
} finally {
try {
is.close();
} catch(IOException e) {
Controller.handleException(Thread.currentThread(), e);
}
}
return null;
}
So: just in theory it should return the same hash, shouldn't it? The problem is that it returns two different hashes that do not differ with every run.. file size stays the same and the content either.
When I run the method once for in: file-1, out: file-2 and again with in: file-2 and out: file-3 the hashes of file-2 and file-3 are the same! This means the method will properly change the file every time the same way.
1. 58a4a9fbe349a9e0af172f9cf3e6050a
2. 7b3f343fa1b8c4e1160add4c48322373
3. 7b3f343fa1b8c4e1160add4c48322373
Here is a little test that compares all buffers if they are equivalent. Test is positive. So there aren't any differences.
File file1 = new File("controller/templates/Example.zip");
File file2 = new File("controller/templates2/Example.zip");
try {
byte[] buf1 = new byte[1024*64];
byte[] buf2 = new byte[1024*64];
FileInputStream is1 = new FileInputStream(file1);
FileInputStream is2 = new FileInputStream(file2);
boolean run = true;
while(run) {
int read1 = is1.read(buf1), read2 = is2.read(buf2);
String result1 = Arrays.toString(buf1), result2 = Arrays.toString(buf2);
boolean test = result1.equals(result2);
System.out.println("1: " + result1);
System.out.println("2: " + result2);
System.out.println("--- TEST RESULT: " + test + " ----------------------------------------------------");
if(!(read1 > 0 && read2 > 0) || !test) run = false;
}
} catch (IOException e) {
e.printStackTrace();
}
Question: Can you help me chunking the file without changing the hash?
while(is.read(buf) > 0) {
os.write(buf);
}
The read() method with the array argument will return the number of files read from the stream. When the file doesn't end exactly as a multiple of the byte array length, this return value will be smaller than the byte array length because you reached the file end.
However your os.write(buf); call will write the whole byte array to the stream, including the remaining bytes after the file end. This means the written file gets bigger in the end, therefore the hash changed.
Interestingly you didn't make the mistake when you updated the message digest:
while((read = is.read(buffer)) > 0) {
digest.update(buffer, 0, read);
}
You just have to do the same when you "rechunk" your files.
Your rechunk method has a bug in it. Since you have a fixed buffer in there, your file is split into ByteArray-parts. but the last part of the file can be smaller than the buffer, which is why you write too many bytes in the new file. and that's why you do not have the same checksum anymore. the error can be fixed like this:
public static void rechunck(File file1, File file2) {
FileInputStream is = null;
FileOutputStream os = null;
try {
byte[] buf = new byte[1024*64];
is = new FileInputStream(file1);
os = new FileOutputStream(file2);
int length;
while((length = is.read(buf)) > 0) {
os.write(buf, 0, length);
}
} catch (IOException e) {
Controller.handleException(Thread.currentThread(), e);
} finally {
try {
if(is != null)
is.close();
if(os != null)
os.close();
} catch (IOException e) {
Controller.handleException(Thread.currentThread(), e);
}
}
}
Due to the length variable, the write method knows that until byte x of the byte array, only the file is off, then there are still old bytes in it that no longer belong to the file.

Code that download empty file and supposed not to

I have this part of function where it supposed to download file like pdf from server and store in new directory. It does do this but an empty pdf or text file.How to fix it.
`File urlfile = new File(host + "/" + path);
urlfile.getParentFile().mkdirs();
// create outputstream for request and inputstream for data
// download
FileOutputStream outS = new FileOutputStream(urlfile);
DataInputStream instream = new DataInputStream(newsocket.getInputStream());
// get rid of head part to get to actual file
String l = null;
String lastmodtime = null;
boolean done = false;
while (!(l = DAA.readLine()).equals("")) {
if (!done && l.contains("Last-Modified:")) {
lastmodtime = l.substring(l.indexOf(' ') + 1, l.length());
done = true;
System.out.println(l);
}
}
// read in bytes to correct file name
try {
byte[] inbytes = new byte[16384];
int input;
while ((input = instream.read(inbytes)) != -1) {
outS.write(inbytes, 0, input);
}
}`
You can try this simple code if you want to create a copy of the file or you can even use apache commons io (FileUtils.copyFile(source, dest)) for java copy file operation.
private static void copyFileUsingStream(File source, File dest)
throws IOException {
InputStream is = null;
OutputStream os = null;
try {
is = new FileInputStream(source);
os = new FileOutputStream(dest);
byte[] buffer = new byte[1024];
int length;
while ((length = is.read(buffer)) > 0) {
os.write(buffer, 0, length);
}
} finally {
is.close();
os.close();
}
}

Java Socket Programming Buffer for Large File

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.

PDF to Bytearray conversion in java

Below is my code to convert a PDF file to byte array
public class ByteArrayExample{
public static void main(String[] args) {
try{
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter File name: ");
String str = bf.readLine();
File file = new File(str);
//File length
int size = (int)file.length();
if (size > Integer.MAX_VALUE){
System.out.println("File is to larger");
}
byte[] bytes = new byte[size];
DataInputStream dis = new DataInputStream(new FileInputStream(file));
int read = 0;
int numRead = 0;
while (read < bytes.length && (numRead=dis.read(bytes, read,
bytes.length-read)) >= 0) {
read = read + numRead;
}
System.out.println("File size: " + read);
// Ensure all the bytes have been read in
if (read < bytes.length) {
System.out.println("Could not completely read: "+file.getName());
}
}
catch (Exception e){
e.getMessage();
}
}
}
Issue is this actually converts the file name into the byte array not the actual PDF file.Can anyone please help me with this.
I added this to the end to check it and it copied the PDF file. Your code is working fine
dis.close();
DataOutputStream out = new DataOutputStream(new FileOutputStream(new File("c:\\out.pdf")));
out.write(bytes);
out.close();
System.out.println("File size: " + read);
// Ensure all the bytes have been read in
if (read < bytes.length) {
System.out.println("Could not completely read: "+file.getName());
}
edit: here is my entire code, its just copied from yours. I ran it in IDE (eclipse) and entered "c:\mypdf.pdf" for the input and it copied it to out.pdf. Identical Copys. Do note that I did close both streams which I noticed you forgot to do in your code.
public class Main {
public static void main(String[] args) {
try {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter File name: ");
String str = bf.readLine();
File file = new File(str);
//File length
int size = (int) file.length();
if (size > Integer.MAX_VALUE) {
System.out.println("File is to larger");
}
byte[] bytes = new byte[size];
DataInputStream dis = new DataInputStream(new FileInputStream(file));
int read = 0;
int numRead = 0;
while (read < bytes.length && (numRead = dis.read(bytes, read,
bytes.length - read)) >= 0) {
read = read + numRead;
}
dis.close();
DataOutputStream out = new DataOutputStream(new FileOutputStream(new File("c:\\out.pdf")));
out.write(bytes);
out.close();
System.out.println("File size: " + read);
// Ensure all the bytes have been read in
if (read < bytes.length) {
System.out.println("Could not completely read: " + file.getName());
}
} catch (Exception e) {
e.getMessage();
}
}
}

Joining two mp3 files into one

I have this code to read bytes to another file.
But I'm not able to concatenate two mp3 files into one.
Am I missing something?
public static void main(String[] args) {
String strFileName = ("D:/Music/Assb/Love.mp3");
BufferedOutputStream bos = null;
try
{
//create an object of FileOutputStream
FileOutputStream fos = new FileOutputStream(new File(strFileName));
//create an object of BufferedOutputStream
bos = new BufferedOutputStream(fos);
String str = "D:/Music/Assembled/Heart001.mp3"
+ "D:/Music/Assembled/Heart002.mp3";
/*
* To write byte array to file use,
* public void write(byte[] b) method of BufferedOutputStream
* class.
*/
System.out.println("Writing byte array to file");
bos.write(str.getBytes());
System.out.println("File written");
It`s suck. Mp3 file starts with headers. For correct merging you have to skip first 32 bytes. Try this.
try {
FileInputStream fistream1 = new FileInputStream(_file_name);
File f = new File(new File(_file_name).getParent()+"/final.mp3");
if(!f.exists())
{
f.createNewFile();
}
FileOutputStream sistream = new FileOutputStream((new File(_file_name)).getParent()+"/final.mp3");
int temp;
int size = 0;
temp = fistream1.read();
while( temp != -1)
{
sistream.write(temp);
temp = fistream1.read();
};
fistream1.close();
FileInputStream fistream2 = new FileInputStream(temp_file);
fistream2.read(new byte[32],0,32);
temp = fistream2.read();
while( temp != -1)
{
sistream.write(temp);
temp = fistream2.read();
};
fistream2.close();
sistream.close();
} catch (IOException e) {
e.printStackTrace();
}
You need to do this in two steps
String str = "D:/Music/Assembled/Heart001.mp3";
>>> ADD code to open the file given by str <<<<
bos.write(strFile.getBytes());
>>> Add code to close the file
str = "D:/Music/Assembled/Heart002.mp3";
>>> ADD code to open the file given by str <<<<
bos.write(strFile.getBytes());
>>> Add code to close the file
And as you can see you need code to open the mp3 file to read it
What Are You Trying For...Actually..if You Want To Read 2 Files to Byte Stream the dont String str = "D:/Music/Assembled/Heart001.mp3"
+ "D:/Music/Assembled/Heart002.mp3";
make str1=D:/Music/Assembled/Heart001.mp3 and str2=D:/Music/Assembled/Heart002.mp3 and read str1,str2 seperately through bufferedoutputsream
This code will work well and merge audio of similar type with in seconds...
try {
InputStream in = new FileInputStream("C:\\a.mp3");//firstmp3
byte[] buffer = new byte[1 << 20]; // loads 1 MB of the file
OutputStream os = new FileOutputStream(new File("C:\\output.mp3", true);//output mp3
int count;
while ((count = in.read(buffer)) != -1) {
os.write(buffer, 0, count);
os.flush();
}
in.close();
in = new FileInputStream("C:\\b.mp3");//second mp3
while ((count = in.read(buffer)) != -1) {
os.write(buffer, 0, count);
os.flush();
}
in.close();
os.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

Categories

Resources