Buffering using Array and reading parts of it.

Hi,

Excuse me, but I wasn't able to form the subject of the title very good. Now I will explain you the problem better: I have a file splitted in many parts (for example 100). In order to join this file I have to read all the parts, one by one, and update an array, to which every part is added. Of course this takes time, and the user is usually unpatient. So I want to at 1/4 of this "buffering" to start showing the file - to start outputing the first parts of the array, while the other parts continue to be added. Any ideas?

[543 byte] By [mihailmileva] at [2007-10-3 1:37:36]
# 1
> Of course this> takes time, and the user is usually unpatient. How much time?How big are the files?How are you reading the files?How are you presenting the content of the files to the user?
sabre150a at 2007-7-14 18:35:45 > top of Java-index,Other Topics,Algorithms...
# 2

Well, let's say that the parts are 64000bytes (array with size 64000), and you have 50 parts, then the for-loop which should read the array 50 times * 64000bytes - it takes around 5minutes for 2MB file. The size of files is every time different - once will be 2, once will be 7MB or even 30MB. The files are stored in 64KB-parts in the filesystem and I am using bufferedinputstream which reads data to a byte[] with size 64000, and then add the contents of this byte[] to a bigger array.

mihailmileva at 2007-7-14 18:35:45 > top of Java-index,Other Topics,Algorithms...
# 3

> Well, let's say that the parts are 64000bytes (array

> with size 64000), and you have 50 parts, then the

> for-loop which should read the array 50 times *

> 64000bytes - it takes around 5minutes for 2MB file.

Then you have serious problem with your code because it should take nothing like that long! I load and parse a 27 MByte map file in a couple of seconds.

> The size of files is every time different - once will

> be 2, once will be 7MB or even 30MB. The files are

> stored in 64KB-parts in the filesystem and I am using

> bufferedinputstream which reads data to a byte[] with

> size 64000, and then add the contents of this byte[]

> to a bigger array.

Post your code!

sabre150a at 2007-7-14 18:35:45 > top of Java-index,Other Topics,Algorithms...
# 4

This is an application for a smartphone device, but the problem is in the basics.

Status.show("Starting playback...", 300);

String sSongName = (String)lfldc.get(lfld, lfld.getSelectedIndex());

currPlaying = sSongName;

RecordStore rs = null;

byte[] data = new byte[0]; //main which will store all data

byte[] temp = new byte[0]; //temporary one for data

byte[] buffer = new byte[64000]; // we will read from the filesystem here

int y = 0;

rs = RecordStore.openRecordStore("Mp3Player:" + sSongName, false); //open file

data = rs.getRecord(1);

rs.closeRecordStore();

int iFileParts = Integer.parseInt(new String(data), 10);

/******* HERE IS THE PROBLEMATIC FOR-LOOP ********/

for(int i = 1; i <= iFileParts; i++) {

Status.show("Buffering! Please wait ..." + i + "/" + iFileParts, 500);

rs = RecordStore.openRecordStore("Mp3Player:" + sSongName + ":" + i, false); //open file

buffer = rs.getRecord(1); //get file data

rs.closeRecordStore();

temp = data; //save old data

data = new byte[temp.length + 64000]; //add 64000bytes to length

for(int z = 0; z < temp.length; z++)

data[z] = temp[z]; //return back old data

for(int z = temp.length; z < data.length; z++) {

if(y < buffer.length) {

data[z] = buffer[y]; //add new data

y++;

}

else break;

}

y = 0;

}

/*********END OF THE LOOP ***********/

p = javax.microedition.media.Manager.createPlayer(new ByteArrayInputStream(data), "audio/mpeg"); //create player

p.realize();

p.prefetch();

vc = (VolumeControl)p.getControl("VolumeControl");

p.addPlayerListener(new MusicListener());

vc.setLevel(preferredVolume);

p.start(); //play

mihailmileva at 2007-7-14 18:35:45 > top of Java-index,Other Topics,Algorithms...
# 5
Ok, I've managed to speed up the process a little bit - removed all the for-loops which extended the data array, and placed the follwoing call: System.arraycopy(Object,int, Object, int, int)
mihailmileva at 2007-7-14 18:35:45 > top of Java-index,Other Topics,Algorithms...
# 6

So it is not actually a File but a databse record! I do just this to store large documents in a database. My extraction code is

public void extract(int fileID, OutputStream os) throws SQLException, IOException

{

String extractFileSQL = "SELECT file_content FROM FILE_CONTENT where file_id = ? ORDER BY ID";

PreparedStatement stmnt = connection_.prepareStatement(extractFileSQL);

stmnt.setInt(1, fileID);

ResultSet rs = stmnt.executeQuery();

int len = 0;

int index = 0;

while (rs.next())

{

index++;

InputStream is = rs.getBinaryStream(1);

IOCopy.copyInputStreamToOutputStream(is, os);

is.close();

}

rs.close();

}

This load 64MByte from a MySQL database and writes it to a file in about a second.

The IOCopy.copyInputStreamToOutputStream() method is

static public OutputStream copyInputStreamToOutputStream(InputStream istrm, OutputStream ostrm, int bufferLength) throws IOException

{

if (bufferLength < 128)

bufferLength = 128;

else if (bufferLength > 65536)

bufferLength = 65536;

byte[] buffer = new byte[bufferLength];

for (int bytesRead = 0; (bytesRead = istrm.read(buffer)) >= 0;)

{

ostrm.write(buffer, 0, bytesRead);

}

ostrm.flush();

return ostrm;

}

but I wrote this some time age before NIO so it could be made faster.

You can write the output into a ByteArrayOutputSteam and get the bytes from it. This will save a load of copying.

I also use this to to write database content to my home grown MP3 and OGG player and I don't even have to buffer it. I just write the byte straight to the the MP3/OGG bit streams.

sabre150a at 2007-7-14 18:35:45 > top of Java-index,Other Topics,Algorithms...
# 7

For all who want to see the answer, here's how I speeded up the process a lot:

Status.show("Starting playback...", 300);

String sSongName = (String)lfldc.get(lfld, lfld.getSelectedIndex());

currPlaying = sSongName;

RecordStore rs = null;

byte[] data = new byte[0]; //main which will store all data

byte[] buffer = new byte[64000]; // we will read from the filesystem here

rs = RecordStore.openRecordStore("Mp3Player:" + sSongName, false); //open file

data = rs.getRecord(1);

rs.closeRecordStore();

int iFileParts = Integer.parseInt(new String(data), 10);

data = new byte[iFileParts * 64000];

int currPos = 0;

/******* HERE IS THE FOR-LOOP ********/

for(int i = 1; i <= iFileParts; i++) {

Status.show("Buffering! Please wait ..." + i + "/" + iFileParts, 500);

rs = RecordStore.openRecordStore("Mp3Player:" + sSongName + ":" + i, false); //open file

buffer = rs.getRecord(1); //get file data

rs.closeRecordStore();

System.arraycopy(buffer,0,data,currPos,buffer.length);

currPos += buffer.length;

}

/*********END OF THE LOOP ***********/

p = javax.microedition.media.Manager.createPlayer(new ByteArrayInputStream(data), "audio/mpeg"); //create player

p.realize();

p.prefetch();

vc = (VolumeControl)p.getControl("VolumeControl");

p.addPlayerListener(new MusicListener());

vc.setLevel(preferredVolume);

p.start(); //play

@sabre150: Thanks a lot, man! You indeed helped me, I will use parts of your code when I upload the files to the "database" as you call it! :) ;)

mihailmileva at 2007-7-14 18:35:45 > top of Java-index,Other Topics,Algorithms...