3

我从 .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");or来检查那个字符串,str.indexOf("\0");但我得到 -1

有想法该怎么解决这个吗?

4

4 回答 4

5

null引用与字符串连接时,会将其转换为"null"字符串,然后执行连接。

这在JLS - 第 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()查询,我不知道您在哪里测试索引,因为它应该返回nullthat is的索引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实例来避免创建中间字符串实例:

StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(sCurrentLine);
于 2013-08-25T07:11:44.383 回答
5

考虑循环的第一次迭代。的值为str空, 的sCurrentLine值为"<?xml version="1.0"?>"

在字符串连接中,空引用被转换为“空”字符串。例如:

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

因此,在您的第一次迭代中,当您执行时:

str += sCurrentLine;

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

可以初始化str""......但我不会。

无论如何它都没有理由应该是一个静态变量 - 即使再次调用该方法,您真的想保留旧值吗?那会很奇怪。它应该是一个局部变量。

此外,您不应该在这样的循环中使用字符串连接 - 这在性能方面很糟糕,因为它需要不断复制旧数据。改用 a StringBuilder

我也不会捕捉到这样的异常——你真的希望调用者不知道有什么问题吗?只需声明您的方法可以 throw IOException

此外,我不会使用FileReader我自己 - 它使您无法控制用于读取文件的编码 - 它将始终使用平台默认编码,这可能是不合适的。我会使用一个FileInputStream包裹在一个InputStreamReader. 然后您可以使用try-with-resourcesJava 7 中的语句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().

于 2013-08-25T07:15:08.487 回答
1
private static String str;

一片空白。你必须初始化它。

private static String str = "";
于 2013-08-25T07:12:08.343 回答
1

这样做private static String str = "";。默认情况下,您的str变量在使用null连接时是如此null

如我所示,将其初始化为空白字符串。

于 2013-08-25T07:12:44.733 回答