Java 将 .txt 文件读入二维数组
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22185683/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Read .txt file into 2D Array
提问by BimmerM3
There are a few of these topics out there, but this problem has a slight twist that makes it different.
有一些这样的主题,但这个问题有一个轻微的转折,使它与众不同。
I'm focused on only half of a larger problem. I'm sure many of you are aware of the magic square problem.
我只关注一个更大问题的一半。我相信你们很多人都知道幻方问题。
Prompt:
Assume a file with lines and numbers on each line like the square shown. Write a program that reads info into a two dimensional array of intS. The program should determine if the matrix is a magic square or not.
提示:
假设一个文件每行都有行和数字,如图所示。编写一个程序,将信息读入 intS 的二维数组。程序应该确定矩阵是否是幻方。
Working Solution:
工作解决方案:
public static int[][] create2DIntMatrixFromFile(String filename) throws Exception {
int[][] matrix = {{1}, {2}};
File inFile = new File(filename);
Scanner in = new Scanner(inFile);
int intLength = 0;
String[] length = in.nextLine().trim().split("\s+");
for (int i = 0; i < length.length; i++) {
intLength++;
}
in.close();
matrix = new int[intLength][intLength];
in = new Scanner(inFile);
int lineCount = 0;
while (in.hasNextLine()) {
String[] currentLine = in.nextLine().trim().split("\s+");
for (int i = 0; i < currentLine.length; i++) {
matrix[lineCount][i] = Integer.parseInt(currentLine[i]);
}
lineCount++;
}
return matrix;
}
public static boolean isMagicSquare(int[][] square) {
return false;
}
Here is my (old) code for reading info from a text file into a 2D array:
这是我的(旧)代码,用于将文本文件中的信息读取到二维数组中:
public static int[][] create2DIntMatrixFromFile(String filename) throws Exception {
int[][] matrix = {{1}, {2}};
File inFile = new File(filename);
Scanner in = new Scanner(inFile);
in.useDelimiter("[/n]");
String line = "";
int lineCount = 0;
while (in.hasNextLine()) {
line = in.nextLine().trim();
Scanner lineIn = new Scanner(line);
lineIn.useDelimiter("");
for (int i = 0; lineIn.hasNext(); i++) {
matrix[lineCount][i] = Integer.parseInt(lineIn.next());
lineIn.next();
}
lineCount++;
}
return matrix;
}
public static boolean isMagicSquare(int[][] square) {
return false;
}
And here is the text file I am reading from. It is in the shape of a 9x9 2D array, but the program must accommodate an array of ambiguous size.
这是我正在阅读的文本文件。它是一个 9x9 二维数组的形状,但程序必须容纳一个大小不明确的数组。
37 48 59 70 81 2 13 24 35
36 38 49 60 71 73 3 14 25
26 28 39 50 61 72 74 4 15
16 27 29 40 51 62 64 75 5
6 17 19 30 41 52 63 65 76
77 7 18 20 31 42 53 55 66
67 78 8 10 21 32 43 54 56
57 68 79 9 11 22 33 44 46
47 58 69 80 1 12 23 34 45
There are two spaces proceeding each line on purpose.
每行有两个空格是故意的。
Before I state the exact problem, this is a homework template so the method declaration and variable initialization was pre-determined.
在我陈述确切的问题之前,这是一个作业模板,因此方法声明和变量初始化是预先确定的。
I'm not positive that the method even correctly creates a 2D Array from the file because I can't run it yet. The issue is that for some reason "matrix" was initialized with 1 column and 2 rows. For what reason I'm not sure, but in order to fill an array with the numbers from the file I need to create a 2D array with dimensions equal to the number of values in a line.
我不确定该方法甚至从文件中正确创建了一个二维数组,因为我还不能运行它。问题是由于某种原因,“矩阵”被初始化为 1 列和 2 行。出于什么原因我不确定,但为了用文件中的数字填充数组,我需要创建一个二维数组,其维度等于一行中的值数。
I previously had written code to create a new 2D array
我以前写过代码来创建一个新的二维数组
int[line.length()][line.length()]
but it created a 36x36 array because that's how many individual characters are in one line. I have a feeling it's as simple as looping through the first line and having a counter keep track of each sequence of numbers separated by a zero.
但它创建了一个 36x36 数组,因为这是一行中有多少个字符。我有一种感觉就像遍历第一行并让计数器跟踪每个由零分隔的数字序列一样简单。
To me, that solution seems too inefficient and time consuming just to find the dimensions of the new array. What's the best way to accomplish this? Without using ArrayLists as I have to rewrite this program after using ArrayLists.
对我来说,这个解决方案似乎太低效和太耗时,只是为了找到新数组的维度。实现这一目标的最佳方法是什么?不使用 ArrayLists,因为我必须在使用 ArrayLists 后重写这个程序。
回答by David Kopczyk
You're close, but change your while loop to look like the following:
您已经接近了,但将您的 while 循环更改为如下所示:
while (in.hasNextLine()) {
Scanner lineIn = new Scanner(line);
//The initial case - this first line is used to determine the size of the array
if(lineIn.hasNext()) {
//Create a String array by splitting by spaces
String[] s = lineIn.nextLine().split(" ");
//Reinitialize the array to hold all of your subarrays
matrix = new int[s.length];
for (int i = 0; i < s.length; i++) {
//Reinitialize each subarray to hold the numbers
matrix[i] = new int[i];
//Finally, parse your data from the String array
matrix[0][i] = Integer.parseInt(s[i]);
}
}
//Repeat the steps now that all of your arrays have been initialized
for (int j = 1; j < matrix.length; j++) {
String[] s = lineIn.nextLine().split(" ");
for (int i = 0; i < s.length; i++) {
matrix[j][i] = Integer.parseInt(s[i]);
}
}
}
The biggest change that you can make to make this easier on yourself is to get your numbers line-by-line. With each line you get, it's easy to then split it into a String array so that you can parse each number separately. Doing it this way you can then get the full length of the array all at once without having to have troublesome counters.
为了让自己更轻松,您可以做出的最大改变是逐行获取您的数字。对于您获得的每一行,很容易将其拆分为一个 String 数组,以便您可以分别解析每个数字。这样做之后,您就可以一次获得数组的全部长度,而无需麻烦的计数器。
回答by Jerry101
First, test out the Scanner results. I don't think those delimiters will work. (BTW, Scanner's nextInt()method is handy.)
首先,测试扫描仪的结果。我不认为这些分隔符会起作用。(顺便说一句,扫描仪的nextInt()方法很方便。)
If you can assume the input is a square matrix, scanning the first line will reveal how many integers it contains. Then you can (re)allocate the arrays. Then process all the lines, including the first line that you already scanned.
如果您可以假设输入是一个方阵,扫描第一行将显示它包含多少个整数。然后你可以(重新)分配数组。然后处理所有行,包括您已经扫描的第一行。
Then you can set matrix = new int[n][n];
然后你可以设置 matrix = new int[n][n];
回答by Mr. Polywhirl
I produced the following 2D array from the file you provided:
我从您提供的文件中生成了以下二维数组:
37 | 48 | 59 | 70 | 81 | 2 | 13 | 24 | 35
----+----+----+----+----+----+----+----+----
36 | 38 | 49 | 60 | 71 | 73 | 3 | 14 | 25
----+----+----+----+----+----+----+----+----
26 | 28 | 39 | 50 | 61 | 72 | 74 | 4 | 15
----+----+----+----+----+----+----+----+----
16 | 27 | 29 | 40 | 51 | 62 | 64 | 75 | 5
----+----+----+----+----+----+----+----+----
6 | 17 | 19 | 30 | 41 | 52 | 63 | 65 | 76
----+----+----+----+----+----+----+----+----
77 | 7 | 18 | 20 | 31 | 42 | 53 | 55 | 66
----+----+----+----+----+----+----+----+----
67 | 78 | 8 | 10 | 21 | 32 | 43 | 54 | 56
----+----+----+----+----+----+----+----+----
57 | 68 | 79 | 9 | 11 | 22 | 33 | 44 | 46
----+----+----+----+----+----+----+----+----
47 | 58 | 69 | 80 | 1 | 12 | 23 | 34 | 45
The array figures out the size of the square when it reads the first line of the file. This is very dynamic. Its works as long as the input file is a perfect square. I have no further error handling.
该数组在读取文件的第一行时计算出正方形的大小。这是非常动态的。只要输入文件是一个完美的正方形,它就可以工作。我没有进一步的错误处理。
Here is a simple approach which should adhere to your guidelines.
这是一个简单的方法,它应该符合您的指导方针。
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
public class ReadMagicSquare {
public static int[][] create2DIntMatrixFromFile(String filename) throws Exception {
int[][] matrix = null;
// If included in an Eclipse project.
InputStream stream = ClassLoader.getSystemResourceAsStream(filename);
BufferedReader buffer = new BufferedReader(new InputStreamReader(stream));
// If in the same directory - Probably in your case...
// Just comment out the 2 lines above this and uncomment the line
// that follows.
//BufferedReader buffer = new BufferedReader(new FileReader(filename));
String line;
int row = 0;
int size = 0;
while ((line = buffer.readLine()) != null) {
String[] vals = line.trim().split("\s+");
// Lazy instantiation.
if (matrix == null) {
size = vals.length;
matrix = new int[size][size];
}
for (int col = 0; col < size; col++) {
matrix[row][col] = Integer.parseInt(vals[col]);
}
row++;
}
return matrix;
}
public static void printMatrix(int[][] matrix) {
String str = "";
int size = matrix.length;
if (matrix != null) {
for (int row = 0; row < size; row++) {
str += " ";
for (int col = 0; col < size; col++) {
str += String.format("%2d", matrix[row][col]);
if (col < size - 1) {
str += " | ";
}
}
if (row < size - 1) {
str += "\n";
for (int col = 0; col < size; col++) {
for (int i = 0; i < 4; i++) {
str += "-";
}
if (col < size - 1) {
str += "+";
}
}
str += "\n";
} else {
str += "\n";
}
}
}
System.out.println(str);
}
public static void main(String[] args) {
int[][] matrix = null;
try {
matrix = create2DIntMatrixFromFile("square.txt");
} catch (Exception e) {
e.printStackTrace();
}
printMatrix(matrix);
}
}
This approach is more refined and optimized.
这种方法更加精细和优化。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class ReadMagicSquare {
private int[][] matrix;
private int size = -1;
private int log10 = 0;
private String numberFormat;
public ReadMagicSquare(String filename) {
try {
readFile(filename);
} catch (IOException e) {
e.printStackTrace();
}
}
public void readFile(String filename) throws IOException {
// If included in an Eclipse project.
InputStream stream = ClassLoader.getSystemResourceAsStream(filename);
BufferedReader buffer = new BufferedReader(new InputStreamReader(stream));
// If in the same directory - Probably in your case...
// Just comment out the 2 lines above this and uncomment the line
// that follows.
//BufferedReader buffer = new BufferedReader(new FileReader(filename));
String line;
int row = 0;
while ((line = buffer.readLine()) != null) {
String[] vals = line.trim().split("\s+");
// Lazy instantiation.
if (matrix == null) {
size = vals.length;
matrix = new int[size][size];
log10 = (int) Math.floor(Math.log10(size * size)) + 1;
numberFormat = String.format("%%%dd", log10);
}
for (int col = 0; col < size; col++) {
matrix[row][col] = Integer.parseInt(vals[col]);
}
row++;
}
}
@Override
public String toString() {
StringBuffer buff = new StringBuffer();
if (matrix != null) {
for (int row = 0; row < size; row++) {
buff.append(" ");
for (int col = 0; col < size; col++) {
buff.append(String.format(numberFormat, matrix[row][col]));
if (col < size - 1) {
buff.append(" | ");
}
}
if (row < size - 1) {
buff.append("\n");
for (int col = 0; col < size; col++) {
for (int i = 0; i <= log10 + 1; i++) {
buff.append("-");
}
if (col < size - 1) {
buff.append("+");
}
}
buff.append("\n");
} else {
buff.append("\n");
}
}
}
return buff.toString();
}
public static void main(String[] args) {
ReadMagicSquare square = new ReadMagicSquare("square.txt");
System.out.println(square.toString());
}
}
回答by YoYo
With Java 8 and it's Streams:
使用 Java 8 和它的Streams:
static public int[][] create2DIntMatrixFromFile(Path path) throws IOException {
return Files.lines(path)
.map((l)->l.trim().split("\s+"))
.map((sa)->Stream.of(sa).mapToInt(Integer::parseInt).toArray())
.toArray(int[][]::new);
}
This is just for the 'reading' part of the question.
这仅适用于问题的“阅读”部分。

