Stack Overflow на русском Asked on December 25, 2021
Задача: достать из файла корректные данные. Корректные – это фамилия, зарплата и номер департамента. Все данные разделены либо слешем и произвольным количеством пробелов, либо произвольным количеством пробелов.
Также необходимо обработать ошибки, мы не должны доставать строки, в которых после знака "." в зарплате идёт более трёх чисел. Пустые строки, строки без фамилии, департамента – не нужны.
Файл с данными:
Ситов /13000.1234134/Первый - невалидно, больше 3 цифр после точки в зп - 1234134, максимум 123 должно быть
Курбян -13000.123/Второй - невалидный, есть минус в числе
Кошкин 13000.123/Четвёртый- валидный, потому что фио, цифры, департамент - подходят по условию
43242/13424/Третий - невалидный, вместо фио цифры
Жестков/13424/43242- невалидный, вместо департамента цифры
Петровна/привет/Третий - невалидный, вместо зп цифры
Иванович/-10000/Третий -невалидно, есть минус у зп
/ 132/ Четвертый - невалидно, ничего нет на месте фио и зп из 3 цифр быть не может, минимум от 5 цифр
Петров/10000/Пятый - валидно
Иванов/30000/ШЕСТОЙ -валидно
Сидоров/20000/Седьмой - валидно
Пушкин/40000/Восьмой - валидно
Как я пытался сделать:
public static void main(String[] args) throws IOException {
String s;
try {
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("C:/Users/VGilenko/Desktop/file.txt"), "CP1251"));
while ((s = br.readLine()) != null) {
if (s.trim().length() != 0) {
String[] words = s.split("/");
for (String element : words) {
System.out.println(element);
}
}
}
br.close();
}
catch (FileNotFoundException e) {
System.out.println("Файл не был найден, нужно скорректировать путь");
}
}
Вывод моего приложения:
Ситов
13000.1234134
Первый
Курбян -13000.123
Второй
Иванович
-10000
Третий
132
Четвертый
Петров
10000
Пятый
Иванов
30000
ШЕСТОЙ
Сидоров
20000
Седьмой
Пушкин
40000
Восьмой
Проблема:
Понимаю, что программа проверяет на пустоту строк, но мне этого недостаточно, как мне ещё добавить условия, которые необходимы? Допустим, чтобы была проверка на пустые ячейки, например, когда фамилии нет и необходимо эту строку убрать. Нужно ли добавлять s.trim().length() == 0)
в if
, потому что если убрать, то он пишет "not a statement" и предлагает Exctract side effect
.
Пожалуй, единственным адекватным решением данного вопроса являются регулярные выражения. Без них проверка сроки станет гораздо более неудобной. Вот оптимальное решение.
String regex = "[А-Яа-яЁёA-Za-z]+";
while ((s = br.readLine()) != null) {
if (!(s = s.trim()).isEmpty()) {
String[] strings = s.split("\s*/\s*|\s+");
if (strings.length < 3)
continue;
if (!(strings[0].matches(regex) && strings[2].matches(regex)))
continue;
if (!strings[1].matches("\d{5}(\.\d{1,3})?"))
continue;
System.out.println(strings[0] + " " + strings[1] + " " + strings[2]);
}
}
Если вы хотите, чтобы разделителем был только символ /
и ничего более, четвёртую строчку надо будет написать так:
String[] strings = s.split("/");
Если вы хотите, чтобы выводилась причина, вы можете сделать так:
if (strings.length < 3) {
System.out.println("Строка `" + s + "` имеет неверное количество слов");
continue;
}
Answered by Имя Фамилия on December 25, 2021
Как-то так?
while ((s = br.readLine()) != null) {
if (!s.trim().isEmpty()) {
String[] words = s.split("/");
for (String element : words) {
if(!element.trim().isEmpty())
System.out.println(element);
}
}
}
Answered by Barmaley on December 25, 2021
Можете создать отдельную функцию, которая будет проверять каждую строку на соответствие. Например так:
public static boolean isLineOkay(String line){
String[] parts = line.split("/");
if(parts.length != 3){
return false;
}
for(int i = 0; i < parts.length; i++){
if (parts[i].trim().isEmpty()){
return false;
}
if (i == 1 && !parts[i].trim().matches("\d+\.?\d{0,3}")){
return false;
}
}
return true;
}
и проверять каждую строчку. В случае true
дальше ее обрабатывать в соов-е с Вашим заданием.
Например
while ((s = br.readLine()) != null) {
if(isLineOkay(s)){
// .. обрабатываем как-то
// .. например отправляем ее в обработчик
}
// .. здесь ничего нет, поэтому
// .. если строчка не пройдет проверку
// .. ничего не произойдет. Мы просто
// .. переходим к следующей
}
Более сложный вариант предполагает использование регулярок для парсинга. Вот пример:
package click.webelement.so;
import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
public static void main(String[] args) {
String inputs[] = {
"Ситов /13000.1234134/Первый",
"Курбян -13000.123/Второй",
"Кошкин 13000.123/Четвёртый",
"43242/13424/Третий",
"Жестков/13424/43242",
"Петровна/привет/Третий",
"Иванович/-10000/Третий",
"/ 132/ Четвертый",
"Петров/10000/Пятый",
"Иванов/30000/ШЕСТОЙ",
"Сидоров/20000/Седьмой",
"Пушкин/40000/Восьмой",
" Пушкин / 40000 Восьмой"
};
for (String input: inputs){
String parts[] = isLineOkay(input);
if(parts != null){
System.out.println("Parsed data: " + Arrays.asList(parts));
}
}
}
public static String[] isLineOkay(String line){
final String PATTERN = "^\s*?([А-Яа-яЁё]+)\s*?(?:\/\s*?)?(\d+\.?\d{0,3})\s*?(?:\/\s*?)?([А-Яа-яЁё]+)$";
Pattern pattern = Pattern.compile(PATTERN);
String[] parts = new String[3];
Matcher matcher = pattern.matcher(line);
if(matcher.matches()){
parts[0] = matcher.group(1);
parts[1] = matcher.group(2);
parts[2] = matcher.group(3);
return parts;
}else{
return null;
}
}
}
Вывод:
Parsed data: [Кошкин, 13000.123, Четвёртый]
Parsed data: [Петров, 10000, Пятый]
Parsed data: [Иванов, 30000, ШЕСТОЙ]
Parsed data: [Сидоров, 20000, Седьмой]
Parsed data: [Пушкин, 40000, Восьмой]
Parsed data: [Пушкин, 40000, Восьмой]
P.S. - Регулярка разбирает строчку на куски позволяя частям быть окруженными любым количеством пробелов и разделяться либо слешами либо пробелами либо вообще ничем. Т.е. текстчислотекст тоже сгодиться.
Answered by Alexey R. on December 25, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP