我正在编写一个FTP客户端应用程序,并在代码中的两点使用了System.nanoTime(),以秒为单位的差返回18,而我的程序只用了2秒...检查onPostExecute方法中的日志...
为什么会发生这种情况,我该如何解决?

protected String doInBackground(String... urls)
{
    try
        {
        if(perflag)
            return "Not yet";
        String ipadd= ip.getText().toString();
            BufferedReader br;
            int port =Integer.parseInt(portt.getText().toString());
        while(true) {
            socket = new Socket(ipadd, port);
            //Button conn=(Button) findViewById(R.id.connectb);
            if(startflag)
            {
                starttime=System.nanoTime();
                startflag=false;
            }
            //conn.setEnabled(false);
            br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            BufferedOutputStream bo = new BufferedOutputStream(socket.getOutputStream());
            PrintWriter pw = new PrintWriter(bo, true);
            file = br.readLine();
            if (file.equals("Finished"))
            {
               // socket.close();
                Log.i("stat","above sock");
               // Thread.sleep(1000);
                //socket= new Socket(ipadd,port);
                //br= new BufferedReader(new InputStreamReader(socket.getInputStream()));
                datas=br.readLine();
                data=Double.parseDouble(datas);
                Log.i("stat",datas);
                br.close();
                socket.close();
                finflag=true;
                break;
            }
            File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES);
            File f = new File(path, "/" + file);
            byte[] buff = new byte[1024];
            int len;

            int i=0;
            while(f.exists())
            {
                f= new File(path,"/"+"("+i+")"+file);
                i++;
            }
            pw.println("done");
            DataInputStream is = new DataInputStream(socket.getInputStream());
            FileOutputStream fos = new FileOutputStream(f);
            publishProgress(file);

            while ((len = is.read(buff)) != -1) {


                fos.write(buff, 0, len);

            }

            publishProgress(file);
        }
    }catch(NumberFormatException nfe)
    {

        runOnUiThread(new Runnable() {
            public void run() {
                Toast.makeText(MainActivity.this,"Enter a proper IP and port!",Toast.LENGTH_LONG).show();
                start();
            }
        });
        nfe.printStackTrace();

    }
    catch(java.net.UnknownHostException un)
    {
        runOnUiThread(new Runnable() {
            public void run() {
                Toast.makeText(MainActivity.this,"Enter a proper IP and port!",Toast.LENGTH_LONG).show();
                start();
            }
        });
        //Toast.makeText(MainActivity.this,"Enter a proper IP and port!",Toast.LENGTH_LONG).show();
        un.printStackTrace();
    }
    catch(java.net.NoRouteToHostException no)
    {

        runOnUiThread(new Runnable() {
            public void run() {
                Toast.makeText(MainActivity.this,"There is no active server at the specified IP and port!",Toast.LENGTH_LONG).show();
                start();
            }
        });
        no.printStackTrace();
    }
    catch(Exception e)

    {
            Log.i("error",e.getMessage());
            runOnUiThread(new Runnable() {
                public void run() {
                    Toast.makeText(MainActivity.this, "Error occurred!Try checking storage permissions or connection.", Toast.LENGTH_LONG).show();

                    start();
                }
            });
        e.printStackTrace();
    }

    endtime=System.nanoTime();
    return "Not Yet";
}
protected void onProgressUpdate(String... para)
{
    super.onProgressUpdate(para);
    trans.setText("Transfering file: "+para[0]);
}
protected void onPostExecute(String as) {
    start();

    if(finflag)
    {
        startflag=true;
        Log.i("start",String.valueOf(starttime));
        Log.i("end",String.valueOf(endtime));
        totaltime=endtime-starttime;

        Log.i("total",String.valueOf(totaltime));
        //totaltime/=100000000;
        double time=totaltime/1000000000;
        Log.i("time in secs",String.valueOf(time));
        double rate= (double)(data/time);
        Toast.makeText(MainActivity.this,"Transfer successful!",Toast.LENGTH_LONG).show();
        Toast.makeText(MainActivity.this,"Average transfer rate: "+rate+"MBps",Toast.LENGTH_LONG).show();
        finflag=false;
    }
}

最佳答案

进行整数除法以获取秒是没有意义的,因为那只会返回整秒。您无需整秒钟使用nanoTime。更改:

double time=totaltime/1000000000;




double time=totaltime/1000000000d; // (or totaltime/1000000000.0)


但是您使用的除数很好;纳米是10-9。但是,我在您的部门上方的代码中看到一条注释掉的行:

        //totaltime /= 100000000;
double time=totaltime/1000000000;


在那行中,除数只有8个零,没有9个零。您确定发布的“ 18”秒来自double time=totaltime/1000000000;而不是totaltime /= 100000000;吗?因为如果除数中的零太少,则实际的1.8秒时间看起来像18秒。

正如评论员所提到的那样,问题实际上是魔术常数,该常数很容易获得错误的零数。

以下是解决此问题的几种方法:


Java允许您出于任何原因在下划线中添加下划线;您可以编写totaltime / 1_000_000_000d使其更清楚地显示您正在使用多少个零。
Java还允许将科学符号表示为双精度,因此您也可以编写totaltime / 1e9
Java内置了用于转换时间单位的函数。但是,由于您只需要几分之一秒,因此不能简单地说出TimeUnit.NANOSECONDS.toSeconds(totaltime)(这将舍入到1秒)。但是,您可以说totaltime / (double) TimeUnit.SECONDS.toNanos(1)

10-04 20:28