2013-08-25 45 views
3

我從.txt文件本readed:java中,在開始打印將「空」

<?xml version="1.0"?> 
<!DOCTYPE cross-domain-policy SYSTEM "/xml/dtds/cross-domain-policy.dtd"> 
<cross-domain-policy> 
    <allow-access-from domain="*" to-ports="*" /> 
</cross-domain-policy> 

但閱讀它,然後outputing後,我得到這個:

null<?xml version="1.0"?> 
<!DOCTYPE cross-domain-policy SYSTEM "/xml/dtds/cross-domain-policy.dtd"> 
<cross-domain-policy> 
    <allow-access-from domain="*" to-ports="*" /> 
</cross-domain-policy> 

零開頭,這是方法:

public class Filer { 

    private static String str; 
    public static String read(String file) { 

     BufferedReader br = null; 
     try { 

      String sCurrentLine; 

      br = new BufferedReader(new FileReader(file)); 

      while ((sCurrentLine = br.readLine()) != null) { 

       str += sCurrentLine; 
      } 

     } catch (IOException e) { 
      e.printStackTrace(); 
     } finally { 
      try { 
       if (br != null)br.close(); 
      } catch (IOException ex) { 
       ex.printStackTrace(); 
      } 
     } 

     return str; 

    } 
} 

返回的字符串其被outputed

我試圖通過str.indexOf("null");str.indexOf("\0");檢查字符串,但我得-1

就如何解決這一問題的任何想法?

回答

5

考慮你的循環的第一次迭代。 str的值爲空,並且sCurrentLine的值爲"<?xml version="1.0"?>"

在字符串連接中,空引用被轉換爲一個「null」字符串。例如:

String x = null; 
String y = "a"; 
String z = x + y; // "nulla" 

所以你的第一次迭代,當你執行:

str += sCurrentLine; 

str值將是"null<?xml version="1.0"?>"

可以只是初始化str"" ...但我不會。

無論如何,它沒有理由爲什麼它應該是一個靜態變量 - 即使方法被再次調用,你是否真的想保持舊值?那會很奇怪。它應該是一個本地變量。

而且,你不應該在這樣的循環中使用字符串連接 - 這是可怕的在性能方面,因爲它需要保持複製舊的數據。改爲使用StringBuilder

我不會捕獲這樣的異常 - 你真的想讓調用者不知道什麼地方出了問題嗎?只要聲明你的方法可以拋出IOException

此外,我自己不會使用FileReader--它不會控制用於讀取文件的編碼 - 它將始終使用平臺默認編碼,這可能不合適。我會用一個FileInputStream包裹在InputStreamReader。然後,您可以使用Java 7中的try-with-resources語句自動關閉FileInputStream

因此,所有這些改變,你的代碼會變得這樣的事情:

public static String read(String file) throws IOException { 
    StringBuilder builder = new StringBuilder(); 
    try (InputStream input = new FileInputStream(file)) { 
     BufferedReader reader = new BufferedReader(
      new InputStreamReader(input, "UTF-8")); 
     String line; 
     while ((line = reader.readLine()) != null) { 
      builder.append(line); 
     } 
    } 
    return builder.toString(); 
} 

注意,這將多行文件轉換成一行文字 - 用builder.append("\n")或類似的東西在循環中如果你想保留行數(但不關心行分隔符)。如果您想保留確切的行尾,請勿使用readLine - 只需將字符讀入緩衝區即可。

此外,請考慮使用第三方庫(例如Guava)來完成所有操作 - 例如,您可以使用Files.toString()

+0

感謝您對本信息,我'學習這種東西) – user2507316

+0

@ user2507316:看我的編輯甚至更多... –

+0

chosed這個答案是接受全建設者例子,再次感謝你 – user2507316

5

當您將一個null引用連接到一個字符串時,它將轉換爲"null"字符串,然後執行連接。

這在JLS - Section 5.1.11指定:

如果參考爲空,它被轉換爲字符串 「null」(N 4個ASCII字符,U,L,L)。

現在,當你宣佈一個實例或靜態引用域,而無需初始化爲任意值,它會被初始化爲默認值 - null,在你的宣言:

private static String str; // This is `null`. 

那麼對於第一循環的迭代:

str += sCurrentLine; 

相當於:

str = null + sCurrentLine; // Hence the result. 

至於你str.indexOf()查詢,我不知道你正在測試的指標,因爲它應該返回的null0索引,提供,您使用的方法中的循環後,如在下面的代碼片段:

​​

這將輸出到您:

Index of null in : nullsomeString : 0 

此外,雖然這樣的循環中執行字符串連接,這喲你無法控制,當它結束時,甚至在一般情況下,你應該使用StringBuilder例如,以避免產生中間字符串實例:

StringBuilder stringBuilder = new StringBuilder(); 
stringBuilder.append(sCurrentLine); 
+0

哇,非常感謝! – user2507316

+0

也爲什麼indexOf沒有找到concatinated的null,它返回我-1 – user2507316

1
private static String str; 

爲空。你必須初始化它。

private static String str = ""; 
+0

謝謝你的答案! – user2507316

+0

沒問題,@ user2507316 – Kon

1

這樣做private static String str = "";。 默認情況下,您的str變量爲null,因此使用連接null

如我所示將它初始化爲一個空白字符串。