将字符串拆分成多个部分

问题描述 投票:1回答:1

我正在读取的文件看起来像这样

textBox25,textBox21,textBox20,textBox1,textBox9,textBox10,textBox6,textBox5,textBox4,textBox3,textBox12,textBox11
"Smith, Lehron",2019,40,Billable,4.10,"Smith, Lehron",2019,40,% Billable,61.50 %,% Billable & Appt.,61.50 %
"Smith, Lehron",2019,40,Non Bill.,2.57,,,,,,,

我正在尝试将拆分的多个部分添加到数组中。当前它从位置1吐出他的名字,但我还需要它在Billable 4.10和Non Bill 2.57中读取,以便吐出类似的东西

史密斯,雷隆,可计费4.10,非法案2.57

任何想法或帮助将不胜感激!

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

    Scanner in;
    in = new Scanner (System.in);

    File cisStaffHours = new File("StaffHoursOverviewReport_10102019 (1).txt");
    Scanner s = new Scanner(cisStaffHours);

    PrintWriter outFile;
    outFile = new PrintWriter(new FileWriter("outFile.txt"));

    ArrayList<Tracking> listInfo = new ArrayList<Tracking>();

    while (s.hasNextLine()){

        Tracking c = new Tracking();
        c.name = s.nextLine();

        if(c.name.contains("\"")) {
            c.name=s.nextLine();
            c.name=s.nextLine();
            String[] parts = c.name.split("\"");
            c.name=parts[1];
            listInfo.add(c);
        }
    }

    for(Tracking o: listInfo) {
        outFile.println(o.name);
    }
        outFile.close();
        System.out.println(listInfo);
    }
}
java string split delimiter
1个回答
0
投票

您似乎拥有的是CSV格式的文本文件,其中包含以逗号分隔的特定列数据的特定行。但是,通常CSV文件将以Header行开头,该行指示您似乎不需要的列名(尽管并非总是如此),因此我们可以忽略该部分。

我认为在这种特殊情况下,理想的情况是读取文本文件并可以在读取文件时从每一行中检索所有或特定列的数据的方法。然后将检索到的数据写入提供的输出文件。

不过,一个小问题是某些列数据在引号(“ ...”)内,其中一些还包含完全相同的定界符,该定界符将任何给定记录行中的所有其他列分开。这可能会带来问题,因此在检索数据时必须格外小心,否则可能会获取不完整的数据并将其写入所需的输出文件并在2D字符串数组中返回。

我在下面提供的代码示例在单个方法中完成了所有这一切。它是相对基本的,因此如果需要,则取决于您是否有任何特定的增强功能。该方法包含三个参数,两个为String类型,一个为可选的int args [],它返回包含检索到的数据的二维字符串数组。如果您不希望该方法返回任何内容,则可以减少代码量。

这里是getFromCSV()方法。受到好评:

public static String[][] getFromCSV(String csvFilePath, String destinationPath, 
                                    int... desiredLiteralColumns) {
    String ls = System.lineSeparator();   // The Line-Separator used for current OS.
    /* Does the destination Path exist? 
       If not create it before file is created. */
    File destPath = new File(destinationPath);
    destPath.getParentFile().mkdirs();

    ArrayList<String[]> list = new ArrayList<>();
    ArrayList<String> lineData = new ArrayList<>();
    File cisStaffHours = new File(csvFilePath);
    // 'Try With Resources' is used here to auto-close the reader.
    try (Scanner reader = new Scanner(cisStaffHours)) {
        String fileLine = "";
        // 'Try With Resources' is used here to auto-close the writer.
        try (PrintWriter writer = new PrintWriter(new FileWriter(destPath))) {
            while (reader.hasNextLine()) {
                /* Read lines one at a time. Trim each read in 
                  line of leading or trailing white-spaces (if any).  */
                fileLine = reader.nextLine().trim(); 
                // Skip blank lines (if any).
                if (fileLine.equals("")) {
                    continue;
                }
                /* Split the line based on a comma (,) delimiter)...
                   (DO NOT split on commas within quotation marks!).
                   The regular expression used with the split() method
                   ignores any number of white-spaces before or after
                   the delimiter.                    */
                String[] lineParts = fileLine.split("\\s{0,},\\s{0,}(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)", -1);

                //Do we only want specific columns only?
                if (desiredLiteralColumns.length > 0) {
                    // Yes...
                    lineData.clear(); // Clear the ArrayList in case it already contains something.
                    // Retrieve the desired columns an place them into a String ArrayList...
                    for (int dc : desiredLiteralColumns) {
                        for (int lp = 0; lp < lineParts.length; lp++) {
                            if (dc == (lp + 1)) {
                                lineData.add(lineParts[lp]);
                                break;
                            }
                        }
                    }
                    /* Convert the 'lineData' ArrayList to a 1D String Array
                       and then add that String Array to the 'list' ArrayList. */
                    list.add(lineData.toArray(new String[0]));

                    // Build and Write the acquired data to the desired output file.
                    String dataString = lineData.get(0).replace("\"", "") + ", " + 
                    lineData.get(1) + " " + lineData.get(2) + " , " + 
                    lineData.get(3).replace(".", " ") + lineData.get(4);
                    writer.println(dataString);
                    writer.flush();
                }
                else {
                    // No, we want all columns. Add all columnar data to the ArrayList...
                    list.add(lineParts);
                    // Build and Write the acquired data to the desired output file.
                    String dataString = lineData.get(0).replace("\"", "") + ", " + 
                    lineData.get(1) + " " + lineData.get(2) + " , " + 
                    lineData.get(3).replace(".", " ") + lineData.get(4);
                    writer.println(dataString);
                    writer.flush();
                }
            }
        }
        // Catch and display any exceptions,
        catch (IOException ex) {
            System.out.println("getFromCSV() Method Error!" + ls + ex.getMessage());
        }
    }
    catch (FileNotFoundException ex) {
        System.out.println("getFromCSV() Method Error!" + ls + ex.getMessage());
    }

    /* Convert list to a 2D String Array and then 
       return the 2D Array...         */
    String[][] array = new String[list.size()][];
    for (int i = 0; i < list.size(); i++) {
        array[i] = list.get(i);
    }
    return array;
}

