首页 > 解决方案 > 为什么这个局部变量在 Java 中等于 null?

问题描述

我的目标是拥有一个存储文件内容的字符串。我从字面上撕掉了从 W3 学校( https://www.w3schools.com/java/java_files_read.asp )读取文件的算法,并简单地改变了一些东西。

public class Fileparser { 
    
    public void fileParse(String filename) {
        
        
        try {
              File myObj = new File("C:\\Users\\(myname)\\Desktop\\" + filename);
              Scanner myReader = new Scanner(myObj);
              String output = "";
              while (myReader.hasNextLine()) {
                String data = myReader.nextLine();
                output.concat(data);
              }
              myReader.close();
              System.out.println(output);
              
              
            } catch (FileNotFoundException e) {
              System.out.println("An error occurred.");
              e.printStackTrace();
            }
        
        
    
    }

}

当然,主要是我有一个 Fileparser 对象,它使用我桌面上的文件执行该方法,但它绝对没有打印任何内容。我不得不与 Java 搏斗,因为我不熟悉局部变量的范围。当我逐行连接输出时,为什么什么都不打印?

标签: javavariableslocal

解决方案


因为output.concat()没有向字符串output中添加任何内容指向:那是不可能的;java中的字符串是不可变的,不能更改。

相反,concat()构造一个新字符串,它是接收者和参数的连接,并返回对其的引用。像output = output.concat(data)完成工作这样简单的事情,但请注意,像这样的连接是非常低效的。更好的:

try {
              File myObj = new File("C:\\Users\\(myname)\\Desktop\\" + filename);
              Scanner myReader = new Scanner(myObj);
              StringBuilder output = new StringBuilder();
              while (myReader.hasNextLine()) {
                String data = myReader.nextLine();
                output.append(data);
              }
              myReader.close();
              System.out.println(output);
              
              
            } catch (FileNotFoundException e) {
              System.out.println("An error occurred.");
              e.printStackTrace();
            }

现在让我们修复你的错误/文体假通行证:

  1. 未能安全关闭资源。
  2. 未能指定字符集编码,使此代码依赖于操作系统(因此,这是一个错误,并且您无法测试 - 非常糟糕)
  3. 非常愚蠢的异常处理
private static final String HOMEDIR = "C:\\Users\\yourname\\Desktop\\";
public String fileParse(String filename) throws IOException {
    try (var s = new Scanner(new File(HOMEDIR + filename, StandardCharsets.UTF_8));
    StringBuilder out = new StringBuilder();
    for (String line = s.nextLine(); line != null; line = s.nextLine()) {
        out.append(line);
    }
    return line.toString(); 
}

一个名为的方法parseFile显然应该声明为throws IOException. 这是该方法应该做的事情所固有的。

然后再来一次,使用现代 API 和命名约定:

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

private static final Path HOME = Paths.get(System.getProperty("user.home"), "Desktop");
public String parseFile(String fileName) {
    return Files.readString(HOME.resolve(fileName));
}

看看那是多么的短和漂亮。单线!

注意:“文件”中的方法使用 UTF_8 作为默认值,而不是使用无用的“平台默认值”的旧东西。


推荐阅读