FileInputStream is too slow

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Nepomuk
    Recognized Expert Specialist
    • Aug 2007
    • 3111

    #1

    FileInputStream is too slow

    Hi!

    I'm trying to transfer files and to do so must, of course, read them. Now, my reference File has a size of 4.240.821 Bytes and I need something between 9 and 14 seconds to simply read it and save the data to arrays.

    When however I transfer the file via FTP, everything is done in about 1 second - reading, transferring and writing.

    I've written the following code, to find out, how much time is needed with different sizes of arrays:

    [CODE=java]
    import java.io.IOExcep tion;
    import java.io.FileInp utStream;
    import java.io.File;

    public class FileReadSpeed {
    public static void main(String[] args) {
    int howMany = 8;
    int howOften = 5;
    long[][] results = new long[howMany][howOften];
    int size = 64;

    try
    {
    File file = new File("E:\\temp\ \file.tar.gz");

    for(int i=8;i<8+howMany ;i++)
    {
    size *= 2;
    for(int j=0; j<howOften; j++)
    {
    System.gc();
    FileInputStream fiStream = new FileInputStream (file);
    long startTime = System.currentT imeMillis();
    byte[] data = new byte[size];
    long amount = file.length() / size;
    if(file.length( ) % size > 0) amount++;
    for(int k=0; k<amount; k++)
    {
    for(int l=0; l<data.length; l++)
    {
    if((k == amount-1) && (l == file.length() % size)) break;
    data[l] = (byte) fiStream.read() ;
    }
    }
    long finishTime = System.currentT imeMillis();
    long timeTaken = finishTime - startTime;
    results[i-8][j] = timeTaken;
    System.out.prin tln("Recorded (" + (i-8) + " | " + j + ") with size = " + size + " Bytes");
    }
    }
    }
    catch(IOExcepti on ioe)
    {
    System.err.prin tln(ioe);
    }

    System.out.prin tln();

    size = 64;
    for(int i=0; i<results.lengt h; i++)
    {
    size *= 2;
    System.out.prin t(size + ":\t");
    for(int j=0; j<results[i].length; j++)
    {
    System.out.prin t(results[i][j] + "\t");
    }
    double tmp = 0.;
    for(int j=0; j<results[i].length; j++)
    {
    tmp += results[i][j];
    }
    System.out.prin tln("-> " + tmp/results[0].length);
    }
    }
    }
    [/CODE]Does anyone know, if there are implementations of FileInputStream or similar, which are faster? (Maybe with reduced functionality?)

    Greetings,
    Nepomuk
    Last edited by Nepomuk; Sep 18 '07, 03:07 PM. Reason: A typo...
  • JosAH
    Recognized Expert MVP
    • Mar 2007
    • 11453

    #2
    You're reading a single byte every time; that is dead slow; you can read entire
    byte arrays in one sweep, use that instead (check the FileInputStream API).
    A byte array size of, say, 4096 is a typical buffer size.

    kind regards,

    Jos

    Comment

    • Nepomuk
      Recognized Expert Specialist
      • Aug 2007
      • 3111

      #3
      Originally posted by JosAH
      You're reading a single byte every time; that is dead slow; you can read entire
      byte arrays in one sweep, use that instead (check the FileInputStream API).
      A byte array size of, say, 4096 is a typical buffer size.

      kind regards,

      Jos
      OK, I've tried that, but somehow I've made a mistake and can't find it... it should be directly before my eyes I guess, but maybe someone can help.

      Here's my changed for-loop:
      [CODE=java]
      for(int k=0; k<amount; k++)
      {
      int offset = (int)(k*size);
      System.out.prin tln("offset:\t" + offset + "\nsize:\t" + size);
      fiStream.read(d ata,offset,size );
      }
      [/CODE]I also changed the settings a little:
      [CODE=java]
      int howMany = 4;
      int howOften = 5;
      int size = 512;
      [/CODE]

      And I get a IndexOutOfBound sException in the line, which does the reading, when the output is as follows:
      Code:
      offset:	0
      size:	1024
      offset:	1024
      size:	1024
      java.lang.IndexOutOfBoundsException...
      It seems to me, that the offset is wrong somehow, but I don't understand, what is wrong...

      Greetings,
      Nepomuk
      Last edited by Nepomuk; Sep 18 '07, 04:06 PM. Reason: Found one error in the for loop, which was nonsense...

      Comment

      • JosAH
        Recognized Expert MVP
        • Mar 2007
        • 11453

        #4
        Just do a:

        [code=java]
        int nofBytesRead= fiStream.read(d ata);
        [/code]
        and it will attempt to read as many bytes as possible in the 'data' byte array.
        All in one sweep that is.

        kind regards,

        Jos

        Comment

        • Nepomuk
          Recognized Expert Specialist
          • Aug 2007
          • 3111

          #5
          Originally posted by JosAH
          Just do a:

          [code=java]
          int nofBytesRead= fiStream.read(d ata);
          [/code]
          and it will attempt to read as many bytes as possible in the 'data' byte array.
          All in one sweep that is.

          kind regards,

          Jos
          The Problem with that is, that my program should be able to send files of any size and with a file, which is over 100MB big, that won't work (I have tried it).

          So, what mistake did I make with the offset version?

          Greetings,
          Nepomuk

          Comment

          • Nepomuk
            Recognized Expert Specialist
            • Aug 2007
            • 3111

            #6
            OK, I've found the error - I thought offset was the offset for the file, not for the array. It does work much faster now.

            Thank you very much!

            Greetings,
            Nepomuk

            Comment

            • JosAH
              Recognized Expert MVP
              • Mar 2007
              • 11453

              #7
              Originally posted by nepomuk
              OK, I've found the error - I thought offset was the offset for the file, not for the array. It does work much faster now.

              Thank you very much!

              Greetings,
              Nepomuk
              Told you so ;-) Simply create a byte array of 64K or so, keep on reading into that
              array, write the array until the read() call returns -1. The previous read might
              return a value less than the size of the array so you should always use that
              value.

              kind regards,

              Jos

              Comment

              Working...