2016-04-15 3 views
1

Итак, у меня есть этот файл, который заполняется целыми числами. Я хотел бы, если возможно, иметь возможность читать файл, который может иметь или не иметь пробелы, определяющие каждое целое число.Чтение файла целыми числами, которые могут быть или могут быть обозначены пробелами

Вот два наглядных примера.

Первый - это целые числа, которые не обозначены пробелами, а второй.

Первый пример:

020030090 
000907000 
900208005 
004806500 
607000208 
003102900 
800605007 
000309000 
030020050 

Второй пример:

0 3 8 0 12 0 15 16 6 0 4 0 0 0 0 0 
0 11 5 0 1 0 0 14 13 0 3 9 12 7 0 0 
0 0 0 0 6 0 0 0 0 12 0 14 0 0 0 16 
10 16 0 6 2 13 0 0 0 8 7 0 0 0 0 0 

3 10 1 0 13 0 0 15 0 9 0 16 5 0 0 0 
0 0 16 0 0 0 0 11 14 0 13 12 0 3 0 0 
4 0 7 8 0 0 12 9 0 0 0 0 0 0 11 0 
0 6 0 0 16 0 0 0 11 5 0 0 15 0 0 2 

11 0 0 12 0 0 8 2 0 0 0 1 0 0 14 0 
0 7 0 0 0 0 0 0 3 11 0 0 8 16 0 9 
0 0 13 0 3 6 0 7 16 0 0 0 0 11 0 0 
0 0 0 2 5 0 14 0 15 0 0 4 0 13 7 1 

0 0 0 0 0 14 5 0 0 0 16 2 13 0 8 10 
14 0 0 0 8 0 9 0 0 0 0 11 0 0 0 0 
0 0 6 15 7 1 0 3 12 0 0 13 0 2 5 0 
0 0 0 0 0 15 0 12 1 14 0 3 0 6 16 0 

Примечание:

Я также хотел бы добавить, что второй файл не может быть очерчена на ту же сумму. Это означает, что одно целое число может иметь одно место после него, а другое целое число может содержать 10 пробелов.

То, что я пробовал:

Я попытался с помощью раскол ("\ S +") в сочетании с replaceAll ("", "«), но это не работает во втором например, потому что у него будет больше пробелов и, следовательно, функция split не будет работать.

Я попытался использовать replaceAll ("", "") вот так, чтобы у них не было пробелов вообще. Затем я преобразовал строку в массив символов, но это представляло проблемы с целыми числами больше одной цифры (не будет работать и со вторым примером).

Код:

public void initializeGrid(int grid[][], String fileName) throws FileNotFoundException, IOException 
{ 
     Scanner read = new Scanner(Paths.get(fileName)); 
     int value; 

     for (int i = 0; i < ROWS; i++) 
     {  
      String line = read.nextLine(); 
      String [] numbers = line.trim().split("\\s+"); 

      for (int j = 0; j < COLUMNS; j++) 
      {  
       value = Integer.parseInt(numbers[j]); 
       grid[i][j] = value; 
      } 
     } 
} 
+0

Если целые числа не ограничены, откуда вы знаете, где заканчивается и начинается следующее? – dnault

+0

@dnault Я знаю, что это проблема, но когда пользователь вводит путь к файлу, откуда я знаю, что каждое целое число ограничено пробелами? Вот почему я сказал в начале, если это было возможно. Гораздо легче не беспокоиться об этой ситуации, но я бы хотел справиться с этой ситуацией, если не могу, потому что оба файла действительны. –

+0

О, я вижу. В первом случае каждое целое число гарантировано находится в диапазоне '[0-9]'. Второй случай необходим для случая, когда целые числа могут быть больше 9. – dnault

ответ

1

По рекомендации @dnault в комментариях выше, вот реализация, которая использует рамки Java Collection вместо 2d int массива. Этот подход имеет преимущество перед 2d-массивом в том, что List для каждой строки содержит ровно столько записей, сколько необходимо. Используя массивы, если строка имеет значения менее COLUMN, массив будет содержать нули для всех остальных значений.

public List<List<Integer>> readFile(String fileName) 
     throws FileNotFoundException, IOException { 
    BufferedReader br = Files.newBufferedReader(Paths.get(fileName)); 
    List<List<Integer>> values = new ArrayList<>(); 


    for(String line; (line = br.readLine()) != null;){ 
     String[] splitLine = line.trim().split("\\s+"); 

     if(splitLine.length < 2) 
      values.add(parseSingleDigitValues(splitLine[0].toCharArray())); 
     else 
      values.add(parseDelimitedValues(splitLine)); 

    } 

    return values; 
} 

private List<Integer> parseSingleDigitValues(char[] line) { 
    List<Integer> values = new ArrayList<>(); 
    for(char c: line){ 
     values.add(Integer.parseInt(String.valueOf(c))); 
    } 
    return values; 

} 

private List<Integer> parseDelimitedValues(String[] line) { 
    List<Integer> values = new ArrayList<>(); 
    for(String str :line) 
     values.add(Integer.parseInt(str)); 
    return values; 
} 

В результате List<List<Integer>> могут быть легко преобразованы в 2D int массив, используя следующий метод:

private int[][] asArray(List<List<Integer>> lists){ 
    int s1 = lists.size(); 
    int s2 = 0; 
    for(List<Integer> sublist : lists){ 
     if(sublist.size() > s2) 
      s2 = sublist.size(); 
    } 

    int[][] arr = new int[s1][s2]; 
    for(int i = 0; i < lists.size(); i++){ 
     List<Integer> sublist = lists.get(i); 
     for(int j = 0; j < sublist.size(); j++){ 
      arr[i][j] = sublist.get(j); 
     } 
    } 
    return arr; 
} 

EDIT В конце концов, если вы четко документировать код/​​API, то бремя находится на пользователе, чтобы правильно использовать его. Я рекомендую вам выбрать простоту в вашем API: скажите пользователю, что они должны предоставить файл с разделителями-пробелами. Затем вы можете предоставить класс утилиты, который преобразует файл без разделителей в файл с разделителями пробелов.

+0

Это именно то, о чем я думал в своем уме. Я просто не хочу, чтобы пользователь вводил файл без пробелов и видел, что он не работает правильно, но я думаю, что говорить им, что он должен быть очерчен пробелами, должно быть достаточно. –

+0

Точно. Это то, что должна делать документация API, - сообщите пользователю, как использовать API. Пока это четко задокументировано, пользователь должен следовать вашим рекомендациям. Если вы решите использовать разделители пространства, я рекомендую вам исключить исключение, если пробелы не используются или не используются ненадлежащим образом (в любой момент). Это поможет пользователю определить проблему как можно раньше в процессе отладки. –

Смежные вопросы