首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >java从文件中读取文本后,开始打印"null“

java从文件中读取文本后,开始打印"null“
EN

Stack Overflow用户
提问于 2013-08-25 07:09:52
回答 4查看 4.2K关注 0票数 3

我从.txt文件中读取了以下内容:

代码语言:javascript
复制
<?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>

但是在读完之后,我得到了这个:

代码语言:javascript
复制
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,这是一个方法:

代码语言:javascript
复制
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

有什么办法解决这个问题吗?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-08-25 07:15:08

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

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

代码语言:javascript
复制
String x = null;
String y = "a";
String z = x + y; // "nulla"

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

代码语言:javascript
复制
str += sCurrentLine;

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

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

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

而且,您不应该在这样的循环中使用字符串连接--这在性能上是很糟糕的,因为它需要不断地复制旧数据。使用StringBuilder代替。

我也不会发现这样的异常--你真的想让来电者不知道出了什么差错吗?只需声明您的方法可以抛出IOException

此外,我不会亲自使用FileReader --它无法控制用于读取文件的编码--它将始终使用平台默认编码,这可能是不合适的。我会使用包装在FileInputStream中的InputStreamReader。然后,可以在Java7中使用try-with-resources语句自动关闭FileInputStream

因此,通过所有这些更改,您的代码将变成如下所示:

代码语言:javascript
复制
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 -只需将字符读入缓冲区即可。

另外,考虑使用第三方库(如番石榴 )来代替所有这些--例如,您可以使用Files.toString()

票数 5
EN

Stack Overflow用户

发布于 2013-08-25 07:11:44

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

这是在JLS -第5.1.11节中指定的

如果引用为null,则将其转换为字符串"null“(4个ASCII字符n、u、l、l)。

现在,当您声明实例或静态引用字段而不初始化任何值时,它将被初始化为默认值- null,如声明中所示:

代码语言:javascript
复制
private static String str;  // This is `null`.

然后,对于循环的第一次迭代:

代码语言:javascript
复制
str += sCurrentLine;

相当于:

代码语言:javascript
复制
str = null + sCurrentLine;  // Hence the result.

至于您的str.indexOf()查询,我不知道您在哪里测试索引,因为它应该返回null的索引,即0,只要在循环之后使用该方法,如下面的片段所示:

代码语言:javascript
复制
String str = null;
String str2 = str + "someString";
System.out.println("Index of null in : " + str2 + " : " + str2.indexOf("null"));

这将输出给您:

代码语言:javascript
复制
Index of null in : nullsomeString : 0

此外,在这样一个循环中执行字符串连接时,当它结束时(甚至在一般情况下),您应该使用StringBuilder实例来避免创建中间字符串实例,这是您无法控制的:

代码语言:javascript
复制
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(sCurrentLine);
票数 5
EN

Stack Overflow用户

发布于 2013-08-25 07:12:08

代码语言:javascript
复制
private static String str;

是空的。你必须初始化它。

代码语言:javascript
复制
private static String str = "";
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18426607

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档