簡體   English   中英

java串行read()無限期等待-如何中斷它?

[英]java serial read() is waiting indefinitely - how to break it?

我有一個連接到我的PI的串行設備,可以從中讀取數據...一切都很好,但是有時電纜移動了或串行設備拔出了。

然后

line = r.readLine();

卡住了

我已嘗試通過以下方法解決此問題:

BufferedReader r = new BufferedReader (newnputStreamReader(p.getInputStream()));     
         try 
            {
                line = r.readLine();
                if (line.length() == 0)
                {
                    logfile.append("problem");
                    logfile.close();
                    System.out.println("Problem");
                    TimeUnit.SECONDS.sleep(5);
                    break;
                }

            }
            catch (IOException e)
            {
                logfile.append(line);
                logfile.close();
            }

但是它什么也不做(因為我懷疑他仍在等待數據)甚至都不會引發異常,我該如何讓他說我有問題? 也許使用計時器或類似的東西? 如果5秒鍾沒有數據?

謝謝 ,

在這種情況下,您的假設是正確的。 BufferedReaderreadLine()方法具有一個內部while-loop ,該while-loop將從底層輸入流中檢索所有字節,並且僅在到達的字符為\\n\\r時才會中斷。

可以這樣想:

while(lastChar != '\n' || lastChar != '\r')
{
     //read from stream
}

但是,一旦輸入該方法將不會返回。 唯一的例外是這兩個特殊字符的出現或InputStream被關閉(在這種情況下,返回null ist)。

訣竅是在從InputStream讀取某些內容之前,不要輸入:

public static void main( String[] args ) throws IOException
{

  boolean awaitInput = true;

  while(awaitInput)
  {
    if(System.in.available() != 0)
    {
      awaitInput = false;
      // read logic
    }
  }
}

這只是許多可能的解決方案之一,我以System.in為例,因為它也像其他任何輸入源一樣都是InputStream。 但是,還有一個稱為BufferedReader#ready的方法,如果有需要讀取的內容,則返回true

public static void main( String[] args ) throws IOException
{

  BufferedReader br = new BufferedReader( new InputStreamReader(System.in) );

  boolean awaitInput = true;

  while(awaitInput)
  {
    if(br.ready())
    {
      awaitInput = false;
      String line = br.readLine();
      // read logic
    }
  }
}

最后,如果您想超時,可以這樣輕松地自己完成:

public static void main( String[] args ) throws IOException
{
  BufferedReader br = new BufferedReader( new InputStreamReader(System.in) );
  boolean awaitInput = true;
  long timeout = System.currentTimeMillis() + 5_000;
  //                                          ^^^^^ 5_000ms = 5 sec 

  while(awaitInput && System.currentTimeMillis() < timeout)
  {
    if(br.ready())
    {
      awaitInput = false;
      String line = br.readLine();
      // read logic
    }
  }
}

您可以使用CompletableFuture並發讀取並可以使用超時。

// wrap the readLine into a concurrent call
CompletableFuture<String> lineFuture = CompletableFuture.supplyAsync(() -> r.readLine());
try {
    // do the call, but with a timeout
    String readLine = lineFuture.get(5, TimeUnit.SECONDS);
    // do stuff with the line you read
} catch (TimeoutException e) {
    // plug pulled?
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM