将文本拆分为数组(无明显分隔符)- Java

3
我需要使用循环将每一行文字分割成数组。问题在于,由于文本文件的格式(我无法更改),没有明显的分隔符可用:
Adam Rippon      New York, NY    77.58144.6163.6780.94
Brandon Mroz     Broadmoor, CO   70.57138.1266.8471.28
Stephen Carriere Boston, MA      64.42138.8368.2770.56
Grant Hochstein  New York, NY    64.62133.8867.4468.44
Keegan Messing   Alaska, AK      61.15136.3071.0266.28
Timothy Dolensky Atlanta, AL     61.76123.0861.3063.78
Max Aaron        Broadmoor, CO   86.95173.4979.4893.51
Jeremy Abbott    Detroit, MI     99.86174.4193.4280.99
Jason Brown      Skokie Value,IL 87.47182.6193.3489.27
Joshua Farris    Broadmoor, CO   78.37169.6987.1783.52
Richard Dornbush All Year, CA    92.04144.3465.8278.52
Douglas Razzano  Coyotes, AZ     75.18157.2580.6976.56
Ross Miner       Boston, MA      71.94152.8772.5380.34
Sean Rabbit      Glacier, CA     60.58122.7656.9066.86
Lukas Kaugars    Broadmoor, CO   64.57114.7550.4766.28
Philip Warren    All Year, CA    55.80113.2457.0258.22
Daniel Raad      Southwest FL    52.98108.0358.6151.42
Scott Dyer       Brooklyn, OH    55.78100.9744.3357.64
Robert PrzepioskiRochester, NY   47.00100.3449.2651.08

理想情况下,我希望每个名字都在[0](或者名字在[0],姓氏在[1]),每个位置都在[2],或者也可以在城市和州两个不同的索引中,然后每个分数都在它们自己的索引中。对于每个人有四个单独的数字。例如,Adam Rippon的得分为77.58、144.61、63.67、80.94。
无法按空格拆分,因为有些城市的名称之间有空格(比如New York会被拆分成New和York两个不同的数组元素,而Broadmoor则只有一个元素)。不能通过逗号拆分城市,因为Southwest FL没有逗号。我也不能通过小数点拆分数字,因为那些数字将是错误的。
所以有没有一种简单的方法来解决这个问题呢?比如按小数位数拆分数字?

你会如何处理 77.58144.6177.58144.6177.58144.61?或者假设你总是有小数点后两位?另外,对于最后一行,你会如何将姓氏与城市分开? - Alexis C.
这正是我正在苦苦挣扎的问题。鉴于文本文件中没有任何数字之间用空格分隔,我不知道如何将它们分开。每个单独的数字在小数点后有两位数字,因此我不确定是否可以使用这种方式来拆分数字。 - sam
正如答案所述,由于它是一个固定大小的行格式,您不会遇到获取名字、姓氏、城市和州的麻烦。然后,如果您知道每个数字小数点后应该有两位,您就知道每个数字的长度,因此就没有更多问题了。 - Alexis C.
6个回答

7

看起来每个列都有一个固定的大小。所以在你的情况下,第一列是17个字符长,第二列是16个字符长,最后一列是21个字符长。

现在你可以简单地遍历这些行并利用substring()方法。像这样...

String firstColumn = line.substring(0, 17).trim();
String secondColumn = line.substring(17, 33).trim();
String thirdColumn = line.substring(33, line.length).trim();

为了提取数字,我们可以使用一个正则表达式来搜索所有保留两位小数的数字。
Pattern pattern = Pattern.compile("(\\d+\\.[0-9]{2})");

Matcher matcher = pattern.matcher(thirdColumn);

while(matcher.find())
{
    System.out.println(matcher.group());
}

所以在这种情况下,47.00100.3449.2651.08将输出。
47.00
100.34
49.26
51.08

那么你的意思是按列大小分割?我该怎么做呢? - sam
啊,非常感谢。如此简单,本应显而易见。 - sam
你如何获取每个小数? - Shar1er80
@Shar1er80 你可以使用正则表达式,例如\d+.[0-9]{2},这样它就会找到每个后面跟着两位小数的数字。我已经编辑了我的帖子!@sam - kevcodez

1

看起来每一列都有固定的大小(字符数)。正如你已经说过的,由于最后一行没有名称和城市之间的制表符或空格,因此无法按制表符或空格拆分。

