澄清几件事:
FileWriter fw = new FileWriter("colon.arff", true);
在您的 FileWriter 声明中,您使用布尔附加标志作为 true,它可以附加到提供的文件。考虑到您希望写入文件的数据与正在读取的文件格式完全相同,我不确定这是否真的是您想要的。您不希望将任何内容附加到该文件,从而扭曲原始内容格式。
toWrite += line;
在循环中进行这样的连接从来都不是一个好主意(是的,为了简单的事情和演示目的,我仍然不时这样做)。循环外的简单连接很好,因为编译器无论如何都会使用 StringBuilder ,如果它认为它会更有益的话。最好使用 StringBuilder 类,原因如下:
在 Java 中,字符串对象是不可变的,这意味着一旦创建,就无法更改它。因此,当我们将一个字符串与另一个字符串连接时,会创建一个新字符串,并将旧字符串标记为垃圾收集器。假设我们需要连接一百万个字符串。然后,我们将创建 100 万个额外的字符串,这些字符串最终将被垃圾回收。
为了解决这个问题,使用了 StringBuilder 类。它就像一个可变的 String 对象一样工作。 StringBuilder#append() 方法有助于避免字符串连接中所需的所有复制。要在您的情况下使用 StringBuilder,您可以在 while 循环上方声明构建器:
StringBuilder toWrite = new StringBuilder();
然后在循环内:
toWrite.append(line).append(System.lineSeparator());
注意到额外的append(System.lineSeparator())了吗?当您想使用 FileWriter 将完成的行写入文件时,您需要添加换行符(“\n”或“\r\n”,具体取决于操作系统),以便下一行将需要写入将在文件中的新行上。在这种情况下,您实际上是在构建将在一次写入时写入文件的字符串,因此如果附加的字符串需要在文件中的新行上,则还需要附加换行符。 System.lineSeparator() 方法返回依赖于操作系统的换行符。
下面的代码将满足您的要求:
// Demo data to replace in file...
String[] newData = {"4,2,13,1,4,2,0",
"1,3,3,5,2,4,1",
"7,7,2,1,5,8,1"};
// 'Try With Resourses' is used here to auto-close the reader and writer.
try (BufferedReader reader = new BufferedReader(new FileReader("aa.txt"));
FileWriter fw = new FileWriter("colon.arff")) {
String ls = System.lineSeparator(); // The Line Break use by OS.
StringBuilder toWrite = new StringBuilder(); // A String builder object
int skip = 0; // Used for skipping old file data for placement of the new data
String line = null; // Use to hold file lines read (one at a time)
// Start reading file...
while ((line = reader.readLine()) != null) {
/* If skip is greater than 0 then read in next line and
decrement skip by 1. This is used in case the data
in file contains more rows of data than what you are
replacing. */
if (skip > 0) {
skip--;
continue;
}
// Append the file line read into the StringBuilder object
toWrite.append(line).append(ls);
// If the file line read equals "@data"
if (line.trim().equals("@data")) {
/* Append the new data to the toWrite variable here,
for example: if the new data was in a string array
named newData (see above declaration)... */
for (int i = 0; i < newData.length; i++) {
/* Perform new data Validation...
Make sure all values are string representations
of numerical data and that the 7th column of data
is no less than 0 and no more than 1. */
String[] ndParts = newData[i].split("\\s{0,},\\s{0,}"); // Split the current data row
boolean isValid = true; // flag
for (int v = 0; v < ndParts.length; v++) {
if (!ndParts[v].matches("\\d+") ||
(v == 6 && (!ndParts[v].equals("0") &&
!ndParts[v].equals("1")))) {
isValid = false;
System.err.println("Invalid numerical value supplied on Row " +
(i+1) + " in Column " + (v+1) + ". (Data: " + newData[i] + ")" +
ls + "Not writing data line to file!");
break;
}
}
/* If the current new data row is valid then append
it to the build and increment skip by 1. */
if (isValid) {
toWrite.append(newData[i]).append(ls);
skip++;
}
}
}
}
// Write the entire built string to file.
fw.write(toWrite.toString());
}
catch (FileNotFoundException ex) {
System.err.println(ex.getMessage());
}
catch (IOException ex) {
System.err.println(ex.getMessage());
}