为什么这个局部变量在java中等于null?

iaqfqrcu  于 2021-06-29  发布在  Java
关注(0)|答案(4)|浏览(398)

我的目标是拥有一个存储文件内容的字符串。我真的撕毁了从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搏斗,因为我不熟悉局部变量的范围。当我逐行连接到输出时,为什么输出什么都不打印?

jdg4fx2g

jdg4fx2g1#

按如下所示更改程序,使其按您的需要工作。这里,string的行为是当您创建一个新对象时,它总是将这些对象保留在字符串池中,并返回一个新的对象,因此您需要指定给现有的string对象来连接所有string对象。
当有多个连接时,总是建议使用stringbuilder。

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= output.concat(data);
          }
          myReader.close();
          System.out.println(output);

        } catch (FileNotFoundException e) {
          System.out.println("An error occurred.");
          e.printStackTrace();
        }
}

}

koaltpgm

koaltpgm2#

因为 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();
            }

现在让我们来修复你的虫子/枯草的假通行证:
无法安全关闭资源。
未能指定字符集编码,使此代码依赖于操作系统(因此,这是一个bug,而且是一个您无法测试的bug-非常糟糕)
非常愚蠢的异常处理

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));
}

你看那有多短多漂亮。一个班轮!
注意:'files'中的方法使用utf8作为默认值,而旧的方法使用无用的'platform default'。

oogrdqng

oogrdqng3#

必须使用“concat”的返回值。
参考 .concat Java文档。它提供了以下内容:
示例:

"cares".concat("s") returns "caress"
"to".concat("get").concat("her") returns "together"

这不是一个无效的方法。它是一个返回连接字符串结果的方法。所以在这种情况下,你应该:

while (myReader.hasNextLine()) {
    String data = myReader.nextLine();
    output=output.concat(data);
}

虽然为了提高效率,我建议使用 StringBuilder ,因为您经常连接:

StringBuilder str = new StringBuilder();
while (myReader.hasNextLine()) {
    String data = myReader.nextLine();
    str.append(data);
}
myReader.close();
System.out.println(str.toString());

或者最好是打印循环内的每一行,而不是打印循环外的每一行,这将(在大多数情况下)保持文件的原始格式:

Scanner myReader = new Scanner(myObj);
while (myReader.hasNextLine()) {
    String data = myReader.nextLine();
    System.out.println(data);
}
myReader.close();
hmtdttj4

hmtdttj44#

而不是 concat ,你通常会写 += 要附加到字符串:

output += data;

然而,两者 += 以及 concat (如另一个答案所示,一旦修复)在一个循环中是缓慢的。更有效的方法是使用 StringBuilder :

final StringBuilder sb = new StringBuilder();

while (myreader.hasNextLine()) {
    sb.append(myreader.readNextLine());
}

System.out.println(sb);
// or:
final String output = sb.toString();
System.out.println(output);

但这里其实没有这个必要:直接打印行:

while (myReader.hasNextLine()) {
    System.out.println(myReader.nextLine());
}

相关问题