我建议先读取一行,然后通过line.substring(startIndex,endIndex)来拆分字符串。例如,如果我数对了,line.substring(0,18)就是名称。然后,您可以使用空格作为分隔符将此名称拆分为名字和姓氏。


0
假设字段是固定宽度的,这似乎是这样的,您可以执行子字符串操作以获取每个字段,然后进行解析。类似于:
String name = line.substring(0,x)
String city_state = line.substring(x, y)
String num1 = line.substring(y,z)

等等,其中 x、y 和 z 是列的分隔符。


0

这似乎是旧的固定位置文件格式。在卡片阅读器时代非常流行。

因此,基本上,您逐行读取此文件,然后执行以下操作:

String name = line.substring(0,17).trim();
String location = line.substring(17,33).trim();

String[] scores = new String[4];
scores[0] = line.substring(33,38);
scores[1] = line.substring(38,44);
scores[2] = line.substring(44,49);
scores[3] = line.substring(49,54);

然后,您可以通过空格拆分名称,通过拆分位置,将分数转换为数字等等。

如果您想使上述所有内容更加通用,可以准备一个索引列表,并根据这些索引创建数组:

int[] fieldIndexes = { 0, 17,33,38,44,49,54 };
String values[] = new String[fieldIndexes.length - 1];

然后在您的读取循环中(我再次假设您将行读入line):

for ( int i = 1; i < fieldIndexes.length; i++ ) {

     values[i-1] = line.substring(fieldIndexes[i-1],fieldIndexes[i]).trim();

}

然后继续使用values数组进行操作。

当然,确保每行读取的字符数等都是适当的,以避免越界问题。


0
为什么不通过索引值进行拆分? 坐标是比较棘手的问题,但是如果小数点后总是有两个数字,那么这个示例可能会有所帮助。
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;


public class Split {

    public static void main(String[] args) throws IOException {

        List<Person> lst = new ArrayList<Split.Person>();

        BufferedReader br = new BufferedReader(new FileReader("c:\\test\\file.txt"));

        try {
            String line = null;

            while ((line = br.readLine()) != null) {

                Person p = new Person();

                String[] name = line.substring(0,17).split(" ");
                String[] city = line.substring(17,33).split(" ");

                p.setName(name[0].trim());
                p.setLastname(name[1].trim());
                p.setCity(city[0].replace(",","").trim());
                p.setState(city[1].replace(",","").trim());

                String[] coordinates = new String[4];
                String coor = line.substring(33);

                String first = coor.substring(0, coor.indexOf(".") + 3);

                coor = coor.substring(first.length());

                String second = coor.substring(0, coor.indexOf(".") + 3);

                coor = coor.substring(second.length());

                String third = coor.substring(0, coor.indexOf(".") + 3);

                coor = coor.substring(third.length());

                String fourth = coor.substring(0, coor.indexOf(".") + 3);

                coordinates[0] = first;
                coordinates[1] = second;
                coordinates[2] = third;
                coordinates[3] = fourth;

                p.setCoordinates(coordinates);

                lst.add(p);
            }

        } finally {
            br.close();
        }

        for(Person p : lst){
            System.out.println(p.getName());
            System.out.println(p.getLastname());
            System.out.println(p.getCity());
            System.out.println(p.getState());
            for(String s : p.getCoordinates()){
                System.out.println(s);
            }

            System.out.println();
        }
    }

    public static class Person {

        public Person(){}

        private String name;
        private String lastname;
        private String city;
        private String state;
        private String[] coordinates;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getLastname() {
            return lastname;
        }
        public void setLastname(String lastname) {
            this.lastname = lastname;
        }
        public String getCity() {
            return city;
        }
        public void setCity(String city) {
            this.city = city;
        }
        public String getState() {
            return state;
        }
        public void setState(String state) {
            this.state = state;
        }
        public String[] getCoordinates() {
            return coordinates;
        }
        public void setCoordinates(String[] coordinates) {
            this.coordinates = coordinates;
        }
    }

}

0

逐行读取,然后在每一行中按照相应的限制进行子字符串分割。例如:

private static String[] split(String line) {
    return new String[] {
        line.substring(0, 16).trim(),
        line.substring(17, 32).trim(),
        line.substring(33, 37).trim(),
        line.substring(38, 43).trim(),
        line.substring(44, 48).trim(),
        line.substring(49, 53).trim(),
    };
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接