[英]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,,,,,,,
我正在嘗試將拆分的多個部分添加到數組中。 目前它從 position 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行開頭,指示您似乎不需要的列名稱(但並非總是如此),因此我們可以忽略它的那部分。
我認為在這種特殊情況下的理想情況是一種讀取文本文件的方法,並且可以在讀取該文件時從每一行檢索所有或特定的數據列。 然后將檢索到的數據寫入提供的 output 文件。
一個小問題是一些列數據在引號(“...”)內,其中一些還包含相同的分隔符,用於分隔任何給定記錄行中的所有其他列。 這可能會造成問題,因此在檢索數據時必須小心處理這種情況,否則可能會獲取不完整的數據並將其寫入所需的 output 文件並在二維字符串數組中返回。
我在下面提供的代碼示例在一個方法中完成了所有這些。 它是相對基本的,因此如果需要,您可以自行處理任何特定的增強功能。 該方法包含三個參數,兩個是 String 類型,一個是可選的 int args[],它返回一個包含檢索數據的二維字符串數組。 如果您不希望該方法返回任何內容,則可以稍微減少代碼。
這是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;
}
如您所見,該方法需要三個參數:
csvFilePath 參數:
此處必須提供一個字符串參數,指示要讀取的文本文件在本地文件系統中的位置。 如果文本文件位於 Class-Path 中,那么只需文件名就足夠了。 如果不是,則需要完整的路徑和文件名。
destinationPath 參數:
此處必須提供一個字符串參數,指示 output 文本文件將在本地文件系統中創建和寫入的位置。 如果 output 文件位於應用程序的項目文件夾中,則只需文件名即可。 如果不是,則需要其所需位置的完整路徑和文件名。 確保您的操作系統中存在權限以實現此目的。 如果提供的目標路徑在本地文件系統中尚不存在,則會自動創建它,再次確保您的操作系統中存在權限以實現此目的。
所需的LiteralColumns 參數:
可以在此處提供 integer 數組 ( int[ ] ) 或一系列逗號分隔的 integer arguments ,它們表示從每個數據行中檢索數據所需的文字列。 “文字”是指位於列索引 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);
然后當代碼運行時 output 文件和返回的二維字符串數組將包含:
"Doe, John", "6558 Cook Road, Atlanta, Georgia", 30336
如果沒有 arguments 提供給可選的desiredLiteralColumns參數,則檢索所有列數據,因此:
String[][] myData = getFromCSV("My_CSV_File.csv", "MY_Output_File.txt");
將以下內容放入 output 文件中,返回的二維字符串數組將包含相同的內容。
"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);
}
這應該輸出到控制台 window 並放置在您想要的 output 文件中:
Smith, Lehron, Billable 4.10 , Non Bill 2.57
這與您為所需 output 提供的示例完全相同。 經測試!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.