我想读取一个包含空格分隔值的文本文件。值是整数。如何读取并将其放入数组列表?
这是文本文件内容的示例:
1 62 4 55 5 6 77
我想将它包含在arraylist中[1, 62, 4, 55, 5, 6, 77]
。如何用Java做到这一点?
Answers:
您可以用来Files#readAllLines()
将文本文件的所有行都放入List<String>
。
for (String line : Files.readAllLines(Paths.get("/path/to/file.txt"))) {
// ...
}
教程:基本I / O>文件I / O>读取,写入和创建文本文件
您可以用来基于正则表达式String#split()
拆分aString
部分。
for (String part : line.split("\\s+")) {
// ...
}
您可以使用Integer#valueOf()
将转换String
为Integer
。
Integer i = Integer.valueOf(part);
您可以使用List#add()
将元素添加到中List
。
numbers.add(i);
教程:接口>列表接口
因此,简而言之(假设文件没有空行,也没有尾随/前导空格)。
List<Integer> numbers = new ArrayList<>();
for (String line : Files.readAllLines(Paths.get("/path/to/file.txt"))) {
for (String part : line.split("\\s+")) {
Integer i = Integer.valueOf(part);
numbers.add(i);
}
}
如果您碰巧已经使用Java 8,那么您甚至可以为此使用Stream APIFiles#lines()
。
List<Integer> numbers = Files.lines(Paths.get("/path/to/test.txt"))
.map(line -> line.split("\\s+")).flatMap(Arrays::stream)
.map(Integer::valueOf)
.collect(Collectors.toList());
Java 1.5引入了Scanner类,用于处理来自文件和流的输入。
它用于从文件获取整数,如下所示:
List<Integer> integers = new ArrayList<Integer>();
Scanner fileScanner = new Scanner(new File("c:\\file.txt"));
while (fileScanner.hasNextInt()){
integers.add(fileScanner.nextInt());
}
不过请检查API。还有许多其他选项可用于处理不同类型的输入源,不同的定界符和不同的数据类型。
此示例代码向您展示了如何使用Java读取文件。
import java.io.*;
/**
* This example code shows you how to read file in Java
*
* IN MY CASE RAILWAY IS MY TEXT FILE WHICH I WANT TO DISPLAY YOU CHANGE WITH YOUR OWN
*/
public class ReadFileExample
{
public static void main(String[] args)
{
System.out.println("Reading File from Java code");
//Name of the file
String fileName="RAILWAY.txt";
try{
//Create object of FileReader
FileReader inputFile = new FileReader(fileName);
//Instantiate the BufferedReader Class
BufferedReader bufferReader = new BufferedReader(inputFile);
//Variable to hold the one line data
String line;
// Read file line by line and print on the console
while ((line = bufferReader.readLine()) != null) {
System.out.println(line);
}
//Close the buffer reader
bufferReader.close();
}catch(Exception e){
System.out.println("Error while reading file line by line:" + e.getMessage());
}
}
}
查看此示例,然后尝试自己做:
import java.io.*;
public class ReadFile {
public static void main(String[] args){
String string = "";
String file = "textFile.txt";
// Reading
try{
InputStream ips = new FileInputStream(file);
InputStreamReader ipsr = new InputStreamReader(ips);
BufferedReader br = new BufferedReader(ipsr);
String line;
while ((line = br.readLine()) != null){
System.out.println(line);
string += line + "\n";
}
br.close();
}
catch (Exception e){
System.out.println(e.toString());
}
// Writing
try {
FileWriter fw = new FileWriter (file);
BufferedWriter bw = new BufferedWriter (fw);
PrintWriter fileOut = new PrintWriter (bw);
fileOut.println (string+"\n test of read and write !!");
fileOut.close();
System.out.println("the file " + file + " is created!");
}
catch (Exception e){
System.out.println(e.toString());
}
}
}
只是为了好玩,这是我在一个真实项目中可能要做的事情,在该项目中,我已经在使用我所有喜欢的库(在本例中为Guava,以前称为Google Collections)。
String text = Files.toString(new File("textfile.txt"), Charsets.UTF_8);
List<Integer> list = Lists.newArrayList();
for (String s : text.split("\\s")) {
list.add(Integer.valueOf(s));
}
好处:自己需要维护的代码很少(与this相比)。编辑:尽管值得注意的是,在这种情况下tschaible的Scanner解决方案没有更多的代码!
缺点:显然,您可能不想为此添加新的库依赖项。(然后再次,您在项目中不使用番石榴会很傻。
将Apache Commons(IO和Lang)用于简单/常见的事情。
进口:
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.ArrayUtils;
码:
String contents = FileUtils.readFileToString(new File("path/to/your/file.txt"));
String[] array = ArrayUtils.toArray(contents.split(" "));
做完了
使用Java 7通过NIO.2读取文件
导入以下软件包:
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
这是读取文件的过程:
Path file = Paths.get("C:\\Java\\file.txt");
if(Files.exists(file) && Files.isReadable(file)) {
try {
// File reader
BufferedReader reader = Files.newBufferedReader(file, Charset.defaultCharset());
String line;
// read each line
while((line = reader.readLine()) != null) {
System.out.println(line);
// tokenize each number
StringTokenizer tokenizer = new StringTokenizer(line, " ");
while (tokenizer.hasMoreElements()) {
// parse each integer in file
int element = Integer.parseInt(tokenizer.nextToken());
}
}
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
要一次读取文件的所有行:
Path file = Paths.get("C:\\Java\\file.txt");
List<String> lines = Files.readAllLines(file, StandardCharsets.UTF_8);
到目前为止给出的所有答案都包括:逐行读取文件,将a作为行String
,然后处理String
。
毫无疑问,这是最容易理解的方法,并且如果文件很短(例如,成千上万行),那么从效率上来说也可以接受。但是,如果文件很长,则这样做的效率很低,原因有二:
String
,一次是处理。String
为每行构造一个新行,然后在移至下一行时将其丢弃。垃圾收集器最终将不得不处置所有String
不再需要的所有这些对象。在你之后有人要清理。如果您关心速度,那么最好先读取一个数据块,然后逐字节处理而不是逐行处理。每次到达数字末尾时,都将其添加到List
要构建的数字中。
它会出来像这样:
private List<Integer> readIntegers(File file) throws IOException {
List<Integer> result = new ArrayList<>();
RandomAccessFile raf = new RandomAccessFile(file, "r");
byte buf[] = new byte[16 * 1024];
final FileChannel ch = raf.getChannel();
int fileLength = (int) ch.size();
final MappedByteBuffer mb = ch.map(FileChannel.MapMode.READ_ONLY, 0,
fileLength);
int acc = 0;
while (mb.hasRemaining()) {
int len = Math.min(mb.remaining(), buf.length);
mb.get(buf, 0, len);
for (int i = 0; i < len; i++)
if ((buf[i] >= 48) && (buf[i] <= 57))
acc = acc * 10 + buf[i] - 48;
else {
result.add(acc);
acc = 0;
}
}
ch.close();
raf.close();
return result;
}
上面的代码假定这是ASCII(尽管可以很容易地对其他编码进行调整),并且不是数字的任何内容(尤其是空格或换行符)都代表数字之间的边界。它还假设文件以非数字结尾(实际上,最后一行以换行结尾),不过,可以再次调整它以处理非数字结尾的情况。
它比作为回答这个问题的任何基于方法的速度快得多String
。对于这个问题中的一个非常相似的问题,有详细的调查。您将看到,如果您想沿多线程行前进,则有可能进一步改进它。