【问题标题】:BufferedReader saving sentence, String array, then 2D int arrayBufferedReader 保存句子,String 数组,然后是 2D int 数组
【发布时间】:2021-12-31 21:34:26
【问题描述】:

我有一个包含文本的 .txt 文件,我想将它的一部分保存在 String 中,一部分保存在 String 数组中,最后一部分保存在 2D int 数组中,我面临两个问题:

  1. 如何在事先不知道大小的情况下读取和保存两个数组?
  2. 二维数组未正确读取/保存

这里是文本文件供参考:

This is the sentence to be read.
This
is
a
String
array.
90 47 110 95 95
101 87 
54 0 38 12 

这是我的方法的一部分,它应该读取和保存三种数据类型:

BufferedReader br = new BufferedReader(new FileReader(fileName));
        
        sentence = br.readLine();

        stringArr = new String[5]; //how to initialize without set number of elements?
        for(int i = 0; i<stringArr.length; i++){
            stringArr[i] = br.readLine();
        }

        int2DArr = new int[3][5]; //how to initialize with any amount of rows and columns?
        for(int i = 0; i<int2DArr.length; i++){
            for(int j = 0; j<int2DArr[i].length; j++){
                int2DArr[i][j] = br.read();
                //how to read the space after each int ?
            }
        }

我将如何通过读取文本文件来“获取”数组的大小,以便在初始化两个数组时获得正确的大小?任何帮助将不胜感激!

【问题讨论】:

  • 我认为您应该使用while 循环来遍历文本行。查看网络上有关如何用 Java 读取文件的许多示例。您始终可以在循环外初始化 int 以捕获行索引,并且可以在 while 内将所述变量加一。
  • @hfontanez,对,但是我怎么知道我何时到达 2d int 数组并切换数据类型?
  • 这就是明确的需求有帮助的原因。我们都不知道这个文件结构。所有文件是否总是具有相同的行数和相同的数据排列?为什么一个文件用来存储混合数据类型?在我看来,它们应该存储在单独的文件中。
  • 此外,您始终可以将数字存储为字符串并在以后转换为数字。
  • @hfontanez 文件结构必须是String,后跟String数组,后跟2D int数组,如上图。这些文件将始终具有相同的数据排列,只是数组大小不同

标签: java file-io bufferedreader


【解决方案1】:

我们可以通过两次文件并获得更简洁的代码,而不是试图一次完成所有事情。

这当然会耗费双倍的时间,但它会帮助您了解如何将较大的问题分解为较小的问题并一一处理。

步骤如下:

  1. 在第一遍中确定 stringArr 和 intArr 的大小
  2. 在第二遍中填充相应数组中的值

如果您想知道如何确定 int2DArr 的列数。只是我们不自己做。我们使用Jagged Arrays的概念

在此处阅读更多信息How do I create a jagged 2d array in Java?

import java.util.*;
import java.io.*;

class ReadFileIntoArr {
    public static void main(String args[]) throws IOException {
        String fileName = "test.txt";
        BufferedReader br = new BufferedReader(new FileReader(fileName));

        String line = br.readLine();
        int strSize = 0;
        int intSize = 0;
        boolean isDigit = false;

        while (line != null && line.trim().length() != 0) {
            if (!isDigit && Character.isDigit(line.charAt(0)))
                isDigit = true;
            if (isDigit)
                intSize++;
            else
                strSize++;
            line = br.readLine();
        }

        br = new BufferedReader(new FileReader(fileName));

        String[] stringArr = new String[strSize];
        for (int i = 0; i < stringArr.length; i++)
            stringArr[i] = br.readLine();

        int[][] int2DArr = new int[intSize][];
        for (int i = 0; i < int2DArr.length; i++)
            int2DArr[i] = Arrays.stream(br.readLine().split(" ")).mapToInt(Integer::parseInt).toArray();

        System.out.println(Arrays.toString(stringArr));
        System.out.println(Arrays.deepToString(int2DArr));
    }
}

注意:在单次传递中,这可以在 ArrayList 的帮助下完成,然后将所有内容转移到相应的数组中。

更新:了解您的问题的限制后,这里是另一个版本

import java.util.*;
import java.io.*;

class ReadFileIntoArr {
    public static void main(String args[]) throws IOException {
        String fileName = "test.txt";
        BufferedReader br = new BufferedReader(new FileReader(fileName));

        String line = br.readLine();
        int strSize = 0;
        int intSize = 0;
        boolean isDigit = false;

        while (line != null && line.trim().length() != 0) {
            if (!isDigit && isDigit(line.charAt(0)))
                isDigit = true;
            if (isDigit)
                intSize++;
            else
                strSize++;
            line = br.readLine();
        }

        br = new BufferedReader(new FileReader(fileName));

        String[] stringArr = new String[strSize];
        for (int i = 0; i < stringArr.length; i++)
            stringArr[i] = br.readLine();

        int[][] int2DArr = new int[intSize][];
        for (int i = 0; i < int2DArr.length; i++)
            int2DArr[i] = convertStringArrToIntArr(br.readLine().split(" "));

        System.out.println(Arrays.toString(stringArr));
        System.out.println(Arrays.deepToString(int2DArr));
    }

    public static boolean isDigit(char c) {
        return c >= '0' && c <= '9';
    }

    public static int[] convertStringArrToIntArr(String[] strArr) {
        int[] intArr = new int[strArr.length];
        for (int i = 0; i < strArr.length; i++)
            intArr[i] = Integer.parseInt(strArr[i]);
        return intArr;
    }
}

【讨论】:

  • 感谢您花时间解释这一点!我知道我必须像你提到的那样经历两次,只是不确定那会是什么样子。但是,由于我的分配限制,我认为我不能使用 .stream 或 .mapToInt ,这些方法到底有什么作用?我还认为我必须手动编写一个 .isDigit() 方法,该方法仅检查当前字符是否为数字,对吗?
  • .stream 在这种情况下用于从 Array 创建流,并且 .mapToInt 可用于将流数据类型转换为 int(原始数据类型)的流。我已经用 isDigit 更新了代码的第二个版本,以及一种避免使用流和 mapToInt 的方法。
【解决方案2】:
Path path = Paths.get(fileName);
List<String> lines = Files.readAllLines(path, Charset.defaultCharset());

String title = lines.get(0);
List<String> words = new ArrayList<>();
for (int i = 1; i < lines.size(); ++i) {
    String word = lines.get(i);
    if (!word.isEmpty() && Character.isDigit(word.codePointAt(0)) {
        break;
    }
    words.add(word);
}
String[] wordArray = words.toArray(new String[]);
int i0 = 1 + words.size();
int n = lines.size() - i0;
int[][] numbers = new int[n][];
for (int i = i0; i < lines.size(); ++i) {
    String[] values = lines.get(i).trim().split("\\s+");
    int m = values.length;
    int[] row = new int[m];
    for (int j = 0; j < m; ++m) {
        row[j] = Integer.parse(values[j]);
    }
    numbers[i - i0] = row;
}
  • PathFile 的泛化,也是 URL。
  • Files 是文件函数的宝库。
  • 可以不用动态调整大小的List;一个人需要先测试, 但通常人们无论如何都会使用 List。
  • String.split 拆分一个或多个空格。

【讨论】:

    猜你喜欢
    • 2016-06-22
    • 2013-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多