I want to read the data from txt, then I will remove the header of the txt and save the data into and array every 2 line, cause it still continues data.
- visitor.txt
1 DAILY REPORT VISITOR
DATE : 02-02-22
0 ------------------------------------------------------------------
NO. DATE NAME ADDRESS
PHONE BIRTHDAY NEED
------------------------------------------------------------------
1 02-02-22 ELIZABETH ZEE WASHINGTON DC
32 62 18-10-1985 BORROW BOOK
2 02-02-22 VICTORIA GEA BRUSEELS
32 64 24-05-1986 VISITOR
3 02-02-22 GEORGE PHILIPS BRUSEELS
32 76 02-05-1990 VISITOR
so, i want the data that save into an array like this.
1 02-02-22 ELIZABETH ZEE WASHINGTON DC 32 62 18-10-1985 BORROW BOOK
2 02-02-22 VICTORIA GEA BRUSEELS 32 64 24-05-1986 VISITOR
3 02-02-22 GEORGE PHILIPS BRUSEELS 32 76 02-05-1990 VISITOR
and this is the code
BufferedReader bR = new BufferedReader(new FileReader(myfile));
int i =0;
String line;
try {
while (line = bufferedReader.readLine()) != null) {
i ;
String data = line.split("\\s", "")
if(data.matches("[0-9]{1,3}\\s. ")) {
String[] dataArray = data.split("\\s", -1);
String[] result = new String[30];
System.arraycopy(fileArray, 0, result, 0, fileArray.length);
String data1 = line.get(i).split("\\s", "")
String[] fileArray1 = data.split("\\s", -1);
String[] result1 = new String[30];
System.arraycopy(fileArray1, 0, result1,0,fileArray1.length);
}
}
The problem here is, i think this code is not effective cause it will be read the second line twice from data and data1. I want every 2 lines will save into one row in the database like the result of txt. Do you have any solution ? I need your help. Thanks :)
CodePudding user response:
It seems unlikely for me that one line would be read multiple times. Try to debug your code to see if that actually happens.
Otherwise, you could really skip the first line before starting processing:
BufferedReader bR = new BufferedReader(new FileReader(myfile));
int i =0;
String line;
try {
// alternative one
String firstline = bufferedReader.readLine();
String secondline = bufferedReader.readLine();
String mergedline = firstline secondline; // the linefeed should have been removed but the data is retained
// alternative two
StringBuilder sb = new StringBuilder();
sb.append(bufferedReader.readLine()); // first line
sb.append(bufferedReader.readLine()); // second line
... = sb.toString(); // now do something with the merged lines
// the other stuff
while (line = bufferedReader.readLine()) != null) {
// process your data lines here
}
}
CodePudding user response:
- The result has actually a dynamic number of records. Then a fixed size array
no longer is suitable. Use
List<String\[\]>
instead:list.add(stringArray)
,list.get(i)
,list.size()
,list.isEmpty()
. - The header seems to consist of 2 lines, but I may err.
- I saw fields with a space, hence one cannot split on
\s
(one or more whitespace characters). I did split on\s\s
. Maybe you should better use the fixed length field boundaries withline1.substring(i1, i2)
. - FileReader uses the encoding on your current computer (=unportable file). I have made it explicit. If it always an US-ASCII file, without special characters, you could use
StandardCharsets.US_ASCII
. Then you can run the software on a Linux server, that normally uses UTF-8.
So without check of data format (which however makes sense):
private void stackOverflow() throws IOException {
List<String[]> data = loadData("mydata.txt");
System.out.println(data.size() " records read");
for (String[] fields: data) {
System.out.println(Arrays.toString(fields));
}
}
private List<String[]> loadData(String myFile) throws IOException {
List<String[]> data = new ArrayList<>();
Path path = Paths.get(myFile);
try (BufferedReader bufferedReader =
Files.newBufferedReader(path, Charset.defaultCharset())) {
if (bufferedReader.readLine() != null
&& bufferedReader.readLine() != null) { // Skip both header lines.
String line1, line2;
while ((line1 = bufferedReader.readLine()) != null
&& (line2 = bufferedReader.readLine()) != null) {
String[] fields1 = line1.split("\\s\\s ", 4); // Split on at least 2 spaces.
if (fields1.length != 4) {
throw new IOException("Wrong number of fields for first line: " line1);
}
String[] fields2 = line2.split("\\s\\s ", 3); // Split on at least 2 spaces.
if (fields1.length != 3) {
throw new IOException("Wrong number of fields for second line: " line2);
}
String[] total = Arrays.copyOf(fields1, 7);
System.arraycopy(fields2, 0, total, 4, fields2.length);
;
data.add(total);
}
if (line1 != null && !line1.isBlank()) {
throw new IOException("Trailing single line: " line1);
}
}
}
return data;
}
Substring is better, safer, than split.
Instead of
String[]
you might userecord
class (since java 14)record Visitor(String no, String date, String name, String address, String phone, String birthday, String need) { } List<Visitor> data = new ArrayList<>(); data.add(new Visitor(fields1[0], fields1[1], fields1[2], fields1[3], fields2[0], fields2[1], fields2[3]);
A record
need little code, however cannot be changed, only replaced in the list.