拉动字符串的多个部分 split

Pulling multiple parts of a string split

我正在阅读的文件如下所示

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 中读取所以它会吐出类似

的内容

Smith、Lehron、Billable 4.10、Non Bill 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);
    }
}

您似乎拥有一个 CSV 格式类型的文本文件,其中有特定行的逗号分隔的柱状数据。然而,通常 CSV 文件将以 Header 行开头,指示您似乎不需要的列名称(尽管并非总是如此),因此我们可以忽略它的那一部分。

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

虽然有一个小问题,但一些列数据在引号 ("...") 内,其中一些还包含非常相同的分隔符,用于分隔任何给定记录行中的所有其他列。这可能会造成问题,因此在检索数据时必须小心处理这种情况,否则可能会获取不完整的数据并将其写入所需的输出文件并 returned 在二维字符串数组中。

我在下面提供的代码示例在一个方法中完成了所有这些。它是相对基本的,因此如果需要的话,您可以处理任何特定的增强功能。该方法包含三个参数,两个是 String 类型,一个是可选的 int args[],​​它 return 是一个包含检索到的数据的二维字符串数组。如果您不希望该方法 return 任何东西,那么可以稍微减少代码。

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

/**
 * This is a very basic parsing type method.<br><br>
 * 
 * Usage: {@code String[][] data = getFromCSV("Data.txt", "DataOutput.txt", 13, 16, 17, 28, 29); }
 * 
 * @param csvFilePath (String) The full path and file name of the Data file.<br>
 * 
 * @param destinationPath (String) The full path and file name of the desired output file. 
 * the retrieved data will be store there.<br>
 * 
 * @param desiredLiteralColumns (Optional - Integer Args or int[] Array) The literal
 * data columns to acquire row data from. The arguments can be provided in any desired
 * order. The returned Array will hold the required data in the order your provided.<br>
 * 
 * @return (2D String Array) Containing columnar data from each data row.
 */
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);
    if (!destinationPath.trim().equals("") && destPath.getParentFile() == null) {
        String fPath = destPath.getAbsolutePath().substring(0, destPath.getAbsolutePath().lastIndexOf("\"));
        new File(fPath).mkdirs();
    }
    else {
        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;
}

如您所见,该方法需要三个参数:

The csvFilePath parmeter:

此处必须提供一个字符串参数,它指示要读取的文本文件在本地文件系统中的位置。如果文本文件位于 Class-Path 中,那么只需要文件名就足够了。如果不是,则需要完整路径和文件名。

The destinationPath parmeter:

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

The desiredLiteralColumns parameter:

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

如果我在文件中有一个数据行,如下所示:

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

并且我们想要检索第 1 列(人名)、第 3 列(地址)和第 4 列(postal 代码)中的数据,然后我们可以向 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);

然后当代码为 运行 时,输出文件和 returned 二维字符串数组将包含:

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

如果没有向可选的 desiredLiteralColumns 参数提供任何参数,则检索 all 列数据,因此:

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

会将以下内容放入输出文件中,returned 二维字符串数组将包含相同的内容。

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

我认为您在 post 示例中提供的数据行中存在定界符定位问题。我认为您缺少一些逗号。 仔细查看。一旦你完成了......要准确构建你需要的东西,你会做这样的事情:

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);
}

这个应该输出到控制台window并放在你想要的输出文件中:

Smith, Lehron, Billable 4.10 , Non Bill 2.57

完全 类似于您为所需输出提供的示例。已测试!