Чтение файла без разрывов строк с использованием Buffered Reader - PullRequest
0 голосов
/ 11 февраля 2019

Я читаю файл со значениями, разделенными запятыми, которые при разбиении на массив будут иметь 10 значений для каждой строкиЯ ожидал, что в файле будут разрывы строк, поэтому

line = bReader.readLine()

даст мне каждую строку.Но у моего файла нет перевода строки.Вместо этого после первого набора значений появляется много пробелов (точнее 465), а затем начинается следующая строка.

Итак, мой приведенный выше код readLine () читает весь файл за один раз, так как нет разрывов строки.Пожалуйста, предложите, как лучше решить этот сценарий.

Ответы [ 5 ]

0 голосов
/ 11 февраля 2019

Насколько я понимаю, у вас есть плоский CSV-файл без правильного разрыва строки, в котором должно быть 10 значений в каждой строке.

Обновлено: 1. (Рекомендуется) Вы можете использовать класс Scanner с useDelimiter для анализаэффективно CSV, если вы пытаетесь сохранить 10 значений из строки:

    public static void parseCsvWithScanner() throws IOException {

    Scanner scanner = new Scanner(new File("test.csv"));

    // set your delimiter for scanner, "," for csv
    scanner.useDelimiter(",");

    // storing 10 values as a "line"
    int LINE_LIMIT = 10;

    // implement your own data structure to store each value of CSV
    int[] tempLineArray = new int[LINE_LIMIT];

    int lineBreakCount = 0;

    while(scanner.hasNext()) {

        // trim start and end spaces if there is any
        String temp = scanner.next().trim();
        tempLineArray[lineBreakCount++] = Integer.parseInt(temp);

        if (lineBreakCount == LINE_LIMIT) {

            // replace your own logic for handling the full array
            for(int i=0; i<tempLineArray.length; i++) {
                System.out.print(tempLineArray[i]);
            } // end replace

            // resetting array and counter
            tempLineArray = new int[LINE_LIMIT];
            lineBreakCount = 0;
        }
    }
    scanner.close();
}

Или используйте BufferedReader.Вам может не понадобиться ArrayList для хранения всех значений, если существует проблема с памятью путем замены собственной логики.

public static void parseCsv() throws IOException {
    BufferedReader br = new BufferedReader(new FileReader(file));
    // your delimiter
    char TOKEN = ',';
    // your requirement of storing 10 values for each "line"
    int LINE_LIMIT = 10;
    // tmp for storing from BufferedReader.read()
    int tmp;
    // a counter for line break
    int lineBreakCount = 0;
    // array for storing 10 values, assuming the values of CSV are integers
    int[] tempArray = new int[LINE_LIMIT];
    // storing tempArray of each line to ArrayList
    ArrayList<int[]> lineList = new ArrayList<>();
    StringBuilder sb = new StringBuilder();

    while((tmp = br.read()) != -1) {
        if ((char)tmp == TOKEN) {
            if (lineBreakCount == LINE_LIMIT) {
                // your logic to handle the current "line" here.
                lineList.add(tempArray);
                // new "line"
                tempArray = new int[LINE_LIMIT];
                lineBreakCount = 0;
            }
            // storing current value from buffer with trim of spaces
            tempArray[lineBreakCount] =
                    Integer.parseInt(sb.toString().trim());
            lineBreakCount++;
            // clear the buffer
            sb.delete(0, sb.length());
        }
        else {
            // add current char from BufferedReader if not delimiter
            sb.append((char)tmp);
        }
    }
    br.close();
}
0 голосов
/ 11 февраля 2019

Вы можете создать свой собственный подкласс FilterInputStream или PushbackInputStream и передать его InputStreamReader.Один переопределяет int read().

Такой класс, к сожалению, нуждается в небольшом наборе.(Так сказать, хороший пример.)

private static final int NO_CHAR = -2;
private boolean fromCache;
private int cachedSpaces;
private int cachedNonSpaceChar = NO_CHAR;

int read() throws IOException {
    if (fromCache) {
        if (cachecSpaces > 0) ...
        if (cachedNonSpaceChar != NO_CHAR) ...
        ...
    }
    int ch = super.read();
    if (ch != -1) {
        ...
    }
    return ch;
}

Идея состоит в том, чтобы кэшировать пробелы до непространственного символа, и в read() либо взять из кеша, вместо этого вернуть \n, вызвать super.read() когда не из кеша, рекурсивный read когда пробел.

0 голосов
/ 11 февраля 2019

Я второй ответ Нинаня: замените 465 пробелов новой строкой, затем запустите функцию, которую вы планировали запустить ранее.

Для эстетики и читабельности я бы предложил использовать шаблон Regex для замены пробелов вместо длинных нечитаемых String.replace(" ").

Ваш код может соответствовать приведенному ниже, но заменить 6 на 465:

 // arguments are passed using the text field below this editor
  public static void main(String[] args)
  {
    String content = "DOG,CAT      MOUSE,CHEESE";
    Pattern p = Pattern.compile("[ ]{6}",
            Pattern.DOTALL | Pattern.CASE_INSENSITIVE);
    String newString = p.matcher(content).replaceAll("\n");
    System.out.println(newString); 
  }
0 голосов
/ 11 февраля 2019

Мое предложение - прочитать файл f1.txt и записать в другой файл f2.txt, удалив все пустые строки и пробелы, затем прочитать f2.txt что-то вроде

FileReader fr = new FileReader("f1.txt"); 
BufferedReader br = new BufferedReader(fr); 
FileWriter fw = new FileWriter("f2.txt"); 
String line;

 while((line = br.readLine()) != null)
{ 
line = line.trim(); // remove leading and trailing whitespace
if (!line.equals("")) // don't write out blank lines
{
    fw.write(line, 0, line.length());
}

}

Затемпопробуйте использовать ваш код.

0 голосов
/ 11 февраля 2019

Одним из способов является замена строки в вашем тексте на 465 пробелов символом новой строки "\ n" перед повторением итерации для чтения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...