Мои данные хранятся в больших матрицах, которые хранятся в текстовых файлах с миллионами строк и 4 столбцами значений, разделенных запятыми. (В каждом столбце хранится отдельная переменная, а в каждой строке хранятся разные миллисекунды для всех четырех переменных.) В первых дюжинах строк есть также несколько не относящихся к делу данных заголовка. Мне нужно написать код Java для загрузки этих данных в четыре массива, с одним массивом для каждого столбца в матрице TXT. Код Java также должен быть в состоянии сказать, когда заголовок сделан, чтобы первая строка данных могла быть разделена на записи для 4 массивов. Наконец, Java-код должен пройти через миллионы строк данных, повторяя процесс разложения каждой строки на четыре числа, каждое из которых вводится в соответствующий массив для столбца, в котором находится номер.
Может кто-нибудь показать мне, как изменить код ниже, чтобы сделать это?
Я хочу найти самый быстрый способ выполнить эту обработку миллионов строк. Вот мой код:
MainClass2.java
package packages;
public class MainClass2{
public static void main(String[] args){
readfile2 r = new readfile2();
r.openFile();
int x1Count = r.readFile();
r.populateArray(x1Count);
r.closeFile();
}
}
readfile2.java
package packages;
import java.io.*;
import java.util.*;
public class readfile2 {
private Scanner scan1;
private Scanner scan2;
public void openFile(){
try{
scan1 = new Scanner(new File("C:\\test\\samedatafile.txt"));
scan1 = new Scanner(new File("C:\\test\\samedatafile.txt"));
}
catch(Exception e){
System.out.println("could not find file");
}
}
public int readFile(){
int scan1Count = 0;
while(scan1.hasNext()){
scan1.next();
scan1Count += 1;
}
return scan1Count;
}
public double[] populateArray(int scan1Count){
double[] outputArray1 = new double[scan1Count];
double[] outputArray2 = new double[scan1Count];
double[] outputArray3 = new double[scan1Count];
double[] outputArray4 = new double[scan1Count];
int i = 0;
while(scan2.hasNext()){
//what code do I write here to:
// 1.) identify the start of my time series rows after the end of the header rows (e.g. row starts with a number AT LEAST 4 digits in length.)
// 2.) split each time series row's data into a separate new entry for each of the 4 output arrays
i++;
}
return outputArray1, outputArray2, outputArray3, outputArray4;
}
public void closeFile(){
scan1.close();
scan2.close();
}
}
Вот первые 19 строк типичного файла данных:
text and numbers on first line
1 msec/sample
3 channels
ECG
Volts
Z_Hamming_0_05_LPF
Ohms
dz/dt
Volts
min,CH2,CH4,CH41,
,3087747,3087747,3087747,
0,-0.0518799,17.0624,0,
1.66667E-05,-0.0509644,17.0624,-0.00288295,
3.33333E-05,-0.0497437,17.0624,-0.00983428,
5E-05,-0.0482178,17.0624,-0.0161573,
6.66667E-05,-0.0466919,17.0624,-0.0204402,
8.33333E-05,-0.0448608,17.0624,-0.0213986,
0.0001,-0.0427246,17.0624,-0.0207532,
0.000116667,-0.0405884,17.0624,-0.0229672,
EDIT
Я проверил предложение кода Shilaghae. Вроде работает. Однако длина всех полученных массивов такая же, как у x1Count, поэтому нули остаются в тех местах, где код сопоставления с образцом Shilaghae не может разместить число. (Это результат того, как я изначально написал код.)
У меня были проблемы с поиском индексов, где остаются нули, но, похоже, было намного больше нулей, кроме ожидаемых там, где был заголовок. Когда я изобразил производную от вывода temp [1], я увидел ряд резких пиков, где могут быть ложные нули в temp [1]. Если я скажу, где находятся нули в temp [1], temp [2] и temp [3], я смогу изменить сопоставление с образцом, чтобы лучше сохранить все данные.
Кроме того, было бы неплохо просто сократить выходной массив, чтобы он больше не включал строки, в которых заголовок находился во входном файле. Однако, учебники, которые я нашел относительно массивов переменной длины, показывают только упрощенные примеры, такие как:
int[] anArray = {100, 200, 300, 400};
Код может работать быстрее, если он больше не использует scan1 для создания scan1Count. Я не хочу замедлять код, используя неэффективный метод для создания массива переменной длины. И я также не хочу пропускать данные в своих временных рядах в тех случаях, когда сопоставление с образцом не может разбить входную строку на 4 числа. Я бы предпочел оставить нули во временных рядах, чтобы найти их и использовать для отладки сопоставления с образцом.
Может кто-нибудь показать, как это сделать в быстродействующем коде?
ВТОРОЕ РЕДАКТИРОВАНИЕ
Итак
"-{0,1}\\d+.\\d+,"
повторяется для раз в выражении:
"-{0,1}\\d+.\\d+,-{0,1}\\d+.\\d+,-{0,1}\\d+.\\d+,-{0,1}\\d+.\\d+,"
делает
"-{0,1}\\d+.\\d+,"
раскладывается на следующие три утверждения:
"-{0,1}" means that a minus sign occurs zero or one times, while
"\\d+." means that the minus sign(or lack of minus sign) is followed by several digits of any value followed by a decimal point, so that finally
"\\d+," means that the decimal point is followed by several digits of any value?
Если так, то как насчет чисел в моих данных, таких как "1.66667E-05" или "-8.06131E-05"? Я только что отсканировал один из входных файлов, и (из более чем 3 миллионов строк с 4 столбцами) он содержит 638 чисел, содержащих E, из которых 5 были в первом столбце, а 633 - в последнем столбце.
ЗАКЛЮЧИТЕЛЬНОЕ РЕДАКТИРОВАНИЕ
Окончательный код был очень простым и просто включал использование string.split () с "," в качестве регулярного выражения. Для этого мне пришлось вручную удалить заголовки из входного файла, чтобы данные содержали только строки с 4 числами, разделенными запятыми.
Если кому-то интересно, окончательный рабочий код для этого:
public double[][] populateArray(int scan1Count){
double[] outputArray1 = new double[scan1Count];
double[] outputArray2 = new double[scan1Count];
double[] outputArray3 = new double[scan1Count];
double[] outputArray4 = new double[scan1Count];
try {
File tempfile = new File("C:\\test\\mydatafile.txt");
FileInputStream fis = new FileInputStream(tempfile);
DataInputStream in = new DataInputStream(fis);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String strLine;
int i = 0;
while ((strLine = br.readLine()) != null) {
String[] split = strLine.split(",");
outputArray1[i] = Double.parseDouble(split[0]);
outputArray2[i] = Double.parseDouble(split[1]);
outputArray3[i] = Double.parseDouble(split[2]);
outputArray4[i] = Double.parseDouble(split[3]);
i++;
}
} catch (IOException e) {
System.out.println("e for exception is:"+e);
e.printStackTrace();
}
double[][] temp = new double[4][];
temp[0]= outputArray1;
temp[1]= outputArray2;
temp[2]= outputArray3;
temp[3]= outputArray4;
return temp;
}
Спасибо за помощь всем. Я собираюсь закрыть эту ветку сейчас, потому что на вопрос был дан ответ.