您可以使用的方法需要三个参数:

csvFilePath参数:

此处必须提供字符串参数,该参数指示要读取的文本文件在本地文件系统中的位置。如果文本文件位于类路径内,则仅文件名就足够了。如果不是,则需要完整的路径和文件名。

destinationPath参数:

此处必须提供字符串参数,该参数指示要在本地文件系统中创建和写入输出文本文件的位置。如果输出文件位于应用程序的项目文件夹中,则仅文件名就足够了。如果没有,则需要完整路径和文件名到它所需的位置。确保您的操作系统中存在权限才能实现。如果提供的目标路径在本地文件系统中尚不存在,则会自动创建该路径,请再次确保操作系统中存在权限才能实现。

desiredLiteralColumns参数:

此处可以提供

整数数组(int [])或一系列逗号分隔的整数参数,这些整数参数表示所需的文字列以从每个文件数据行中检索数据。所谓“ literal”,是指位于列索引0的数据实际上是列1。列索引7中的数据实际上是列8。这是您要提供的文字值。这是一个简单的例子:

如果文件中有一个数据行,看起来像:

"Doe, John", 62, "6558 Cook Road, Atlanta, Georgia", 30336, $78,564.77

并且我们想在第一列(人名),第三列(地址)和第四列(邮政编码)中检索数据,然后可以向getFromCSV()方法提供以下内容:] >

String[][] myData = getFromCSV("My_CSV_File.csv", "MY_Output_File.txt", 1, 3, 5);

                                O R

int[] columns = {1, 3, 5};
String[][] myData = getFromCSV("C:\\MyDataFile\\My_CSV_File.csv",
                               "C:\\MyOuputFiles\\MY_Output_File.txt", 
                               columns);

然后在运行代码时,输​​出文件和返回的2D字符串数组将包含:

"Doe, John", "6558 Cook Road, Atlanta, Georgia", 30336

如果没有将参数提供给可选的desiredLiteralColumns

参数,则all检索列数据,因此:
String[][] myData = getFromCSV("My_CSV_File.csv", "MY_Output_File.txt");

将以下内容放入输出文件,并且返回的2D字符串数组将包含相同的内容。

"Doe, John", 62, "6558 Cook Road, Atlanta, Georgia", 30336, $78,564.77

我相信您在帖子中提供的数据行中存在分隔符定位问题,例如。我认为您缺少一些逗号。在仔细地

上查看。完成此操作后。...要完全构建所需的内容,将执行以下操作:
String[][] data = getFromCSV("StaffHoursOverviewReport_10102019 (1).txt",
                             "outFile.txt", 
                             13, 16, 17, 28, 29);
for (int i = 0; i < data.length; i++) {
    String dataString = data[i][0].replace("\"", "") + ", " + 
                        data[i][1] + " " + data[i][2] + " , " + 
                        data[i][3].replace(".", " ") + data[i][4];
    System.out.println(dataString);
}

应该

输出到控制台窗口:
Smith, Lehron, Billable 4.10 , Non Bill 2.57

完全

相似,如您为所需输出提供的示例。
© www.soinside.com 2019 - 2024. All rights reserved.