如何从文件中读取文本并替换丢失的数据?

How to read text from a file and replace the missing data?

假设我在文件中有这个矩阵,首先我想从文件中读取它,然后我想将 *(star) 更改为 (2x8x11/3 = 58.7):

| 1 2 3 |               | 1 2 3 |
| 4 * 6 |   ----------> | 4 58.7 6 |
| 7 8 9 |               | 7 8 9 |
| 10 11 12|             | 10 11 12|

这就是我所做的

//This method turns the Strings to a matrix (A[][])
//Right now It doesn't work properly because when I put * in my file it crashes because * is not a number 
public double[][] fixMatrix1(String fileName, int r, int c) {//r is row c is column
    double A[][]= new double [r][c];
    try {
        File file = new File(fileName);
        FileInputStream input = new FileInputStream(file);
        Scanner scan = new Scanner(input);
        while(scan.hasNext()) { //IMPORTANT From here I want to look at my file and see if there is any * inside. If so I want to change * to like 999 this way it becomes a number

                /*
                if(scan.nextLine() == "*") {
                  replace that * with 999
                }
                 Something like this (If this isn't clear I want to change that star and replace it with any number so I can take the matrix inside the file as a number matrix, not as a String version that printed on console)
                */

                for (int i = 0; i < r; i++) {
                    for (int j = 0; j < c; j++) {
                        A[i][j] = scan.nextDouble();
                 //With this for block I can fill my empty matrix with numbers in a file
            }
        }
    }
        scan.close();
        input.close();
    } 
    catch (FileNotFoundException e) {
        System.err.println(e.getMessage());
    }
    catch (IOException e) {
        System.err.println(e.getMessage());
    }
    //At the end return
    return A; //It will return my matrix(Right now I turned the String version of a matrix into a double version of a matrix which I can use this A[][] matrix in different methods to replace that * or 999 to another number
}
//From here I want to find that row and column of number that is 999 (which is the right row and column for *)
public void fixMatrix(double A[][], int row, int column) {
    for (int i = 0; i < row; i++) {
        for (int j = 0; j < column; j++) {
            if (A[i][j]==999) { //If any row and column has 999 in it take that row and column
                for (int j2 = 0; j2 < row; j2++) {
                    /*I want it to take that row and column which is 
                    | 2 |
                    | 999|
                    | 8 |
                    | 11|
                    and I want to multiply 2 8 11 and divide them by 3 (2*8*11/3) and give the result in the console like 58.7)
                    */
                    double a1 = A[j2][j]; 
                    System.out.println(a1);
                }
            } System.out.println();
        }
    }
    
}
public static void main(String[] args) {
    //Part 1
    Homework h1 = new Homework();
    
    h1.printMatrix(h1.fixMatrix1("corruptedMatrix.txt", 4, 3), 4, 3);

    /*Right now this gives me 
     | 1 2 3 |
     | 4 5 6 |
     | 7 8 9 |
     | 10 11 12|
     because in my file there is no * (It crashes when I put * in my file because it's not a number)
     */

您可以采用不同的方法。

这里有 2 个:

  1. 使用字符串矩阵并在相关时转换 to/from 数字。 Double.parseDouble(string) 会将字符串转换为双精度。 String.valueOf(double)"" + double 会将双精度数转换为字符串。
  2. 而不是 * 使用一个永远不会在那里使用的数字。例如,如果该矩阵永远不会有负数,则可以使用负数代替 *.

编辑: 看来我没有正确理解问题。

if(scan.nextLine() == "*") {
  replace that * with 999
}

可以换成

String nextLine = scan.nextLine().replace("*", "999")

这样你就可以在 * 的位置得到 999。 将 hasNext() 替换为 hasNextLine() 并在 hasNextLine() 循环中,您可以执行类似

的操作
int j = 0;
for (String num : nextLine.split(" ")) {
    A[i][j] = Double.parseDouble(num);
    j++;
}
i++;

此外,您应该使用 .equals() 来比较字符串。由于它们是对象,== 只比较它们的引用,而不是它们的内容。

您没有完全说明您明确遇到问题的部分,但看起来它正在确定文件中的下一个标记是双精度还是“*”。如果您使用的是扫描仪,则:

  • 在调用 nextDouble()

    之前使用 hasNextDouble() 方法确定下一项是否为双精度
  • 使用hasNext(),传入匹配''的regular expression,判断下一个token是否为“ “:这看起来如下:

    if (scanner.hasNext("\*")) ...

(阅读正则表达式以了解为什么需要反斜杠:本质上,“*”通常具有特殊含义,因此您需要将其转义。)

此外,在您的中间结构中,我建议使用双精度数组而不是双精度数组:换句话说,双精度可以采用 null 的值,因此您不必拥有“特殊”值,如 999 表示 'not present',并避免文件意外包含该值的风险。

这是完整的工作代码,带有注释可以指导您。

import java.io.File;
import java.io.FileInputStream;
import java.util.Scanner;

public class Homework {
  /**
   * This method reads the matrix from
   * the file as a Strings[][] in order 
   * to cater for the '*' (asterisk).
   */
  public String[][] readMatrix (String fileName, int rows, int columns) {
    String matrix[][]= new String [rows][columns];
    try {
      try (Scanner sc = new Scanner (new FileInputStream (new File (fileName)));) {
        /**
         * With this block, the matrix[][]
         * is filled with values from the
         * file.
         */
        while (sc.hasNext ())
          for (int i = 0; i < rows; i++)
            for (int j = 0; j < columns; j++)
              matrix [i] [j] = sc.next ();
      }
    }
    catch (Throwable t) {
      System.out.println (t);
    }
    /**
     * Now the returned is the matrix
     * from file with an '*' (asterisk)
     * in it.
     * ie
     * |  1  2  3 |
     * |  4  *  6 | 
     * |  7  8  9 |
     * | 10 11 12 |
     */
    return matrix;
  }
  /**
   * This method replaces the '*'
   * with the average of the product
   * of the second column of the matrix.
   */
  public String[][] fixMatrix (String matrix[][], int rows, int columns) {
    // Loop through elements of matrix
    for (int i = 0; i < rows; i++)
      for (int j = 0; j < columns; j++) {
        /**
         * If value is an '*', replacw it...
         */
        if (matrix [i] [j].equals ("*")) {
          // The variable to store the product
          double product = 1;
          // Loop through each row, and multiply
          // the second value to get product.
          for (int k = 0; k < rows; k++)
            if (k != j)
              product *= Integer.parseInt (matrix [k] [1]);
          // Now divide the product by 3
          // and round off the decimal
          // then convert it to String
          // and replace the '*' in
          // matrix with the value
          matrix [i] [j] = Double.toString (Math.round ((product / 3)));
          // No need to continue loop
          // so return the matrix
          return matrix;
        }
      }
    // This should not excecute
    return null;
  }
  /**
   * This method prints the matrix.
   */
  public void printMatrix (String[][] matrix, int rows, int columns) {
    for (int i = 0; i < rows; i++) {
      for (int j = 0; j < columns; j++)
      // Aligns the numbers to the right
        System.out.printf ("%4s ", matrix [i] [j]);
      System.out.println ();
    }
  }
  /**
   * This is the driver method.
   */
  public static void main (String[] args) {
    int rows = 4, columns = 3;
    Homework homeWork = new Homework ();
    homeWork.printMatrix (
      homeWork.fixMatrix (
        homeWork.readMatrix (
          "corruptedMatrix.txt", rows, columns), rows, columns), rows, columns);
  }
}