我想写一个由0到x的整数组成的int[][](其中x是一种颜色的图像数量)。现在,我只是写了一个列元素,然后是一个分隔符,然后是一个元素,如此重复。然后,一旦我完成了我的列,我写一个列分隔符,并移动到下一个。
for (int i = 0; i < imageColors.length; i++) {
for (int j = 0; j < imageColors[0].length; j++) {
writer.append(compressedColors[i][j]);
writer.append("!");
}
writer.append("@");
}
我可以一列一列地写我的数组,用@
分隔,但是有更好的方法我可以写这些列吗?特别是考虑到很多元素是连续的和相同的,我觉得这可以用更少的文件空间来完成。只要我能解码到原始数据,什么都可以。
谢谢!
将整数写成十六进制会使它们更短,您只需要记住在读取它们时使用16进制。有时,固定长度编码可以通过去掉数字分隔符来节省空间,例如"!"。这取决于你的数字有多少个前导零。此外,如果所有的数字都适合一个短字节或一个字节,那么您可以使用short[][]
或byte[][]
来节省空间。
就像你说的,最大的一个可能是运行长度编码。而不是:
"1234!1234!1234!1234!@"
你有这样的东西:
"r4x1234!@"
同样,您需要重写您的读取代码来考虑。"r"表示这是一个运行长度,而不是一个普通的数字。"x"将运行长度与要重复的数字分开。
较短的运行长度可以延长输出;没有一种压缩方法是完美的。用"1234!5678!"
代替"r1x1234!r1x5678!"
下面是一些未测试的代码,用于运行长度编码。我已将其设置为使用十六进制并拒绝小于3的运行。
void writeArray(int[][] imageColors, Writer writer) throws IOException {
for (int i = 0; i < imageColors.length; i++) {
writer.append(processRow(imageColors[i]));
writer.append("@");
}
}
String processRow(int[] row) {
int pointer = 0;
StringBuilder sb = new StringBuilder(DEFAULT_ROW_LENGTH);
// Set up for first rum.
int currentValue = row[pointer];
int repeatCount = 1;
pointer++;
while (pointer < row.length) {
if (row[pointer] == currentValue) {
// One more value in this run.
++repeatCount;
++pointer;
} else {
// End of run.
if (repeatCount == 1) {
sb.append(Integer.toHexString(currentValue));
} else if (repeatCount == 2) {
sb.append(Integer.toHexString(currentValue));
sb.append("!");
sb.append(Integer.toHexString(currentValue));
} else {
// Process long run >= 3.
sb.append("r"); // "r" for "run".
sb.append(Integer.toHexString(repeatCount));
sb.append("x"); // Separate run length from value.
sb.append(Integer.toHexString(currentValue));
}
sb.append("!");
// Set up for next run.
currentValue = row[pointer];
repeatCount = 1;
pointer++;
}
}
return sb.toString();
}
只是为了让您高兴,有一个明显的代码片段丢失了。包含它会使示例变得复杂,而不会添加任何新内容。