#java #substring
#java #подстрока
Вопрос:
Я разбираю много строк из текстового файла. Строки файла имеют фиксированную длину, но в зависимости от начала строки, например «0301 ….», структура данных файла разделяется. есть пример строк, начинающийся с 11, 34 и т.д., И на основе этого строка разделяется по-разному.
Пример: если начало строки содержит «03», то строка будет разделена на
name = line.substring(2, 10);
surname = line.substring(11, 21);
id = line.substring(22, 34);
adress = line.substring (35, 46);
Другой пример: если начало строки содержит «24», то строка будет разделена на
name = line.substring(5, 15);
salary = line.substring(35, 51);
empid = line.substring(22, 34);
department = line.substring (35, 46);
Итак, у меня есть много подстрок, которые добавляются ко многим строкам, а затем записываются в новый файл в csv.
Мой вопрос был бы в том, есть ли какой-либо простой способ сохранить координаты (индексы) подстроки и вызвать их позже проще? Пример
name = (2,10);
surname = (11,21);
…
и т.д.
Или, возможно, какая-либо альтернатива использованию подстрок? Спасибо!
Комментарии:
1. Я полагаю, вы могли бы поместить все координаты в массив и использовать карту для поиска в массиве на основе вашей входной строки.
2. Всегда ли строки разделяются одними и теми же полями (имя, фамилия, идентификатор, адрес) или у них могут быть разные поля, основанные на начале?
3. @Loris Securo к сожалению, новые типы данных не совпадают
4. карта ключей «start» (строка), которая содержит значение пользовательского объекта (как предложено @AzizSonawalla ниже), который содержит начальный индекс, конечный индекс и пользовательскую функцию (или некоторое расширение функции), может подойти вам.
Ответ №1:
Вы могли бы попробовать что-то вроде этого. Я оставлю проверку границ и оптимизацию вам, но в качестве первого шага…
public static void main( String[] args ) {
Map<String, Map<String,IndexDesignation>> substringMapping = new HashMap<>();
// Put all the designations of how to map here
substringMapping.put( "03", new HashMap<>());
substringMapping.get( "03" ).put( "name", new IndexDesignation(2,10));
substringMapping.get( "03" ).put( "surname", new IndexDesignation(11,21));
// This determines which mapping value to use
Map<String,IndexDesignation> indexDesignationMap = substringMapping.get(args[0].substring(0,2));
// This holds the results
Map<String, String> resultsMap = new HashMap<>();
// Make sure we actually have a map to use
if ( indexDesignationMap != null ) {
// Now take this particular map designation and turn it into the resulting map of name to values
for ( Map.Entry<String,IndexDesignation> mapEntry : indexDesignationMap.entrySet() ) {
resultsMap.put(mapEntry.getKey(), args[0].substring(mapEntry.getValue().startIndex,
mapEntry.getValue().endIndex));
}
}
// Print out the results (and you can assign to another object here as needed)
System.out.println( resultsMap );
}
// Could also just use a list of two elements instead of this
static class IndexDesignation {
int startIndex;
int endIndex;
public IndexDesignation( int startIndex, int endIndex ) {
this.startIndex = startIndex;
this.endIndex = endIndex;
}
}
Комментарии:
1. Спасибо, вероятно, это то, что я искал. Я обязательно попробую.
Ответ №2:
Создайте класс с именем Line
и сохраните эти объекты вместо строки:
class Line {
int[] name;
int[] surname;
int[] id;
int[] address;
String line;
public Line(String line) {
this.line = line;
String startCode = line.substring(0, 3);
switch(startCode) {
case "03":
this.name = new int[]{2, 10};
this.surname = new int[]{11, 21};
this.id = new int[]{22, 34};
this.address = new int[]{35, 46};
break;
case "24":
// same thing with different indices
break;
// add more cases
}
}
public String getName() {
return this.line.substring(this.name[0], this.name[1]);
}
public String getSurname() {
return this.line.substring(this.surname[0], this.surname[1]);
}
public String getId() {
return this.line.substring(this.id[0], this.id[1]);
}
public String getAddress() {
return this.line.substring(this.address[0], this.address[1]);
}
}
Тогда:
String line = "03 ..."
Line parsed = new Line(line);
parsed.getName();
parsed.getSurname();
...
Если вы собираетесь извлекать name
, surname
и т.д. Из Line
объекта несколько раз, вы даже можете кэшировать его в первый раз, чтобы не вызывать substring
несколько раз
Комментарии:
1. Дорогой Азис, спасибо вам за ответ. К сожалению, каждый начальный код содержит новые типы данных, не всегда имя, фамилию и т. Д
Ответ №3:
Мы также можем использовать шаблон регулярных выражений и потоки для достижения результатов.
Скажем, у нас есть текстовый файл, подобный этому —
03SomeNameSomeSurname
24SomeName10000
Шаблон регулярных выражений имеет имя группы для присвоения имени атрибута анализируемому тексту. Итак, шаблон для первой строки —
^03(?<name>.{8})(?<surname>.{11})
Код является —
public static void main(String[] args) {
// Fixed Width File Lines
List<String> fileLines = List.of(
"03SomeNameSomeSurname",
"24SomeName10000"
);
// List all regex patterns for the specific file
List<Pattern> patternList = List.of(
Pattern.compile("^03(?<name>.{8})(?<surname>.{11})"), // Regex for String - 03SomeNameSomeSurname
Pattern.compile("^24(?<name>.{8})(?<salary>.{5})")); // Regex For String - 24SomeName10000
// Pattern for finding Group Names
Pattern groupNamePattern = Pattern.compile("\?<([a-zA-Z0-9]*)>");
List<List<String>> output = fileLines.stream().map(
line -> patternList.stream() // Stream over the pattern list
.map(pattern -> pattern.matcher(line)) // Create a matcher for the fixed width line and regex pattern
.filter(matcher -> matcher.find()) // Filter matcher which matches correctly
.map( // Transform matcher results into String (Group Name = Matched Value
matcher ->
groupNamePattern.matcher(matcher.pattern().toString()).results() // Find Group Names for the regex pattern
.map(groupNameMatchResult -> groupNameMatchResult.group(1) "=" matcher.group(groupNameMatchResult.group(1))) // Transform into String (Group Name = Matched Value)
.collect(Collectors.joining(","))) // Join results delimited with ,
.collect(Collectors.toList())
).collect(Collectors.toList());
System.out.println(output);
}
В результате вывода имя атрибута и значение атрибута были проанализированы как список строк.
[[name=SomeName,surname=SomeSurname], [name=SomeName,salary=10000]]