读取 .txt 文件为二维数组

7

有一些关于这些话题的内容,但这个问题稍微有点不同。

我只关注更大问题的一半。我相信你们中的许多人都知道魔方问题。

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

工作解决方案:

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

这是我(旧的)从文本文件读取信息到2D数组的代码:

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 

每行开头有两个空格是有意为之。

在我说明具体问题之前,这是一个作业模板,所以方法声明和变量初始化已经预先确定。

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

我之前写过创建新的二维数组的代码。

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

但是它创建了一个36x36的数组,因为每行有这么多个单独的字符。我有一种感觉,只需循环第一行,并通过计数器跟踪由零分隔的每个数字序列即可。对我来说,这个解决方案似乎太低效和耗时,仅仅是为了找到新数组的尺寸。最好的方法是什么?不使用ArrayLists,因为我必须在使用ArrayLists后重新编写此程序。

要获取给定行上的数字,您可以简单地调用 line.split(" "); - ggmathur
4个回答

6

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

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

我很感激这是唯一解决问题的方法,但我们从未接触过缓冲区,并且还没有编写带有辅助方法的类。我知道这会产生正确的答案,但我认为我需要以更基础的方式完成它。 - BimmerM3
如果输入的列数(9)大于行数(1),那该怎么办?你会用一个行和一列来初始化矩阵,最终可能会出现数组越界异常。 - Em Ae
你读了我说的话吗?“这非常动态。只要输入文件是完美的平方,它就能工作。我没有更多的错误处理。” - Mr. Polywhirl
如果你想的话,我可以把它讲得更简单易懂... 当我完成后,我会在“新”答案下面保留我的原始提交。 - Mr. Polywhirl
我会使用 BufferedReader 而不是 Scanner。它不仅存在更久,而且它是同步的! :-) 只需按照我的注释创建基于您需求的 BufferedReader 即可。 - Mr. Polywhirl
显示剩余2条评论

1
你很接近了,但是需要将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()' 上出现了“没有这样的元素”错误,而且我不确定它到底在什么时候到达了文件的末尾。 - BimmerM3

0

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

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


0

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

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

接下来你可以设置matrix = new int[n][n];


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接