简体   繁体   English

将 .txt 文件读入二维数组

[英]Read .txt file into 2D Array

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.编写一个程序,将信息读入 intS 的二维数组。 The program should determine if the matrix is a magic square or not.程序应该确定矩阵是否是幻方。

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.问题是由于某种原因,“矩阵”被初始化为 1 列和 2 行。 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.出于什么原因我不确定,但为了用文件中的数字填充数组,我需要创建一个二维数组,其维度等于一行中的值数。

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.但它创建了一个 36x36 数组,因为这是一行中有多少个字符。 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.我有一种感觉就像遍历第一行并让计数器跟踪每个由零分隔的数字序列一样简单。

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 后重写这个程序。

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

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.对于您获得的每一行,很容易将其拆分为一个 String 数组,以便您可以分别解析每个数字。 Doing it this way you can then get the full length of the array all at once without having to have troublesome counters.这样做之后,您就可以一次获得数组的全部长度,而无需麻烦的计数器。

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

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.这仅适用于问题的“阅读”部分。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM