我从.txt文件中读到了这个:
<?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>
但在阅读然后输出后我得到了这个:
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>
开头为null,这是方法:
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;
}
}
返回的字符串由System.out.println
我试图通过str.indexOf("null");
或str.indexOf("\0");
检查该字符串,但我得到-1
关于如何解决这个问题的任何想法?
答案 0 :(得分:5)
将null
引用与字符串连接时,会将其转换为"null"
字符串,然后执行连接。
这在JLS - Section 5.1.11中指定:
如果引用为null,则将其转换为字符串“null”(四个ASCII字符n,u,l,l)。
现在,当您声明一个实例或静态引用字段时,如果没有初始化为任何值,它将被初始化为默认值 - null
,如您的声明:
private static String str; // This is `null`.
然后是循环的第一次迭代:
str += sCurrentLine;
相当于:
str = null + sCurrentLine; // Hence the result.
至于你的str.indexOf()
查询,我不知道你在哪里测试索引,因为它应该返回null
的{{1}}索引,前提是你使用了循环后的方法,如下面的代码片段所示:
0
这将输出给你:
String str = null;
String str2 = str + "someString";
System.out.println("Index of null in : " + str2 + " : " + str2.indexOf("null"));
此外,在这样的循环中执行字符串连接时,您无法控制,当它结束时,甚至一般情况下,您应该使用Index of null in : nullsomeString : 0
实例,以避免创建中间字符串实例:
StringBuilder
答案 1 :(得分:5)
考虑循环的第一次迭代。 str
的值为null,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()
。
答案 2 :(得分:1)
private static String str;
为空。你必须初始化它。
private static String str = "";
答案 3 :(得分:1)
执行此操作private static String str = "";
。
默认情况下,您的str
变量为null
,因此在使用null
连接时。
如我所示,将其初始化为空白字符串。