如何使用线程进行文件读/写?
一项家庭作业要求我实现一个程序,通过为每个文件启动一个新线程来计算一个或多个文件中的单词数(文件名在命令行上指定为参数)。
这是我的问题:run() 方法不能抛出 IOException,因为 Runnable 接口中的 run() 方法不会抛出 IOException。我通过将 File 和 Scanner 构造函数调用放入实现 Runnable 的类的构造函数中来绕过编译器的警告,但即使它现在编译得很好,我仍然感到阴暗,就像我在做一些不合规矩的事情。有什么想法吗?
import java.io.File;
import java.util.Scanner;
import java.io.FileNotFoundException;
import java.io.IOException;
public class WordCounter implements Runnable {
File inFile;
Scanner in;
int characters;
int words;
int lines;
int[] counted;
public WordCounter(String aFile) throws FileNotFoundException {
inFile = new File(aFile);
in = new Scanner(inFile);
counted = new int[3];
}
public int[] getTotals() {
return counted;
}
public void run() {
characters = 0;
words = 0;
lines = 0;
while (in.hasNextLine()) {
String thisLine = in.nextLine();
lines++;
Scanner line = new Scanner(thisLine);
while (line.hasNext()) {
String thisWord = line.next();
words++;
characters++; // because each call to line.next() strips a whitespace character
Scanner word = new Scanner(thisWord);
word.useDelimiter("");
while (word.hasNext()) {
char ch = word.next().charAt(0);
characters++;
}
}
}
counted[0] = characters;
counted[1] = words;
counted[2] = lines;
}
}
A homework assignment asks me to implement a program that counts the words in one or more files (filenames are specified as arguments on the command line) by starting a new thread for each file.
Here's my issue: the run() method can't throw an IOException, because the run() method in the Runnable interface doesn't throw one. I've gotten around the compiler's warnings by putting the File and Scanner constructor calls in the constructor of my class that implements Runnable, but even though it compiles fine now, I still feel shady somehow, like I am doing something not kosher. Any thoughts?
import java.io.File;
import java.util.Scanner;
import java.io.FileNotFoundException;
import java.io.IOException;
public class WordCounter implements Runnable {
File inFile;
Scanner in;
int characters;
int words;
int lines;
int[] counted;
public WordCounter(String aFile) throws FileNotFoundException {
inFile = new File(aFile);
in = new Scanner(inFile);
counted = new int[3];
}
public int[] getTotals() {
return counted;
}
public void run() {
characters = 0;
words = 0;
lines = 0;
while (in.hasNextLine()) {
String thisLine = in.nextLine();
lines++;
Scanner line = new Scanner(thisLine);
while (line.hasNext()) {
String thisWord = line.next();
words++;
characters++; // because each call to line.next() strips a whitespace character
Scanner word = new Scanner(thisWord);
word.useDelimiter("");
while (word.hasNext()) {
char ch = word.next().charAt(0);
characters++;
}
}
}
counted[0] = characters;
counted[1] = words;
counted[2] = lines;
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我认为一般的经验法则是尽可能接近抛出异常的位置来处理异常。是什么阻止您的可运行程序处理异常,而不是您的 main() 或任何创建可运行程序的内容?
我同意变量初始化通常最好在构造函数中完成,但是当使用可运行对象时,如果该构造发生在 run() 方法中,您将获得更好的性能。我特别谈论的是实际上需要一些时间来处理的变量; int[3] 无论是在构造函数还是在 run 方法中都不会产生影响,但 Scanner 和 File 可能取决于它们在初始化时执行的操作(例如,Scanner 是否缓冲文件的第一行?)。
I think a general rule of thumb would be to handle the exception as close to where it is thrown as possible. What is stopping your runnable from handling the exception instead of your main() or whatever is creating the runnables?
I agree that variable initialization is typically best done in the constructor, but when using runnables, you are going to get better performance if that construction takes place in your run() method. I am specifically talking about variables that actually take some time to process; the int[3] isnt going to make a difference whether its in your constructor or run method, but the Scanner and File might depending on what they do upon initialization (e.g., does Scanner buffer the first line of the file for example?).
在构造函数中初始化成员变量通常是一个很好的做法。我认为你做的是正确的事情,此外,我还将把
characters
、words
和lines
的初始化移到构造函数中。Initializing member variables in a constructor is generally good practice. I think you are doing the right thing, and furthermore, I would move the initializations of
characters
,words
, andlines
into the constructor as well.您可以静默异常,并中止线程内的文件操作。沉默异常是否是一个好主意取决于您想要做什么。
不过,我认为在构造函数中初始化文件并没有什么问题;如果你想尽早失败而不是等到以后失败,这是一个非常好的做法。
You can silent the Exception, and abort file operations inside the thread. Whether silencing the exception is a good idea or not depends on what you're attempting to do.
However, I think there is nothing wrong with initializing the file in the constructor; it's a perfectly good practice if you want to fail early instead of waiting until later.
如果问题是受检查的异常,那么常见的习惯做法是将其转换为 RuntimeException,如下所示:
基本上,您捕获、转换并重新抛出。 RuntimeException 未经检查,因此方法签名不需要声明它。
If the problem is the checked exception then a common idiom is to convert it to a RuntimeException, something like this:
Basically you catch, convert and rethrow. RuntimeException is unchecked so the method signature does not need to declare it.