我正在制作一个IRC机器人,我有一个文本文件,其中包含每个用户在新的单独行上的引用。
例如: 我喜欢豌豆 - user1 我喜欢西红柿 - user2 我喜欢西红柿里面的豌豆 - user1
我希望有一种方法可以做到这一点,如果有人输入"!引用用户"它将从该用户随机引用并将其发送到该频道。这是我到目前为止的代码:
if (messageIC.startsWith("!quote")) {
String user = message.substring(7);
java.io.FileInputStream fs = null;
try {
fs = new java.io.FileInputStream("C:/Users/Quibbles/Documents/ampersand/quotes.txt");
} catch (FileNotFoundException ex) {
Logger.getLogger(Ampersand.class.getName()).log(Level.SEVERE, null, ex);
}
BufferedReader br = new BufferedReader(new InputStreamReader(fs));
ArrayList<String> array = new ArrayList<>();
String line;
try {
while((line = br.readLine()) != null)
array.add(br.readLine());
} catch (IOException ex) {
Logger.getLogger(Ampersand.class.getName()).log(Level.SEVERE, null, ex);
}
// variable so that it is not re-seeded every call.
Random rand = new Random();
// nextInt is exclusive. Should be good with output for array.
int randomIndex = rand.nextInt(array.size());
if ((array.get(randomIndex).contains(user))) {
sendMessage(channel, array.get(randomIndex));
}
}
然而,这不起作用。机器人没有吐出任何东西。我做错了什么?
答案 0 :(得分:1)
有些事情看起来可能会导致问题乍一看:
(我假设&#34; C:/Users/Quibbles/Documents/ampersand/quotes.txt"包含所有用户的引用。)< /子>
首先,如果您只是在寻找一个用户,请不要将所有用户的所有引号都放入ArrayList<String> array
。这样,当您从列表中选择一个随机值时,您可以确定它将从指定用户返回一些内容(或为空)。
其次,正如您在评论中看到的那样,构建Random
的实例是一项相当昂贵的操作,但将其置于一个变量中,使得每次调用都不会停止它被重新播种,因为它实际上正在被重新实例化。你应该把它放在方法之外,所以它不是一个不断创建和销毁的局部变量。
第三,你在每次迭代中都会调用br.readLine()
两次,这会跳过行。由于您已经调用过一次并将其分配给line
,因此只需使用line
。
请改为尝试:
// ... somewhere in the actual class, *not* inside a method ...
private static Random rand = new Random();
// ...
// ... the rest here will be where it was, *inside* the method
if (messageIC.startsWith("!quote")) {
String user = message.substring(7);
java.io.FileInputStream fs = null;
try {
fs = new java.io.FileInputStream("C:/Users/Quibbles/Documents/ampersand/quotes.txt");
} catch (FileNotFoundException ex) {
Logger.getLogger(Ampersand.class.getName()).log(Level.SEVERE, null, ex);
}
BufferedReader br = new BufferedReader(new InputStreamReader(fs));
ArrayList<String> array = new ArrayList<String>();
String line;
try {
while ((line = br.readLine()) != null) {
if (line.contains(user)) {
array.add(br.readLine());
}
}
} catch (IOException ex) {
Logger.getLogger(Ampersand.class.getName()).log(Level.SEVERE, null, ex);
}
// `rand` will now refer to the class variable, located outside of the method
if (!array.isEmpty()) {
// nextInt is exclusive. Should be good with output for array.
sendMessage(channel, array.get(rand.nextInt(array.size())));
}
}
此外,如果您说原始代码“无法正常工作”,那么确切地知道出了什么问题会很有帮助。您是否尝试过调试或查看是否找到了用户的引用? 这样,我们将能够帮助您确切地解决出错的问题。
如果找到用户是问题,如果我们使用&#34; quotes.txt&#34;的常规格式,也可能会有所帮助。
无论如何,我希望这有帮助。 :)
答案 1 :(得分:0)
您可以使用以下代码替换代码的前半部分:
List<String> array = Files.readAllLines(
Paths.get(System.getProperty("user.home"),
"Documents", "ampersand", "quotes.txt"),
Charset.defaultCharset());
您的异常处理需要改进。如果你无法读取文件,继续使用该方法是没有意义的,对吧?因此,要么将throws IOException
添加到包含方法的签名中,要么执行以下操作:
try {
List<String> array = Files.readAllLines(
Paths.get(System.getProperty("user.home"),
"Documents", "ampersand", "quotes.txt"),
Charset.defaultCharset());
// Choose quote here
} catch (IOException e) {
// Can't continue if we can't read the quotes file.
throw new RuntimeException(e);
}
您想要来自特定用户的随机引用,而不仅仅是文件中的随机行。因此,您应该将随机值仅应用于所需用户的行:
try {
List<String> array = Files.readAllLines(
Paths.get(System.getProperty("user.home"),
"Documents", "ampersand", "quotes.txt"),
Charset.defaultCharset());
// Discard lines from other users
Iterator<String> i = array.iterator();
while (i.hasNext()) {
if (!i.next().endsWith(" - " + user)) {
i.remove();
}
}
// Important: Do not keep creating a new Random instance. Instead,
// create one instance and keep it in a field of your class.
int randomIndex = random.nextInt(array.size());
sendMessage(channel, array.get(randomIndex));
} catch (IOException e) {
// Can't continue if we can't read the quotes file.
throw new RuntimeException(e);
}
在Java 8中,您可以使用Stream缩短时间:
Path quotesFile = Paths.get(System.getProperty("user.home"),
"Documents", "ampersand", quotes.txt");
try (Stream<String> lines =
Files.lines(quotesFile, Charset.defaultCharset())) {
String[] array = lines.filter(line -> line.endsWith(" - " + user))
.toArray(String[]::new);
int randomIndex = random.nextInt(array.length);
sendMessage(channel, array[randomIndex]);
} catch (IOException e) {
// Can't continue if we can't read the quotes file.
throw new RuntimeException(e);
}
Stream是一个try-with-resources语句,因为它是一个支持I / O的Stream,这意味着它从I / O操作(特别是读取文件)中提供其值。