在 Java 中读取 .ICO 文件
Reading .ICO file in Java
我正在尝试加载一个 ICO 文件,但我似乎在图像数据大小和图像数据偏移值中得到了奇怪的值,导致了 ArrayOutOfBoundsException。任何帮助表示赞赏。我尝试了 Little/Big endian 但没有成功。我找到了 ICO 结构的信息 here.
代码:
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;
public class IcoFileReader {
public static void main(String[] args) {
URL url = null;
try {
url = new URL("https://www.google.be/favicon.ico");
} catch (MalformedURLException e) {
e.printStackTrace();
}
if(url == null) {
System.err.println("Url is null");
System.exit(-1);
}
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try {
final byte[] chunk = new byte[4096];
final InputStream stream = url.openStream();
int bytesRead;
while ((bytesRead = stream.read(chunk)) > 0) {
outputStream.write(chunk, 0, bytesRead);
}
} catch (IOException e) {
e.printStackTrace();
}
final byte[] icoBytes = outputStream.toByteArray();
System.out.println("Ico bytes: " + Arrays.toString(icoBytes));
System.out.println("-- HEADER --");
System.out.println("Reserved: " + Arrays.toString(Arrays.copyOfRange(icoBytes, 0, 2)));
System.out.println("Image type: " + Arrays.toString(Arrays.copyOfRange(icoBytes, 2, 4)));
System.out.println("Num images: " + Arrays.toString(Arrays.copyOfRange(icoBytes, 4, 6)));
System.out.println("");
System.out.println("-- BODY --");
System.out.println("Width: " + icoBytes[6]);
System.out.println("Height: " + icoBytes[7]);
System.out.println("Color Palette: " + icoBytes[8]);
System.out.println("Reserved: " + icoBytes[9]);
System.out.println("Color planes: " + Arrays.toString(Arrays.copyOfRange(icoBytes, 10, 11)));
System.out.println("Bits per pixel: " + Arrays.toString(Arrays.copyOfRange(icoBytes, 12, 13)));
System.out.println("Img data size: " + Arrays.toString(Arrays.copyOfRange(icoBytes, 13, 17)) + " - " + ByteBuffer.wrap(Arrays.copyOfRange(icoBytes, 13, 17)).order(ByteOrder.LITTLE_ENDIAN).getInt());
System.out.println("Offset beginning data: " + Arrays.toString(Arrays.copyOfRange(icoBytes, 17, 21)) + " - " + ByteBuffer.wrap(Arrays.copyOfRange(icoBytes, 17, 21)).order(ByteOrder.LITTLE_ENDIAN).getInt());
final int imgSize = ByteBuffer.wrap(Arrays.copyOfRange(icoBytes, 13, 17)).order(ByteOrder.LITTLE_ENDIAN).getInt();
final int offset = ByteBuffer.wrap(Arrays.copyOfRange(icoBytes, 17, 21)).order(ByteOrder.LITTLE_ENDIAN).getInt();
System.out.println("Bytes length: " + icoBytes.length);
System.out.println("Image data: " + Arrays.toString(Arrays.copyOfRange(icoBytes, offset, offset + imgSize)));
/* for(int i = 0; i < icoBytes[4]; i ++) {
final int start = (i * offset);
System.out.println("Image data: " + Arrays.toString(Arrays.copyOfRange(icoBytes, start, start + imgSize)));
}*/
}
}
并且输出:
--HEADER--
预留:[0, 0]
图片类型:[1, 0]
图片数量:[2, 0]
--BODY--
宽度:16
身高:16
调色板:0
预留:0
彩色平面:1
每像素位数:[32]
图片数据大小:[0, 104, 4, 0] - 288768
偏移起始数据:[0, 38, 0, 0] - 9728
字节长度:5430
线程异常 "main" java.lang.ArrayIndexOutOfBoundsException
你被绊倒了。
System.out.println("Color planes: " + Arrays.toString(Arrays.copyOfRange(icoBytes, 10, 12)));
System.out.println("Bits per pixel: " + Arrays.toString(Arrays.copyOfRange(icoBytes, 12, 14)));
System.out.println("Img data size: " + Arrays.toString(Arrays.copyOfRange(icoBytes, 14, 18)) + " - " + ByteBuffer.wrap(Arrays.copyOfRange(icoBytes, 14, 18)).order(ByteOrder.LITTLE_ENDIAN).getInt());
System.out.println("Offset beginning data: " + Arrays.toString(Arrays.copyOfRange(icoBytes, 18, 22)) + " - " + ByteBuffer.wrap(Arrays.copyOfRange(icoBytes, 18, 22)).order(ByteOrder.LITTLE_ENDIAN).getInt());
final int imgSize = ByteBuffer.wrap(Arrays.copyOfRange(icoBytes, 14, 18)).order(ByteOrder.LITTLE_ENDIAN).getInt();
final int offset = ByteBuffer.wrap(Arrays.copyOfRange(icoBytes, 18, 22)).order(ByteOrder.LITTLE_ENDIAN).getInt();
(使用 ByteBuffer 将允许在没有显式索引的情况下进行顺序读取;并且只设置一次字节顺序。)
我正在尝试加载一个 ICO 文件,但我似乎在图像数据大小和图像数据偏移值中得到了奇怪的值,导致了 ArrayOutOfBoundsException。任何帮助表示赞赏。我尝试了 Little/Big endian 但没有成功。我找到了 ICO 结构的信息 here.
代码:
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;
public class IcoFileReader {
public static void main(String[] args) {
URL url = null;
try {
url = new URL("https://www.google.be/favicon.ico");
} catch (MalformedURLException e) {
e.printStackTrace();
}
if(url == null) {
System.err.println("Url is null");
System.exit(-1);
}
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try {
final byte[] chunk = new byte[4096];
final InputStream stream = url.openStream();
int bytesRead;
while ((bytesRead = stream.read(chunk)) > 0) {
outputStream.write(chunk, 0, bytesRead);
}
} catch (IOException e) {
e.printStackTrace();
}
final byte[] icoBytes = outputStream.toByteArray();
System.out.println("Ico bytes: " + Arrays.toString(icoBytes));
System.out.println("-- HEADER --");
System.out.println("Reserved: " + Arrays.toString(Arrays.copyOfRange(icoBytes, 0, 2)));
System.out.println("Image type: " + Arrays.toString(Arrays.copyOfRange(icoBytes, 2, 4)));
System.out.println("Num images: " + Arrays.toString(Arrays.copyOfRange(icoBytes, 4, 6)));
System.out.println("");
System.out.println("-- BODY --");
System.out.println("Width: " + icoBytes[6]);
System.out.println("Height: " + icoBytes[7]);
System.out.println("Color Palette: " + icoBytes[8]);
System.out.println("Reserved: " + icoBytes[9]);
System.out.println("Color planes: " + Arrays.toString(Arrays.copyOfRange(icoBytes, 10, 11)));
System.out.println("Bits per pixel: " + Arrays.toString(Arrays.copyOfRange(icoBytes, 12, 13)));
System.out.println("Img data size: " + Arrays.toString(Arrays.copyOfRange(icoBytes, 13, 17)) + " - " + ByteBuffer.wrap(Arrays.copyOfRange(icoBytes, 13, 17)).order(ByteOrder.LITTLE_ENDIAN).getInt());
System.out.println("Offset beginning data: " + Arrays.toString(Arrays.copyOfRange(icoBytes, 17, 21)) + " - " + ByteBuffer.wrap(Arrays.copyOfRange(icoBytes, 17, 21)).order(ByteOrder.LITTLE_ENDIAN).getInt());
final int imgSize = ByteBuffer.wrap(Arrays.copyOfRange(icoBytes, 13, 17)).order(ByteOrder.LITTLE_ENDIAN).getInt();
final int offset = ByteBuffer.wrap(Arrays.copyOfRange(icoBytes, 17, 21)).order(ByteOrder.LITTLE_ENDIAN).getInt();
System.out.println("Bytes length: " + icoBytes.length);
System.out.println("Image data: " + Arrays.toString(Arrays.copyOfRange(icoBytes, offset, offset + imgSize)));
/* for(int i = 0; i < icoBytes[4]; i ++) {
final int start = (i * offset);
System.out.println("Image data: " + Arrays.toString(Arrays.copyOfRange(icoBytes, start, start + imgSize)));
}*/
}
}
并且输出:
--HEADER--
预留:[0, 0]
图片类型:[1, 0]
图片数量:[2, 0]
--BODY--
宽度:16
身高:16
调色板:0
预留:0
彩色平面:1
每像素位数:[32]
图片数据大小:[0, 104, 4, 0] - 288768
偏移起始数据:[0, 38, 0, 0] - 9728
字节长度:5430
线程异常 "main" java.lang.ArrayIndexOutOfBoundsException
你被绊倒了。
System.out.println("Color planes: " + Arrays.toString(Arrays.copyOfRange(icoBytes, 10, 12)));
System.out.println("Bits per pixel: " + Arrays.toString(Arrays.copyOfRange(icoBytes, 12, 14)));
System.out.println("Img data size: " + Arrays.toString(Arrays.copyOfRange(icoBytes, 14, 18)) + " - " + ByteBuffer.wrap(Arrays.copyOfRange(icoBytes, 14, 18)).order(ByteOrder.LITTLE_ENDIAN).getInt());
System.out.println("Offset beginning data: " + Arrays.toString(Arrays.copyOfRange(icoBytes, 18, 22)) + " - " + ByteBuffer.wrap(Arrays.copyOfRange(icoBytes, 18, 22)).order(ByteOrder.LITTLE_ENDIAN).getInt());
final int imgSize = ByteBuffer.wrap(Arrays.copyOfRange(icoBytes, 14, 18)).order(ByteOrder.LITTLE_ENDIAN).getInt();
final int offset = ByteBuffer.wrap(Arrays.copyOfRange(icoBytes, 18, 22)).order(ByteOrder.LITTLE_ENDIAN).getInt();
(使用 ByteBuffer 将允许在没有显式索引的情况下进行顺序读取;并且只设置一次字节顺序。)