【问题标题】:Read .txt file into 2D Array将 .txt 文件读入二维数组
【发布时间】:2026-01-24 23:10:01
【问题描述】:

其中有一些这样的主题,但这个问题略有不同,因此有所不同。

我只关注较大问题的一半。相信很多人都知道魔方问题。

提示:
假设一个文件在每一行都有行和数字,如所示的正方形。编写一个程序,将信息读入 intS 的二维数组。程序应确定矩阵是否为幻方。

工作解决方案:

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;
}

这是我的(旧)代码,用于将文本文件中的信息读取到二维数组中:

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;
}

这是我正在阅读的文本文件。它是一个 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 

每行故意有两个空格。

在我陈述确切的问题之前,这是一个作业模板,因此方法声明和变量初始化是预先确定的。

我不确定该方法是否正确地从文件中创建了一个 2D 数组,因为我还不能运行它。问题是由于某种原因“矩阵”被初始化为 1 列和 2 行。出于什么原因我不确定,但是为了用文件中的数字填充数组,我需要创建一个二维数组,其维度等于一行中的值的数量。

我之前写过代码来创建一个新的二维数组

int[line.length()][line.length()]

但它创建了一个 36x36 数组,因为这是一行中有多少个单独的字符。我有一种感觉,就像循环第一行并让计数器跟踪每个由零分隔的数字序列一样简单。

对我来说,该解决方案似乎太低效且太耗时,无法找到新数组的维度。实现这一目标的最佳方法是什么?不使用 ArrayLists,因为我必须在使用 ArrayLists 后重写这个程序。

【问题讨论】:

  • 要获取给定行的数字,您只需调用line.split(" ");

标签: java arrays java.util.scanner


【解决方案1】:

我从您提供的文件中生成了以下二维数组:

 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

数组在读取文件的第一行时计算出正方形的大小。这是非常动态的。只要输入文件是一个完美的正方形,它就可以工作。我没有进一步的错误处理。

这是一个简单的方法,应该遵守您的指南。

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);
    }
}

这种方法更加完善和优化。

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());
    }
}

【讨论】:

  • 我很欣赏这确实是解决问题的唯一方法,但我们从未接触过缓冲区,也尚未使用辅助方法编写类。我知道这会产生正确的答案,但我认为我需要以更基本的方式完成它。
  • 如果输入的列 (9) 多于行 (1) 怎么办?您将使用 1 行和 1 列初始化矩阵,并最终以 arrayindexoutofbound 异常结束。
  • 你看我说的了吗? “这是非常动态的。只要输入文件是一个完美的正方形,它就可以工作。我没有进一步的错误处理。”
  • 如果你愿意,我可以将其“简化”...当我完成时,我会将原始提交的内容保留在“新”答案下方。
  • 那将不胜感激。如果我不必坚持使用这样的基本代码,我认为我不会遇到这样的问题。我在这个简单的问题上花了很多时间,以至于我的大脑甚至都不会尝试继续思考它。
【解决方案2】:

您已经接近了,但将您的 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]);
        }
    }
}

您可以做的最大改变是让您自己更轻松地获取您的数字。对于您获得的每一行,很容易将其拆分为字符串数组,以便您可以分别解析每个数字。这样一来,您就可以一次获得数组的全部长度,而不必使用麻烦的计数器。

【讨论】:

  • 我已经实现了这个循环,但是在 '.nextLine()' 上出现“没有这样的元素”错误,我不确定它到底在什么时候到达文件末尾.
【解决方案3】:

首先,测试扫描仪结果。我认为这些分隔符不会起作用。 (顺便说一句,Scanner 的nextInt() 方法很方便。)

如果你可以假设输入是一个方阵,扫描第一行将显示它包含多少个整数。然后你可以(重新)分配数组。然后处理所有行,包括您已经扫描的第一行。

然后你可以设置matrix = new int[n][n];

【讨论】:

    【解决方案4】:

    使用 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);
      }
    

    这只是问题的“阅读”部分。

    【讨论】: