Java Апплет-Проблемы С Производительностью Экспорта Изображений


У меня есть Java-апплет, в который я делаю некоторые правки и сталкиваюсь с проблемами производительности. Более конкретно, апплет генерирует изображение, которое мне нужно экспортировать на компьютер клиента.

Это действительно на стадии доказательства концепции, так что потерпите меня. На данный момент изображение экспортируется на клиентскую машину в заранее определенном месте (это будет заменено диалогом сохранения или чем-то еще в будущем). Однако этот процесс занимает почти 15 секунд для файла размером 32 КБ.

Я сделал некоторое профилирование "стреляй по бедру", где я печатал сообщения на консоль через логические интервалы на протяжении всего рассматриваемого метода. Я обнаружил, к своему удивлению, что узкое место, по-видимому, связано с реальным процессом записи потока данных, а не с кодировкой jpeg.

ИМЕЙТЕ В ВИДУ, ЧТО У МЕНЯ ЕСТЬ ТОЛЬКО БАЗОВЫЕ ЗНАНИЯ JAVA И ЕГО МЕТОДОВ

Так что не торопитесь :p-я в основном ищу предложения, чтобы решить проблему, а не решение сам.

Вот блок кода, где происходит волшебство:

ByteArrayOutputStream jpegOutput = new ByteArrayOutputStream();
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(jpegOutput);
encoder.encode(biFullView);
byte[] imageData = jpegOutput.toByteArray();

String myFile="C:" + File.separator + "tmpfile.jpg";
File f = new File(myFile);

try {
dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(myFile),512));
dos.writeBytes(byteToString(imageData));
dos.flush();
dos.close();
}
catch (SecurityException ee) {
    System.out.println("writeFile: caught security exception");
}
catch (IOException ioe) {
    System.out.println("writeFile: caught i/o exception");
}

Как я уже упоминал, используя систему.из.println() я сузил узкое место производительности до блока DataOutputStream. Использование различных машин с различной аппаратной статистикой, по-видимому, мало влияет на общую производительность.

Любые указатели / предложения / направления были бы весьма признательны.

Править: Как и было предложено, byteToString ():

public String byteToString(byte[] data){
  String text = new String();
  for ( int i = 0; i < data.length; i++ ){
    text += (char) ( data[i] & 0x00FF );
  }
  return text;
}
3 2

3 ответа:

Если вам не нужен байтовый массив данных изображения, вы можете закодировать его непосредственно в файл:

String myFile="C:" + File.separator + "tmpfile.jpg";
File f = new File(myFile);
FileOutputStream fos = null;
try {
    fos = new FileOutputStream(f);
    JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(
                             new BufferedOutputStream(fos));
    encoder.encode(biFullView);
}
catch (SecurityException ee) {
    System.out.println("writeFile: caught security exception");
}
catch (IOException ioe) {
    System.out.println("writeFile: caught i/o exception");
}finally{
    if(fos != null) fos.close();
}

Если вам нужен массив байтов для выполнения других операций, то лучше записать его непосредственно в поток FileOutputStream:

//...
fos = new FileOutputStream(myFile));
fos.write(imageData, 0, imageData.length);
//...

Возможно, вы захотите взглянуть на ImageIO.

И я думаю, что причина проблемы с производительностью-это цикличность в byteToString. Вы никогда не хотите делать конкатенацию в цикле. Вместо этого вы можете использовать конструктор String(byte[]), но вам все равно не нужно превращать байты в строку.

Можно также использовать стандартный ImageIO API (классы в com.солнце.изображение.кодек.пакет jpeg не является частью основных API Java).

String myFile="C:" + File.separator + "tmpfile.jpg";
File f = new File(myFile);
ImageIO.write(biFullView, "jpeg", f);