为什么这个局部变量在Java中等于null?
我的目标是拥有一个存储文件内容的字符串。我从W3学校()撕下了读取文件的算法,只是做了一些改变为什么这个局部变量在Java中等于null?,java,variables,local,Java,Variables,Local,我的目标是拥有一个存储文件内容的字符串。我从W3学校()撕下了读取文件的算法,只是做了一些改变 public class Fileparser { public void fileParse(String filename) { try { File myObj = new File("C:\\Users\\(myname)\\Desktop\\" + filename);
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搏斗,因为我不熟悉局部变量的范围。当我逐行连接到输出时,为什么输出不打印?必须使用“concat”的返回值
请参阅.concat
javadocs。它提供了以下内容:
示例:
"cares".concat("s") returns "caress"
"to".concat("get").concat("her") returns "together"
尽管为了提高效率,我还是建议使用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();
必须使用“concat”的返回值
请参阅.concat
javadocs。它提供了以下内容:
示例:
"cares".concat("s") returns "caress"
"to".concat("get").concat("her") returns "together"
尽管为了提高效率,我还是建议使用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();
您通常会编写
+=
来附加到字符串,而不是concat
:
output += data;
但是,循环中的+=
和concat
(如另一个答案所示,一旦修复)都很慢。更有效的方法是使用:
但实际上这里不需要这样做:直接打印行即可:
while (myReader.hasNextLine()) {
System.out.println(myReader.nextLine());
}
您通常会编写
+=
来附加到字符串,而不是concat
:
output += data;
但是,循环中的+=
和concat
(如另一个答案所示,一旦修复)都很慢。更有效的方法是使用:
但实际上这里不需要这样做:直接打印行即可:
while (myReader.hasNextLine()) {
System.out.println(myReader.nextLine());
}
因为
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-非常糟糕)
非常愚蠢的异常处理
名为parseFile
的方法显然应该声明为抛出IOException
。这是该方法的固有功能
然后,对于encore,使用现代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作为默认值,而旧的方法使用无用的“平台默认值”。因为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-非常糟糕)
非常愚蠢的异常处理
名为parseFile
的方法显然应该声明为抛出IOException
。这是该方法的固有功能
然后,对于encore,使用现代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作为默认值,而旧的方法使用无用的“平台默认值”。如下图所示更改程序,使其按需工作。
这里,字符串的行为是当您创建一个新对象时,它总是将这些对象保留在字符串池中,并返回一个新的对象,因此您需要指定给现有的字符串对象以连接所有字符串对象
当具有多个连接时,始终建议使用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();
}
}
}如下图所示更改程序,使其按照您的需要工作。
这里,字符串的行为是当您创建一个新对象时,它总是将这些对象保留在字符串池中,并返回一个新的对象,因此您需要指定给现有的字符串对象以连接所有字符串对象
当具有多个连接时,始终建议使用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();
}
}
}声明:“String
s是常量;它们的值在创建后不能更改。”因此,返回一个新的String
,表示连接。将此行替换为output=output.concat(数据)代码>。声明:“String
s是常量;它们的值在创建后不能更改。”因此,返回一个新的String
,表示连接。将此行替换为output=output.concat(数据)代码>。