我想写一个int [] [],由0到x的整数组成(其中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("@");
}
我可以逐列编写我的数组并按@
分隔,但是有更好的方法可以编写列吗?特别是考虑到很多元素是连续的和相同的,我觉得这可以使用更少的文件空间来完成。只要我能够解码到原始数据,任何事情都会发生。
谢谢!
答案 0 :(得分:0)
用十六进制编写整数会缩短它们,你只需要记住在阅读它时使用base 16。有时固定长度编码可以通过删除数字分隔符来节省空间,即“!”。这取决于您的号码有多少前导零。此外,如果您的所有数字都适合短或一个字节,那么您可以使用short[][]
或byte[][]
来节省空间。
正如你所说,最重要的可能是游程编码。而不是:
"1234!1234!1234!1234!@"
你有类似的东西:
"r4x1234!@"
同样,您需要重写您的阅读代码以考虑到这一点。 “r”表示这是一个运行长度,而不是一个普通的数字。 “x”将运行长度与要重复的数字分开。
短程可以延长输出;没有压缩方法是完美的。使用"1234!5678!"
代替"r1x1234!r1x5678!"
以下是一些运行长度编码的未经测试的代码。我已将其设置为使用十六进制并拒绝短于三的运行。
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();
}
为了让你高兴,有一段明显的代码遗失了。包括它会使示例变得复杂而不添加任何新内容。我把它作为读者的练习。