4

I'm trying to copy a file from my local machine to Shared folder in a windows server. This is the function which I used.

public static void copyFileUsingJcifs(final String domain, final String userName, final String password, final String sourcePath, final String destinationPath) throws IOException {
    final NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication(domain, userName, password);
    final SmbFile sFile = new SmbFile(destinationPath, auth);
    final SmbFileOutputStream smbFileOutputStream = new SmbFileOutputStream(sFile);
    final FileInputStream fileInputStream = new FileInputStream(new File(
            sourcePath));

    final byte[] buf = new byte[16384];
    int len;
    while ((len = fileInputStream.read(buf)) > 0) {
        smbFileOutputStream.write(buf, 0, len);
    }
    fileInputStream.close();
    smbFileOutputStream.close();
}

I tried this answer, but didn't work for me. When I do normal copying(Copy and Paste) it only takes maximum of 8minutes for a 25MB file. But when I use my java program using this function its taking more than 20minutes. How can I make this copying faster? Thanks in advance.

Christophe Roussy
  • 16,299
  • 4
  • 85
  • 85
Nirmal Raghavan
  • 572
  • 7
  • 20
  • 1
    There could be lots of reasons, buffer over/under runs (ie the write taking longer the read, slowing the whole process down), network latency (unoptimised handling of packets) and API overhead. Try playing around with the `byte` buffer a little and see if that changes anything – MadProgrammer Aug 08 '13 at 06:48
  • @MadProgrammer I tried with both low buffer size and some big values. But there wasn't any better performance changes. I'm using jcifs-1.3.17.jar – Nirmal Raghavan Aug 08 '13 at 06:57
  • 8 minutes for 25 megabytes is quite slow for a LAN. What is your environment? – Thorbjørn Ravn Andersen Aug 08 '13 at 07:15
  • @ThorbjørnRavnAndersen I tried to copy the file to a remote location. In LAN its working fine. I'm using Windows 7 on my machine. And the Server is running on Windows Server 2008. – Nirmal Raghavan Aug 08 '13 at 07:21
  • 1
    Sounds like small buffer sizes (either your buffer or transfer buffers inside JCIF). – Thorbjørn Ravn Andersen Aug 08 '13 at 08:07
  • @ThorbjørnRavnAndersen I tried the buffer(buffer inside this function) sizes from 1024 to 16*1024*1024, no luck. How can I change the buffer size inside JCIFS library? – Nirmal Raghavan Aug 08 '13 at 09:01
  • I do not know. Perhaps raise the question on the JCIFS mailing list? – Thorbjørn Ravn Andersen Aug 08 '13 at 10:02

6 Answers6

2

In case it helps others...I had a similar issue, but in the other direction (slow copying TO Windows using JCIFS). The issue was resolved by adding

   -Djcifs.resolveOrder=DNS

to the property list. (The default inclusion of BCAST -- to send a NetBIOS name query broadcast to 255.255.255.255 -- is what was causing the enormous delay.)

Glenn
  • 881
  • 9
  • 11
  • 1
    Just to add to this ancient thread - we just had this issue pop up, and this option helped us get through it while we tracked down root cause. In our case, a Samba server had won the local NetBIOS election and registered with a non-routable interface, causing jCIFS to hang while trying to connect. – Virtually Nick Feb 07 '21 at 01:41
2

try this function its highly optimized if its still slow then increase buffer size in code . In my case it reduced time from 10 min to copy 48MB file to 1 min

public static boolean createCopyOnNetwork(String domain,String username,String password,String src, String dest) throws Exception
{
    //FileInputStream in = null;
    SmbFileOutputStream out = null;
     BufferedInputStream inBuf = null;
    try{
        //jcifs.Config.setProperty("jcifs.smb.client.disablePlainTextPasswords","true");
        NtlmPasswordAuthentication authentication = new NtlmPasswordAuthentication(domain,username,password); // replace with actual values  
        SmbFile file = new SmbFile(dest, authentication); // note the different format
        //in = new FileInputStream(src);
          inBuf = new BufferedInputStream(new FileInputStream(src));
        out = (SmbFileOutputStream)file.getOutputStream();
        byte[] buf = new byte[5242880];
        int len;
        while ((len = inBuf.read(buf)) > 0){
            out.write(buf, 0, len);
        }
    }
    catch(Exception ex)
    {
        throw ex;
    }
    finally{
        try{
            if(inBuf!=null)
                inBuf.close();
            if(out!=null)
                out.close();
        }
        catch(Exception ex)
        {}
    }
    System.out.print("\n File copied to destination");
        return true;
}
fahad
  • 389
  • 2
  • 12
2

What I noticed is that jCIFS does "something" (afair jcifs.smb.SmbTransport.checkStatus(..)) for every chunk it reads - i.e. for each chunk that is read into the buffer. That means increasing your buffer size might really speed things up, although the real problem still exists, but only occurs 1 or 2 times having a lower impact on the overall time..

It helps a lot to set "jcifs.util.loglevel=3" and have a look what's really wrong..

In my case I had to set "jcifs.smb.client.dfs.disabled=false" in the end, as "jcifs.resolveOrder=DNS" didn't help..

floh.mueller
  • 83
  • 1
  • 7
1

I was having the same issue. Tried -Djcifs.resolveOrder=DNS with no luck. After reading a few comments with buffer size I decided to go to the extreme and really ramp it up. I know my transfer rate should be at least 50mb/s so I converted that to bytes and set it as my buffer and it worked as expected.

Matthew Pautzke
  • 548
  • 5
  • 13
1

There are some new SMB java project that support SMB2 and above , I think you can give them a try.

Just note that SMB2 is better, faster and more secure than SMB1 (jCifs)

Eliad Cohen
  • 378
  • 2
  • 10
0

I compared time take to write a big buffer into file in the shared folder. The smbj is more than 10 times faster than jcifs!

doronk
  • 101
  • 1
  • 4