Hello I was curious on how data can be downloaded in java, so I looked through few methods and decided to use BufferedInputStream.
Now when I download, I download the file by 1024 bytes burst, and everytime it downloads 1kb I concat the temp array to the main data array.tH
I use this concat method:
public static byte[] concat(byte[] data, byte[] bytes) {
byte[] result = Arrays.copyOf(data, data.length + bytes.length);
System.arraycopy(bytes, 0, result, data.length, bytes.length);
return result;
}
This is my download process:
URL target = new URL ("http://freshhdwall.com/wp-content/uploads/2014/08/Image-Art-Gallery.jpg");
URLConnection t = target.openConnection();
t.setRequestProperty("User-Agent", "NING/1.0");
t.connect();
BufferedInputStream stream = new BufferedInputStream(t.getInputStream());
final byte[] bytes = new byte[1024];
int count;
byte[] data = new byte[0];
while ( (count = stream.read(bytes, 0, bytes.length)) != -1) {
System.out.println(count);
data = concat(data, bytes);
}
Now after downloading, I convert the bytes array to BufferedImage using ByteArrayInputStream:
InputStream s = new ByteArrayInputStream(data);
BufferedImage m = ImageIO.read(s);
And then I display the result:
JFrame j = new JFrame();
j.add(new JLabel(new ImageIcon(m)));
j.pack();
j.setVisible(true);
Now the result image looks like this:
(source: gyazo.com)
As you see, the image looks broken, missing bytes when downloading.
This is the real image:
img http://freshhdwall.com/wp-content/uploads/2014/08/Image-Art-Gallery.jpg
What did I do wrong that it displays the image like that?
On each loop iteration, you potentially read less than bytes.length bytes. As such, you can't use the full length of the array. You need to use exactly that part that was actually read.
One solution is to use
while ((count = stream.read(bytes, 0, bytes.length)) != -1) {
System.out.println(count); // this should hint at this
data = concat(data, bytes, count); // use the count
}
and
public static byte[] concat(byte[] data, byte[] bytes, int count) {
byte[] result = Arrays.copyOf(data, data.length + count);
System.arraycopy(bytes, 0, result, data.length, count);
return result;
}
so as to only copy over the bytes you've actually received.
Consider using some of the solutions here. They are probably more efficient or, at least, more readable.
Related
I am trying to convert a Byte Array to a String in order to be able to see this Vector/Array and analyse how these bytes are organized.
I'm using the code below to do it:
byte[] bytes = bos.toByteArray();
String msgDecode = new String(bytes); // trying to convert byte in String
System.out.println("Vetor de bytes [" + msgDecode + "]"); // Showing it
But it's not working. Why the code above it's no working?
It is worth mentioning that the Byte Array is being constructed according to this other code here:
String path = Environment.getExternalStorageDirectory().getAbsolutePath()+"/"+UUID.randomUUID().toString()+"audio_record.3gp";
public byte[] convert(String path) throws IOException {
FileInputStream fis = new FileInputStream(path);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] b = new byte[1024];
for (int readNum; (readNum = fis.read(b)) != -1; ) {
bos.write(b, 0, readNum);
}
byte[] bytes = bos.toByteArray();
return bytes;
}
The general idea is to record an audio with the smartphone and convert this audio file to a array of bytes. This String path is the path where the audio is being saved after recording. Then I use this path (that represents the audio file) and convert it to a byte array according to the code above.
More information you can find and help me here: How to solve this error: Android resource linking failed?
if you want to see value of bytes you can use as below:
Log.d("TAG", Arrays.toString(bytes));
What I'll try to do, based in what you guys said:
String decode = Arrays.toString(bytes);
Log.d("mytag", decode);
byte[] bytes = "ABCDEFG".getBytes();
System.out.println(new String(bytes)); // ABCDEFG
System.out.println(Arrays.toString(bytes)); // [65, 66, 67, 68, 69, 70, 71]
I have a byte array obtained from an image using the following code.
String path = "/home/mypc/Desktop/Steganography/image.png";
File file = new File(path);
BufferedImage bfimage = ImageIO.read(file);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(bfimage, "png", baos);
baos.flush();
byte[] img_in_bytes = baos.toByteArray();
baos.close();
Then I converted these bytes back to png image using the following code.
BufferedImage final_img = ImageIO.read(new ByteArrayInputStream(img_in_bytes));
File output_file = new File("Stegano2.png");
ImageIO.write(final_img, "png", output_file);
It is perfectly fine if i just execute this piece of code. But if i try to modify some of the bytes in between, say like this :
Insert_number_to_image(image_in_bytes, 10);
and my method "Inset_number_to_image" goes like this :
static void Insert_number_to_image(byte[] image, int size){
byte[] size_in_byte = new byte[4];
size_in_byte[0] = (byte)(size >>> 0);
size_in_byte[1] = (byte)(size >>> 8);
size_in_byte[2] = (byte)(size >>> 16);
size_in_byte[3] = (byte)(size >>> 24);
byte temp;
int count = 0;
for(int i=0; i<4; i++)
{
for(int j=0; j<8; j++)
{
temp = size_in_byte[i];
temp = (byte)(temp >>> j);
temp = (byte)(temp & 1);
if(temp == 1)
{
image[count] = (byte)(image[count] | 1);
}
else if(temp == 0)
{
image[count] = (byte)(image[count] & (byte)(~(1)));
}
count++;
}
}
}
then after that, when i save the modified byte array as png image using same code mentioned above, i am getting this error :
Exception in thread "main" java.lang.IllegalArgumentException: image == null!
at javax.imageio.ImageTypeSpecifier.createFromRenderedImage(ImageTypeSpecifier.java:925)
at javax.imageio.ImageIO.getWriter(ImageIO.java:1591)
at javax.imageio.ImageIO.write(ImageIO.java:1520)
at Steganography.main(Steganography.java:211)
What you're using is the raw bytestream of a PNG image. PNG is a compressed format, where the bytestream doesn't reflect any of the pixel values directly and even changing one byte might irreversibly corrupt the file.
What you want instead is to extract the pixel data to a byte array with
byte[] pixels = ((DataBufferByte) img.getRaster().getDataBuffer()).getData();
Now you can modify the pixel values however you want. When you are ready to save that back to a file, convert the pixel byte array to a BufferedImage by putting your pixel array in a DataBufferByte object and passing that to a WriteableRaster, which you then use to create a BufferedImage.
Your method would work for formats where the raw bytestream does directly represent the pixels, such as in BMP. However, even then you'd have to skip the first few bytes to avoid corrupting the header.
I want to use java(httpurlconnection class) to download a pdf file,but have some thing puzzle,the core code is:
BufferedInputStream inputStream = new BufferedInputStream(httpConn.getInputStream());
OutputStream output = new FileOutputStream("F:/httpclient-tutorial.pdf");
byte[] infoBytes = new byte[BUFFER];
while(inputStream.read(infoBytes) != -1){
output.write(infoBytes, 0, BUFFER);
}
Question:when the BUFFER is 1024,get the pdf file is larger than real one;but the BUFFER is 8,then it's ok. I don't know why it is? Has anyone know about that?
You're unconditionally writing out the whole of the buffer on each iteration. You should only write out as many bytes as you've just read:
int bytesRead;
while((bytesRead = inputStream.read(infoBytes)) != -1){
output.write(infoBytes, 0, bytesRead);
}
I have the following code:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int size = 4096;
byte[] bytes = new byte[size];
while (is.read(bytes, 0, size) != -1)
{
baos.write(bytes);
baos.flush();
}
When I do:
String s = baos.toString();
I get \u0000-s appended to my string. So, if my character data is only X bytes out of Y, the Y-Z will get prefilled with \u0000 making it impossible to check for equals. What am I doing wrong here? How should I be converting the bytes to a String in this case?
The entire array (all 4096 bytes) is be written to the output - arrays have no idea of how much "useful data" they contain!
Store how much was read into a variable (InputStream.read returns a useful number) and specify that to the appropriate OutputStream.write overload to only write a portion (that which contains the useful data) of the array.
While the above change should "fix" the problem, it is generally recommended to use the string<->byte[] conversion forms that take in an explicit character set.
You should only be writing as much data as you are reading in each time through the loop:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int size;
byte[] bytes = new byte[4096];
while (size = is.read(bytes, 0, bytes.length) != -1)
{
baos.write(bytes, 0, size);
}
baos.flush();
String s = baos.toString();
You might consider specifying a specific character set for converting the bytes to a String. The no-arg toString() method uses the platform default encoding.
new String(baos.toByteArray(), 0, strLen, encoding)
Im receiving a file trough this code and the "bos.write" are saving it o to my HDD.
Everything working good.
Since im sending the file in a few second i thought i could store the file in memory
instead of HDD.
Now how do i do this?
File path = new File("C://anabella//test1.txt");
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(path));
int size = 1024;
int val = 0;
byte[] buffer = new byte[1024];
while (fileSize >0) {
val = in.read(buffer, 0, size);
bos.write(buffer, 0, val);
fileSize -= val;
if (fileSize < size)
size = (int) fileSize;
}
Presumably bos is a FileOutputStream? To use an in-memory buffer use a ByteArrayOutputStream instead.
If you know the size in advance you don't even need a ByteArrayOutputStream
InputStream is = socket.getInputStream(); // or where ever the inputstream comes from.
DataInputStream in = new DataInputStream(is);
byte[] bytes = new byte[fileSize];
in.readFully(bytes);
to send the bytes to any OutputStream like
OutputStream os = ...
os.write(bytes);
The bytes will contain the contents of the file.