如何在Java中有效地读取带分隔值的文本文件?

时间:2015-07-06 11:22:29

标签: java

我有一个看起来像这样的文本文件:

2, 20, 0, 9, 7, 17, ... (100 columns)
1, 3, 22, 11, 0, 0, ...
...
(100 rows)

条件:

  1. 我想将每个值作为int读入int [] []
  2. 类型的变量中
  3. 这不是csv文件(文件中还有其他值)
  4. 这适用于Android开发 - 没有java库
  5. 我希望它尽可能高效 - 最好不要使用String
  6. 我想到了什么,但不喜欢:

    while ((line = br.readLine()) != null) {
       String[] values = line.split(','); // this heavily uses String
       parseInts(values);
    }
    

    while ((r = fileInput.read()) != -1) {
       char c = (char) r;
       if (c != ',' && c != '\n') {
          doSomething(c); // this is problematic when reading 2 digit numbers
       }
    }
    

    请记住,我想要一种方法有效这样做。任何帮助表示赞赏。感谢

    检查下面的完整解决方案。

4 个答案:

答案 0 :(得分:2)

答案 1 :(得分:0)

对于非单个数字的号码,我们知道我们可以使用逗号识别号码。

  

所以读一下这个数字,直到你休息一下。

你如何将角色变成数字。

考虑123

number char    num * 10 + char
   0    1          0 * 10 + 1 = 1
   1    2          1 * 10 + 2 = 12
   2    3          12 * 10 + 3 = 123 

所以这是程序

List<Integer> = new ArrayList();
int number = 0;
while ((r = fileInput.read()) != -1) {
   char c = (char) r;
   if (c != ',' && c != '\n') {
       number = number * 10 + (int)c - 48;
   }
   else
      {
         list.add(number);
         number = 0; 
     }
}

使用扫描仪 使用扫描仪,设置分隔符可以让您轻松阅读,而不占用任何额外空间。

List<Integer> list = new ArrayList();
File file = new File("10_Random.txt");

try {

    Scanner sc = new Scanner(file);
    sc.useDelimiter(",");
    while (sc.hasNextLine()) {
        list.add(sc.nextInt());
    }
    sc.close();
} 
catch (FileNotFoundException e) {
    e.printStackTrace();
}

答案 2 :(得分:0)

以下是一个高效的代码段,只缺少parseInt缓冲区的替代char实现以及一些调整...:

public static void main(String args[]) throws IOException {
    //data source
    StringReader reader = new StringReader(
            "2, 20, 0, 9, 7, 17" + "\n" +
                    "1, 3, 22, 11, 0, 0"); //todo change to the actual data source

    //result
    int[][] values = new int[2][6]; //todo increase size to new int[100][100]
    int x = 0;
    int y = 0;

    //buffer
    char[] charBuffer = new char[3]; //todo check if increased size is necessary
    int ci = 0;

    //parse loop
    while (true) {
        final int c = reader.read();
        switch (c) {
            case ' ':
                //ignore
                continue;
            case ',':
            case '\n':
            case -1:
                //parse number
                values[y][x] = parseInt(charBuffer, 0, ci);
                ci = 0;
                break;
        }
        if (c == -1) {
            break;
        }
        switch (c) {

            case ',':
                //next column
                x++;
                break;
            case '\n':
                //next line
                x = 0;
                y++;
                break;
            default:
                //store digit
                charBuffer[ci++] = (char) c;
                break;
        }
    }

    System.out.println(Arrays.deepToString(values));
}

public static int parseInt(char[] charBuffer, int offset, int length) {
    //todo implement a faster performing parse method for a ``char[]``
    return Integer.parseInt(new String(charBuffer, offset, length));
}

答案 3 :(得分:0)

使用Andrei Ciobanu的答案,我使用StreamTokenizer并且完美地工作,正是我想要的,谢谢!

StreamTokenizer st = new StreamTokenizer(reader);
st.parseNumbers();
st.eolIsSignificant(true);
st.whitespaceChars(',', ',');

tilePattern = new int[rowCount][columnCount];
int row = 0;
int column = 0;

boolean eof = false;
do {
    int token = st.nextToken();
    switch (token) {
        case StreamTokenizer.TT_EOF:
            eof = true;
            break;
        case StreamTokenizer.TT_EOL:
            row++;
            column = 0;
            break;
        case StreamTokenizer.TT_NUMBER:
            tilePattern[row][column] = (int) st.nval;
            column++;
            break;
    }
} while (!eof);