Java:如何读取文本文件
我想读取包含空格分隔值的文本文件。 值是整数。 我怎样才能读取它,并把它放在一个数组列表中?
这是一个文本文件内容的例子:
1 62 4 55 5 6 77
我想把它列入一个数组列表中[1, 62, 4, 55, 5, 6, 77]
1,62,4,55,5,6,77 [1, 62, 4, 55, 5, 6, 77]
。 我怎样才能在Java中做到这一点?
您可以使用Files#readAllLines()
将文本文件的所有行转换为List<String>
。
for (String line : Files.readAllLines(Paths.get("/path/to/file.txt"))) { // ... }
教程: 基本I / O>文件I / O>读取,写入和创build文本文件
您可以使用String#split()
根据正则expression式在部分中分割String
。
for (String part : line.split("\\s+")) { // ... }
教程: 数字和string>string>操作string中的字符
您可以使用Integer#valueOf()
将String
转换为Integer
。
Integer i = Integer.valueOf(part);
教程: 数字和string>string>数字和string之间的转换
您可以使用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 API进行操作,从Files#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 8stream处理数据
Java 1.5引入了Scanner类来处理来自文件和stream的input。
它用于从文件中获取整数,看起来像这样:
List<Integer> integers = new ArrayList<Integer>(); Scanner fileScanner = new Scanner(new File("c:\\file.txt")); while (fileScanner.hasNextInt()){ integers.add(fileScanner.nextInt()); }
虽然检查API。 处理不同types的input源,不同的分隔符和不同的数据types有更多的select。
这个示例代码展示了如何在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)); }
好处:没有太多自己的代码来维护(与此相反)。 编辑 :虽然值得注意的是,在这种情况下, tschaible的扫描仪解决scheme没有任何更多的代码!
缺点:你显然可能不想为此添加新的库依赖关系。 (再次,你会愚蠢的不要在你的项目中使用番石榴.-)
使用Apache Commons (IO和Lang)进行简单/常见的事情。
import:
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);
到目前为止给出的所有答案都涉及到逐行读取文件,将该行作为String
,然后处理String
。
毫无疑问,这是理解的最简单的方法,如果文件相当短(比如说成千上万行),在效率方面也是可以接受的。 但是,如果文件很长 ,这是一个非常低效的方法,原因有两个:
- 每个字符被处理两次,一次构build
String
,一次处理它。 - 如果文件中有很多行,垃圾收集器将不会成为你的朋友。 您正在为每一行构build一个新的
String
,然后在移动到下一行时将其丢弃。 垃圾回收器最终必须处理所有这些不再需要的String
对象。 有人需要清理。
如果你关心速度,读取数据块然后逐字节处理而不是逐行处理会更好。 每当你到一个数字的结尾,你把它添加到你正在build立的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(尽pipe可以很容易地对其他编码进行调整),并且任何不是数字(特别是空格或换行符)的数字都表示数字之间的边界。 它还假设文件以非数字结尾(实际上,最后一行以换行符结束),但是可以调整它来处理不是的情况。
它比任何基于String
的方法都要快得多 ,这也是对这个问题的答案。 在这个问题上有一个非常类似的问题的详细调查。 你会看到那里有进一步改进它的可能性,如果你想要去multithreading的话。
读取文件然后做任何你想要的java8 Files.lines(Paths.get(“c://lines.txt”))。collect(Collectors.toList());