├── .gitignore ├── README.md ├── build.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src ├── main ├── java │ └── com │ │ └── example │ │ └── readFile │ │ └── readFileJava │ │ ├── Common.java │ │ ├── FileReadingChallenge.java │ │ ├── ReadFileJavaApplicationBufferedReader.java │ │ ├── ReadFileJavaApplicationFileInputStream.java │ │ ├── ReadFileJavaApplicationLineIterator.java │ │ └── ReadFileJavaApplicationStoringOnlySummaryData.java └── resources │ ├── application.properties │ ├── config │ └── test.txt │ └── img │ ├── classRunnerExample.png │ └── intellijRun.png └── test └── java └── com └── example └── readFile └── readFileJava └── ReadFileJavaApplicationTests.java /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | .vscode/ 5 | bin/ 6 | .DS_Store 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | 17 | ### IntelliJ IDEA ### 18 | .idea 19 | *.iws 20 | *.iml 21 | *.ipr 22 | /out/ 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | 31 | ### Files ### 32 | /src/main/resources/config/itcont2.txt -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Java Large File / Data Reading & Performance Testing 2 | 3 | This is an example of 3 different ways to use Java to process big data files. One file is the Java's `bufferedReader()` method, the second is with Java's `fileInputString()` method, and the third way is with the help of the Apache Commons IO package, `lineIterator()`. 4 | 5 | There is also use of Java's date time methods `Instant.now()` and `Duration.between()` to determine the performance of the 3 different implementations, and which is most efficient processing the files. 6 | 7 | ### To Download the Really Large File 8 | Download the large file zip here: https://www.fec.gov/files/bulk-downloads/2018/indiv18.zip 9 | 10 | The main file in the zip: `itcont.txt`. I used the smaller file included in the config folder `test.txt` to test before running my solutions against the larger scale files. 11 | 12 | ### To Run 13 | I used Intellij's handy Spring Boot configurations to create main class runners for each of the three main files I included inside the repo for the purposes of this example. 14 | 15 | Add the file path for one of the files (could be the big one `itcont.txt` or any of its smaller siblings in the `indiv18` folder that were just downloaded - you can see how I set up my relative and hard coded file paths in each of the files), and then run whichever main class file you want by right clicking the file and selecting 'Run'. 16 | [Intellij Run](/src/main/resources/img/intellijRun.png) 17 | 18 | Either run `./gradlew assemble` and then 19 | * `java -cp ./build/libs/readFileJava-0.0.1-SNAPSHOT.jar com.example.readFile.readFileJava.ReadFileJavaApplicationBufferedReader [path-to-file]`, 20 | * `java -cp ./build/libs/readFileJava-0.0.1-SNAPSHOT.jar com.example.readFile.readFileJava.ReadFileJavaApplicationFileInputStream [path-to-file]`, 21 | * `java -cp ./build/libs/readFileJava-0.0.1-SNAPSHOT.jar com.example.readFile.readFileJava.ReadFileJavaApplicationLineIterator [path-to-file]` 22 | * `java -cp ./build/libs/readFileJava-0.0.1-SNAPSHOT.jar com.example.readFile.readFileJava.ReadFileJavaApplicationStoringOnlySummaryData [path-to-file]` 23 | for whichever method you want to run, from the command line. 24 | 25 | If `path-to-file` is omitted, the smaller test file will be used instead. 26 | 27 | Or the easier way: 28 | 29 | You can set up the Spring Boot runner in Intellij, by simply specifying which main class file you want to run. 30 | [Intellij Configuration](/src/main/resources/img/classRunnerExample.png) 31 | 32 | Then you'll see the answers required from the file printed out to the terminal. 33 | 34 | ### To Check Performance Testing 35 | Performance testing is already implemented for all three files as well using `Instant.now()`. You can see the performance for the three methods by passing files of different sizes and seeing how long it takes to process them. 36 | 37 | ### Gotchas 38 | The downloadable file seems to be live data that keeps getting larger. When I downloaded the file in the beginning of Oct 2018, it was 2.55GB. Now, some users have reported it being 3.5GB large, so please be aware some of your results and numbers will differ from mine for that reason. 39 | 40 | ### Acknowledgements 41 | Thanks to [AtomicStryker](https://github.com/AtomicStryker) for his contribution to this repo. He added the `FileReadingChallenge.java` file, which demonstrates an asynchronous way of using fibers from the CompletableFuture API to read the file even faster. I appreciate the addition to provide even more ways to quickly churn through large amounts of data in small amounts of time. 42 | 43 | Thanks also to [Morgen Peschke](https://github.com/morgen-peschke) for his excellent contribution to the repo. He added the `ReadFileJavaApplicationStoringOnlySummaryData.java` file. It demonstrates another, more efficient solution using different data structures to solve the problems. Full details of his thought process and implementation of the code can be read [here](https://medium.com/@morgen.peschke/great-article-code-has-some-issues-e1504f32c0a6). 44 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | mavenCentral() 4 | } 5 | } 6 | 7 | apply plugin: 'java' 8 | apply plugin: 'eclipse' 9 | 10 | group = 'com.example.readFile' 11 | version = '0.0.1-SNAPSHOT' 12 | sourceCompatibility = 1.8 13 | 14 | repositories { 15 | mavenCentral() 16 | } 17 | 18 | jar { 19 | manifest { 20 | attributes "Main-Class": "com.example.readFile.readFileJava.ReadFileJavaApplicationLineIterator" 21 | } 22 | 23 | from { 24 | configurations.compile.collect { 25 | it.isDirectory() ? it : zipTree(it) 26 | } 27 | } 28 | } 29 | 30 | dependencies { 31 | compile group: 'commons-io', name: 'commons-io', version: '2.6' 32 | } 33 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paigen11/read-file-java/63c327e342cdb17e5223e70a922c901eebb7082a/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'readFileJava' 2 | -------------------------------------------------------------------------------- /src/main/java/com/example/readFile/readFileJava/Common.java: -------------------------------------------------------------------------------- 1 | package com.example.readFile.readFileJava; 2 | 3 | class Common { 4 | static String getPathToTargetFile(String[] args) { 5 | if (args.length >= 1) { 6 | return args[0]; 7 | } 8 | return "src/main/resources/config/test.txt"; 9 | } 10 | 11 | private Common() {} 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/example/readFile/readFileJava/FileReadingChallenge.java: -------------------------------------------------------------------------------- 1 | package com.example.readFile.readFileJava; 2 | 3 | import org.apache.commons.io.FileUtils; 4 | import org.apache.commons.io.LineIterator; 5 | 6 | import java.io.File; 7 | import java.io.IOException; 8 | import java.text.ParseException; 9 | import java.text.SimpleDateFormat; 10 | import java.time.Duration; 11 | import java.time.Instant; 12 | import java.util.Calendar; 13 | import java.util.Date; 14 | import java.util.Map; 15 | import java.util.concurrent.CompletableFuture; 16 | import java.util.concurrent.ConcurrentHashMap; 17 | 18 | /** 19 | * More efficient java solution of the challenge 20 | */ 21 | public class FileReadingChallenge { 22 | 23 | // for memory conservation reasons i cheated and looked up the line count beforehand 24 | // we _could_ just use ArrayList for keeping them and convert to arrays after but meh 25 | private static final int LINE_COUNT = 18245416; 26 | 27 | static final String[] names = new String[LINE_COUNT]; 28 | static final String[] firstNames = new String[LINE_COUNT]; 29 | static int resultsToWaitFor = 0; 30 | 31 | static final ConcurrentHashMap firstNameCount = new ConcurrentHashMap<>(); 32 | static final ConcurrentHashMap monthCount = new ConcurrentHashMap<>(); 33 | 34 | public static void main(String[] args) { 35 | System.out.println("Hello World!"); 36 | 37 | File f = new File(Common.getPathToTargetFile(args)); 38 | if (!f.exists() || !f.canRead()) { 39 | System.out.println("Problem reading file " + f); 40 | } 41 | 42 | int lineCount = 0; 43 | Instant lineRead = Instant.now(); 44 | try { 45 | LineIterator it = FileUtils.lineIterator(f, "UTF-8"); 46 | while (it.hasNext()) { 47 | String line = it.nextLine(); 48 | lineCount++; 49 | if (lineCount < 10) { 50 | // print some of the data so we can see what it looks like - most editors fail to display the file 51 | System.out.println("line " + (lineCount + 1) + " printout: " + line); 52 | } 53 | 54 | incrementLock(); 55 | if (lineCount % 1000000 == 0) { 56 | System.out.println("reading line " + lineCount + ", fibers running: " + (resultsToWaitFor - 1)); 57 | // optimization: as it is possible for I/O to supply new fibers faster than can be completed, 58 | // which chokes and stalls the JVM, we pause the line reading if the fiber count is too high. 59 | while (resultsToWaitFor > 9999) { 60 | try { 61 | System.out.println("waiting for fiber count to drop, now at: " + resultsToWaitFor); 62 | Thread.sleep(1000); 63 | } catch (InterruptedException e) { 64 | e.printStackTrace(); 65 | } 66 | } 67 | } 68 | // optimization: reading a line and doing anything with the content is decoupled from each other 69 | // and asynchronous. We use Fibers, from the CompletableFuture API 70 | CompletableFuture.runAsync(new LineRunnable(line, lineCount)).thenAcceptAsync(whenDone -> decrementLock()); 71 | } 72 | } catch (IOException e) { 73 | e.printStackTrace(); 74 | return; 75 | } 76 | 77 | Instant lineReadDone = Instant.now(); 78 | long millis = Duration.between(lineRead, lineReadDone).toMillis(); 79 | System.out.printf("%d lines read and supplied in %d milliseconds\n", lineCount, millis); 80 | 81 | // now keep querying our lock until it indicates that all fibers have finished 82 | int waitCount = 0; 83 | while (resultsToWaitFor > 0) { 84 | try { 85 | waitCount++; 86 | if (waitCount % 10 == 0) { 87 | // give some user feedback 88 | System.out.println("fibers not done yet: " + resultsToWaitFor); 89 | } 90 | Thread.sleep(100); 91 | } catch (InterruptedException e) { 92 | e.printStackTrace(); 93 | } 94 | } 95 | 96 | Instant parsingDone = Instant.now(); 97 | millis = Duration.between(lineReadDone, parsingDone).toMillis(); 98 | System.out.printf("fibers kept parsing async for (approx) %d milliseconds longer\n", millis); 99 | 100 | System.out.println(); 101 | // present the solutions! 102 | System.out.println("name 432: " + names[431]); 103 | System.out.println("name 43243: " + names[43242]); 104 | 105 | // technically these last steps could be async too but it is not worth it here 106 | int highestNameCount = 0; 107 | String mostCommonName = null; 108 | for (Map.Entry entry : firstNameCount.entrySet()) { 109 | if (entry.getValue() > highestNameCount) { 110 | mostCommonName = entry.getKey(); 111 | highestNameCount = entry.getValue(); 112 | } 113 | } 114 | System.out.println("most common name is " + mostCommonName + " with " + highestNameCount + " occurences"); 115 | System.out.println("now printing months and occurrences:"); 116 | for (Map.Entry entry : monthCount.entrySet()) { 117 | System.out.println("month " + entry.getKey() + " with a count of " + entry.getValue()); 118 | } 119 | } 120 | 121 | // we need to prevent race conditions on our locking variable 122 | static synchronized void incrementLock() { 123 | resultsToWaitFor++; 124 | } 125 | 126 | static synchronized void decrementLock() { 127 | resultsToWaitFor--; 128 | } 129 | 130 | private static class LineRunnable implements Runnable { 131 | 132 | final String input; 133 | final int index; 134 | 135 | LineRunnable(String line, int indexOfLine) { 136 | input = line; 137 | index = indexOfLine - 1; 138 | } 139 | 140 | @Override 141 | public void run() { 142 | if (index < 10) { 143 | // we are somewhat paranoid about our fibers starting... 144 | System.out.println("fiber started for line " + (index + 1)); 145 | } 146 | String[] columns = input.split("\\|"); 147 | if (columns.length < 8) { 148 | return; 149 | } 150 | names[index] = columns[7]; 151 | String[] nameFragments = columns[7].split(","); 152 | // i will just disregard anything not following the "NAME, SURNAME" template 153 | if (nameFragments.length == 2) { 154 | firstNames[index] = nameFragments[1]; 155 | // amass a count 156 | Integer count = firstNameCount.getOrDefault(nameFragments[1], 0); 157 | firstNameCount.put(nameFragments[1], count + 1); 158 | } 159 | 160 | // like 201701230300133512 161 | String dateString = columns[4]; 162 | if (dateString.length() >= 8) { 163 | // dont need to parse the whole date fragment, in fact this is overkill too 164 | SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); 165 | try { 166 | Date date = sdf.parse(dateString.substring(0, 8)); 167 | Calendar calendar = Calendar.getInstance(); 168 | calendar.setTime(date); 169 | int year = calendar.get(Calendar.YEAR); 170 | int month = calendar.get(Calendar.MONTH); 171 | String monthString = String.format("%d-%d", month, year); 172 | Integer count = monthCount.getOrDefault(monthString, 0); 173 | monthCount.put(monthString, count + 1); 174 | } catch (ParseException e) { 175 | e.printStackTrace(); 176 | } 177 | } 178 | if (index < 10) { 179 | // we are somewhat paranoid about our fibers finishing... 180 | System.out.println("fiber finished for line " + (index + 1)); 181 | } 182 | } 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /src/main/java/com/example/readFile/readFileJava/ReadFileJavaApplicationBufferedReader.java: -------------------------------------------------------------------------------- 1 | package com.example.readFile.readFileJava; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.File; 5 | import java.io.FileReader; 6 | import java.io.IOException; 7 | import java.time.Duration; 8 | import java.time.Instant; 9 | import java.util.ArrayList; 10 | import java.util.Collections; 11 | import java.util.Comparator; 12 | import java.util.HashMap; 13 | import java.util.LinkedList; 14 | import java.util.Map; 15 | import java.util.Map.Entry; 16 | 17 | public class ReadFileJavaApplicationBufferedReader { 18 | 19 | public static void main(String[] args) { 20 | try { 21 | 22 | File f = new File(Common.getPathToTargetFile(args)); 23 | 24 | try (BufferedReader b = new BufferedReader(new FileReader(f))) { 25 | 26 | String readLine = ""; 27 | 28 | // get total line count 29 | Instant lineCountStart = Instant.now(); 30 | int lines = 0; 31 | 32 | Instant namesStart = Instant.now(); 33 | ArrayList names = new ArrayList<>(); 34 | 35 | // get the 432nd and 43243 names 36 | ArrayList indexes = new ArrayList<>(); 37 | 38 | indexes.add(1); 39 | indexes.add(433); 40 | indexes.add(43244); 41 | 42 | // count the number of donations by month 43 | Instant donationsStart = Instant.now(); 44 | ArrayList dates = new ArrayList<>(); 45 | 46 | // count the occurrences of first name 47 | Instant commonNameStart = Instant.now(); 48 | ArrayList firstNames = new ArrayList<>(); 49 | 50 | 51 | System.out.println("Reading file using Buffered Reader"); 52 | 53 | while ((readLine = b.readLine()) != null) { 54 | lines++; 55 | // System.out.println(readLine); 56 | 57 | // get all the names 58 | String array1[] = readLine.split("\\s*\\|\\s*"); 59 | String name = array1[7]; 60 | names.add(name); 61 | if(indexes.contains(lines)){ 62 | System.out.println("Name: " + names.get(lines - 1) + " at index: " + (lines - 1)); 63 | } 64 | 65 | if(name.contains(", ")) { 66 | 67 | String array2[] = (name.split(", ")); 68 | String firstHalfOfName = array2[1].trim(); 69 | 70 | if (!firstHalfOfName.isEmpty()) { 71 | if (firstHalfOfName.contains(" ")) { 72 | String array3[] = firstHalfOfName.split(" "); 73 | String firstName = array3[0].trim(); 74 | firstNames.add(firstName); 75 | } else { 76 | firstNames.add(firstHalfOfName); 77 | } 78 | } 79 | } 80 | 81 | String rawDate = array1[4]; 82 | String month = rawDate.substring(4,6); 83 | String year = rawDate.substring(0,4); 84 | String formattedDate = month + "-" + year; 85 | dates.add(formattedDate); 86 | 87 | } 88 | 89 | Instant namesEnd = Instant.now(); 90 | long timeElapsedNames = Duration.between(namesStart, namesEnd).toMillis(); 91 | System.out.println("Name time: " + timeElapsedNames + "ms"); 92 | 93 | System.out.println("Total file line count: " + lines); 94 | Instant lineCountEnd = Instant.now(); 95 | long timeElapsedLineCount = Duration.between(lineCountStart, lineCountEnd).toMillis(); 96 | System.out.println("Line count time: " + timeElapsedLineCount + "ms"); 97 | 98 | HashMap dateMap = new HashMap<>(); 99 | for(String date:dates){ 100 | Integer count = dateMap.get(date); 101 | if (count == null) { 102 | dateMap.put(date, 1); 103 | } else { 104 | dateMap.put(date, count + 1); 105 | } 106 | } 107 | for (Map.Entry entry : dateMap.entrySet()) { 108 | String key = entry.getKey(); 109 | Integer value = entry.getValue(); 110 | System.out.println("Donations per month and year: " + key + " and donation count: " + value); 111 | 112 | } 113 | Instant donationsEnd = Instant.now(); 114 | long timeElapsedDonations = Duration.between(donationsStart, donationsEnd).toMillis(); 115 | System.out.println("Donations time: " + timeElapsedDonations + "ms"); 116 | 117 | HashMap map = new HashMap<>(); 118 | for(String name:firstNames){ 119 | Integer count = map.get(name); 120 | if (count == null) { 121 | map.put(name, 1); 122 | } else { 123 | map.put(name, count + 1); 124 | } 125 | } 126 | 127 | LinkedList> list = new LinkedList<>(map.entrySet()); 128 | 129 | Collections.sort(list, new Comparator >() { 130 | public int compare(Map.Entry o1, 131 | Map.Entry o2) 132 | { 133 | return (o2.getValue()).compareTo(o1.getValue()); 134 | } 135 | }); 136 | System.out.println("The most common first name is: " + list.get(0).getKey() + " and it occurs: " + list.get(0).getValue() + " times."); 137 | Instant commonNameEnd = Instant.now(); 138 | long timeElapsedCommonName = Duration.between(commonNameStart, commonNameEnd).toMillis(); 139 | System.out.println("Most common name time: " + timeElapsedCommonName + "ms"); 140 | 141 | } 142 | 143 | } catch (IOException e) { 144 | e.printStackTrace(); 145 | } 146 | } 147 | } 148 | 149 | -------------------------------------------------------------------------------- /src/main/java/com/example/readFile/readFileJava/ReadFileJavaApplicationFileInputStream.java: -------------------------------------------------------------------------------- 1 | package com.example.readFile.readFileJava; 2 | 3 | import java.io.File; 4 | import java.io.FileInputStream; 5 | import java.io.FileNotFoundException; 6 | import java.io.IOException; 7 | import java.time.Duration; 8 | import java.time.Instant; 9 | import java.util.ArrayList; 10 | import java.util.Collections; 11 | import java.util.Comparator; 12 | import java.util.HashMap; 13 | import java.util.LinkedList; 14 | import java.util.Map; 15 | import java.util.Map.Entry; 16 | import java.util.Scanner; 17 | 18 | public class ReadFileJavaApplicationFileInputStream { 19 | 20 | public static void main(String[] args) throws IOException { 21 | File f = new File(Common.getPathToTargetFile(args)); 22 | 23 | try { 24 | FileInputStream inputStream = new FileInputStream(f); 25 | Scanner sc = new Scanner(inputStream, "UTF-8"); 26 | 27 | // get total line count 28 | Instant lineCountStart = Instant.now(); 29 | int lines = 0; 30 | 31 | Instant namesStart = Instant.now(); 32 | ArrayList names = new ArrayList<>(); 33 | 34 | // get the 432nd and 43243 names 35 | ArrayList indexes = new ArrayList<>(); 36 | 37 | indexes.add(1); 38 | indexes.add(433); 39 | indexes.add(43244); 40 | 41 | // count the number of donations by month 42 | Instant donationsStart = Instant.now(); 43 | ArrayList dates = new ArrayList<>(); 44 | 45 | // count the occurrences of first name 46 | Instant commonNameStart = Instant.now(); 47 | ArrayList firstNames = new ArrayList<>(); 48 | 49 | 50 | System.out.println("Reading file using File Input Stream"); 51 | 52 | while (sc.hasNextLine()) { 53 | String line = sc.nextLine(); 54 | lines++; 55 | // System.out.println(line); 56 | 57 | // get all the names 58 | String array1[] = line.split("\\s*\\|\\s*"); 59 | String name = array1[7]; 60 | names.add(name); 61 | if (indexes.contains(lines)) { 62 | System.out.println("Name: " + names.get(lines - 1) + " at index: " + (lines - 1)); 63 | } 64 | 65 | if (name.contains(", ")) { 66 | 67 | String array2[] = (name.split(", ")); 68 | String firstHalfOfName = array2[1].trim(); 69 | 70 | if (!firstHalfOfName.isEmpty()) { 71 | if (firstHalfOfName.contains(" ")) { 72 | String array3[] = firstHalfOfName.split(" "); 73 | String firstName = array3[0].trim(); 74 | firstNames.add(firstName); 75 | } else { 76 | firstNames.add(firstHalfOfName); 77 | } 78 | } 79 | } 80 | 81 | String rawDate = array1[4]; 82 | String month = rawDate.substring(4, 6); 83 | String year = rawDate.substring(0, 4); 84 | String formattedDate = month + "-" + year; 85 | dates.add(formattedDate); 86 | 87 | } 88 | sc.close(); 89 | 90 | Instant namesEnd = Instant.now(); 91 | long timeElapsedNames = Duration.between(namesStart, namesEnd).toMillis(); 92 | System.out.println("Name time: " + timeElapsedNames + "ms"); 93 | 94 | System.out.println("Total file line count: " + lines); 95 | Instant lineCountEnd = Instant.now(); 96 | long timeElapsedLineCount = Duration.between(lineCountStart, lineCountEnd).toMillis(); 97 | System.out.println("Line count time: " + timeElapsedLineCount + "ms"); 98 | 99 | HashMap dateMap = new HashMap<>(); 100 | for (String date : dates) { 101 | Integer count = dateMap.get(date); 102 | if (count == null) { 103 | dateMap.put(date, 1); 104 | } else { 105 | dateMap.put(date, count + 1); 106 | } 107 | } 108 | for (Map.Entry entry : dateMap.entrySet()) { 109 | String key = entry.getKey(); 110 | Integer value = entry.getValue(); 111 | System.out.println("Donations per month and year: " + key + " and donation count: " + value); 112 | 113 | } 114 | Instant donationsEnd = Instant.now(); 115 | long timeElapsedDonations = Duration.between(donationsStart, donationsEnd).toMillis(); 116 | System.out.println("Donations time: " + timeElapsedDonations + "ms"); 117 | 118 | HashMap map = new HashMap<>(); 119 | for (String name : firstNames) { 120 | Integer count = map.get(name); 121 | if (count == null) { 122 | map.put(name, 1); 123 | } else { 124 | map.put(name, count + 1); 125 | } 126 | } 127 | 128 | LinkedList> list = new LinkedList<>(map.entrySet()); 129 | 130 | Collections.sort(list, new Comparator>() { 131 | public int compare(Map.Entry o1, 132 | Map.Entry o2) { 133 | return (o2.getValue()).compareTo(o1.getValue()); 134 | } 135 | }); 136 | System.out.println("The most common first name is: " + list.get(0).getKey() + " and it occurs: " + list.get(0).getValue() + " times."); 137 | Instant commonNameEnd = Instant.now(); 138 | long timeElapsedCommonName = Duration.between(commonNameStart, commonNameEnd).toMillis(); 139 | System.out.println("Most common name time: " + timeElapsedCommonName + "ms"); 140 | 141 | } catch (FileNotFoundException e) { 142 | e.printStackTrace(); 143 | } 144 | } 145 | } 146 | 147 | 148 | -------------------------------------------------------------------------------- /src/main/java/com/example/readFile/readFileJava/ReadFileJavaApplicationLineIterator.java: -------------------------------------------------------------------------------- 1 | package com.example.readFile.readFileJava; 2 | 3 | import org.apache.commons.io.FileUtils; 4 | import org.apache.commons.io.LineIterator; 5 | 6 | import java.io.File; 7 | import java.io.FileNotFoundException; 8 | import java.io.IOException; 9 | import java.time.Duration; 10 | import java.time.Instant; 11 | import java.util.ArrayList; 12 | import java.util.Collections; 13 | import java.util.Comparator; 14 | import java.util.HashMap; 15 | import java.util.LinkedList; 16 | import java.util.Map; 17 | import java.util.Map.Entry; 18 | 19 | public class ReadFileJavaApplicationLineIterator { 20 | public static void main(String[] args) throws IOException { 21 | File f = new File(Common.getPathToTargetFile(args)); 22 | 23 | try { 24 | LineIterator it = FileUtils.lineIterator(f, "UTF-8"); 25 | 26 | // get total line count 27 | Instant lineCountStart = Instant.now(); 28 | int lines = 0; 29 | 30 | Instant namesStart = Instant.now(); 31 | ArrayList names = new ArrayList<>(); 32 | 33 | // get the 432nd and 43243 names 34 | ArrayList indexes = new ArrayList<>(); 35 | 36 | indexes.add(1); 37 | indexes.add(433); 38 | indexes.add(43244); 39 | 40 | // count the number of donations by month 41 | Instant donationsStart = Instant.now(); 42 | ArrayList dates = new ArrayList<>(); 43 | 44 | // count the occurrences of first name 45 | Instant commonNameStart = Instant.now(); 46 | ArrayList firstNames = new ArrayList<>(); 47 | 48 | 49 | System.out.println("Reading file using Line Iterator"); 50 | 51 | while (it.hasNext()) { 52 | String line = it.nextLine(); 53 | lines++; 54 | // System.out.println(line); 55 | 56 | // get all the names 57 | String array1[] = line.split("\\s*\\|\\s*"); 58 | String name = array1[7]; 59 | names.add(name); 60 | if (indexes.contains(lines)) { 61 | System.out.println("Name: " + names.get(lines - 1) + " at index: " + (lines - 1)); 62 | } 63 | 64 | if (name.contains(", ")) { 65 | 66 | String array2[] = (name.split(", ")); 67 | String firstHalfOfName = array2[1].trim(); 68 | 69 | if (!firstHalfOfName.isEmpty()) { 70 | if (firstHalfOfName.contains(" ")) { 71 | String array3[] = firstHalfOfName.split(" "); 72 | String firstName = array3[0].trim(); 73 | firstNames.add(firstName); 74 | } else { 75 | firstNames.add(firstHalfOfName); 76 | } 77 | } 78 | } 79 | 80 | String rawDate = array1[4]; 81 | String month = rawDate.substring(4, 6); 82 | String year = rawDate.substring(0, 4); 83 | String formattedDate = month + "-" + year; 84 | dates.add(formattedDate); 85 | 86 | } 87 | 88 | Instant namesEnd = Instant.now(); 89 | long timeElapsedNames = Duration.between(namesStart, namesEnd).toMillis(); 90 | System.out.println("Name time: " + timeElapsedNames + "ms"); 91 | 92 | System.out.println("Total file line count: " + lines); 93 | Instant lineCountEnd = Instant.now(); 94 | long timeElapsedLineCount = Duration.between(lineCountStart, lineCountEnd).toMillis(); 95 | System.out.println("Line count time: " + timeElapsedLineCount + "ms"); 96 | 97 | HashMap dateMap = new HashMap<>(); 98 | for (String date : dates) { 99 | Integer count = dateMap.get(date); 100 | if (count == null) { 101 | dateMap.put(date, 1); 102 | } else { 103 | dateMap.put(date, count + 1); 104 | } 105 | } 106 | for (Map.Entry entry : dateMap.entrySet()) { 107 | String key = entry.getKey(); 108 | Integer value = entry.getValue(); 109 | System.out.println("Donations per month and year: " + key + " and donation count: " + value); 110 | 111 | } 112 | Instant donationsEnd = Instant.now(); 113 | long timeElapsedDonations = Duration.between(donationsStart, donationsEnd).toMillis(); 114 | System.out.println("Donations time: " + timeElapsedDonations + "ms"); 115 | 116 | HashMap map = new HashMap<>(); 117 | for (String name : firstNames) { 118 | Integer count = map.get(name); 119 | if (count == null) { 120 | map.put(name, 1); 121 | } else { 122 | map.put(name, count + 1); 123 | } 124 | } 125 | 126 | LinkedList> list = new LinkedList<>(map.entrySet()); 127 | 128 | Collections.sort(list, new Comparator>() { 129 | public int compare(Map.Entry o1, 130 | Map.Entry o2) { 131 | return (o2.getValue()).compareTo(o1.getValue()); 132 | } 133 | }); 134 | System.out.println("The most common first name is: " + list.get(0).getKey() + " and it occurs: " + list.get(0).getValue() + " times."); 135 | Instant commonNameEnd = Instant.now(); 136 | long timeElapsedCommonName = Duration.between(commonNameStart, commonNameEnd).toMillis(); 137 | System.out.println("Most common name time: " + timeElapsedCommonName + "ms"); 138 | 139 | } catch (FileNotFoundException e) { 140 | e.printStackTrace(); 141 | } 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /src/main/java/com/example/readFile/readFileJava/ReadFileJavaApplicationStoringOnlySummaryData.java: -------------------------------------------------------------------------------- 1 | package com.example.readFile.readFileJava; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.File; 5 | import java.io.FileReader; 6 | import java.io.IOException; 7 | import java.time.Duration; 8 | import java.time.Instant; 9 | import java.util.*; 10 | 11 | /** 12 | * Alternate implementation exploring the effects of tuning the amount of data stored in memory and the data structures 13 | * used throughout. 14 | * 15 | * Based on {@link com.example.readFile.readFileJava.ReadFileJavaApplicationBufferedReader}, diversions will be noted 16 | * as comments in the body of {@link ReadFileJavaApplicationStoringOnlySummaryData#main(String[])} 17 | */ 18 | public class ReadFileJavaApplicationStoringOnlySummaryData { 19 | 20 | public static void main(String[] args) { 21 | try { 22 | File f = new File(Common.getPathToTargetFile(args)); 23 | try (BufferedReader reader = new BufferedReader(new FileReader(f))) { 24 | 25 | String readLine; 26 | 27 | Instant start = Instant.now(); 28 | int lines = 0; 29 | 30 | // While the runtime differences between a lookup for ArrayList or HashSet for a 3 element collection 31 | // are very minimal, HashSet is much more clear about the intended purpose of `indexes`. 32 | Set indexes = new HashSet<>(); 33 | indexes.add(1); 34 | indexes.add(433); 35 | indexes.add(43244); 36 | 37 | // Because only the summary data is stored, all that's needed is the count for each month or name so 38 | // we can eliminate all but two of the data structures that were used to hold intermediate values. 39 | Map donationsPerYearMonth = new HashMap<>(); 40 | Map firstNameOccurrences = new HashMap<>(); 41 | 42 | while ((readLine = reader.readLine()) != null) { 43 | lines++; 44 | String array1[] = readLine.split("\\s*\\|\\s*"); 45 | String name = array1[7]; 46 | if (indexes.contains(lines)) { 47 | // Storing, then immediately retrieving the name was simplified down to simply printing 48 | // the values. 49 | System.out.println("Name: " + name + " at index: " + (lines - 1)); 50 | } 51 | 52 | if (name.contains(", ")) { 53 | String array2[] = (name.split(", ")); 54 | String firstHalfOfName = array2[1].trim(); 55 | 56 | if (!firstHalfOfName.isEmpty()) { 57 | if (firstHalfOfName.contains(" ")) { 58 | String array3[] = firstHalfOfName.split(" "); 59 | String firstName = array3[0].trim(); 60 | // As we only care about how many times a particular first name shows up, 61 | // we don’t need to store every instance we come across, just storing a 62 | // single copy and how many times it occurs is more than sufficient. 63 | firstNameOccurrences.merge(firstName, 1, (a, b) -> a + b); 64 | } else { 65 | // This would have been possible even if we didn't have `merge`, but having 66 | // it does make things nicely concise. 67 | firstNameOccurrences.merge(firstHalfOfName, 1, (a, b) -> a + b); 68 | } 69 | } 70 | } 71 | 72 | String rawDate = array1[4]; 73 | String month = rawDate.substring(4, 6); 74 | String year = rawDate.substring(0, 4); 75 | String formattedDate = month + "-" + year; 76 | 77 | // Same optimization here as with the first name. 78 | donationsPerYearMonth.merge(formattedDate, 1, (a, b) -> a + b); 79 | } 80 | 81 | // One of the side effects of moving most of the logic into the loop is that there 82 | // isn’t much to time outside the loop. On the upside, the previous timing information 83 | // measured time-to-output rather than time-calculating, so the utility of the omitted 84 | // information was a YMMV situation to begin with. 85 | Instant end = Instant.now(); 86 | System.out.println("Total file line count: " + lines); 87 | Duration timeElapsedLineCount = Duration.between(start, end); 88 | // In addition to the milliseconds, the elapsed time is printed in ISO-8601 duration format. 89 | // Once you are familiar with the format, it's much easier to compare times if 121449ms is also 90 | // printed as PT2M1.449S (2 minutes, 1.449 seconds) 91 | System.out.println("Time: " + timeElapsedLineCount.toMillis() + "ms (" + timeElapsedLineCount + ")"); 92 | 93 | donationsPerYearMonth.forEach((key, value) -> 94 | System.out.println("Donations per month and year: " + key + " and donation count: " + value) 95 | ); 96 | 97 | // ArrayList vs LinkedList is really context dependent. LinkedList is much better for 98 | // building up data by prepending, but you can’t beat ArrayList for random access. One 99 | // of the consequences of this is that, if you’re doing an in-place sort, ArrayList is 100 | // generally a better structure to use. 101 | List> list = new ArrayList<>(firstNameOccurrences.entrySet()); 102 | list.sort(Comparator.comparing(o -> -o.getValue())); 103 | Map.Entry head = list.get(0); 104 | System.out.println("The most common first name is: " + head.getKey() + " and it occurs: " + head.getValue() + " times."); 105 | } 106 | 107 | } catch (IOException e) { 108 | e.printStackTrace(); 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paigen11/read-file-java/63c327e342cdb17e5223e70a922c901eebb7082a/src/main/resources/application.properties -------------------------------------------------------------------------------- /src/main/resources/config/test.txt: -------------------------------------------------------------------------------- 1 | C00177436|N|M2|P|201702039042410893|15|IND|MAKER, SCOTT T.|NORTH YARMOUTH|ME|040976952|UNUM|SVP, DEPUTY GENERAL COUNSEL, BUSINESS|01312017|384||PR2260663445050|1147350||P/R DEDUCTION ($192.00 BI-WEEKLY)|4020820171370029336 2 | C00095109|N|M2|P|201702109049341736|15|IND|LEFKIN, PETER|WASHINGTON|DC|200162218|ALLIANZ LIFE NORTH AMERICA|SR. V.P. - GOVERNMENT & EXTERNAL AFFAI|01312017|380||PR282813516201|1148519||P/R DEDUCTION ($190.00 SEMI-MONTHLY)|4021020171370599168 3 | C00095109|N|M2|P|201702109049341736|15|IND|BURNS, THOMAS|EXCELSIOR|MN|553318325|ALLIANZ LIFE NORTH AMERICA|CHIEF DISTRIBUTION OFFICER|01312017|240||PR283051916201|1148519||P/R DEDUCTION ($120.00 SEMI-MONTHLY)|4021020171370599169 4 | C00095109|N|M2|P|201702109049341736|15|IND|WHITE, WALTER|STILLWATER|MN|550822150|ALLIANZ LIFE NORTH AMERICA|CHIEF ADMINISTRATIVE OFFICER|01312017|400||PR301778416201|1148519||P/R DEDUCTION ($200.00 SEMI-MONTHLY)|4021020171370599170 5 | C00095109|N|M2|P|201702109049341737|15|IND|CEPEK, GRETCHEN|EDINA|MN|554362650|ALLIANZ LIFE NORTH AMERICA|LEGAL OPERATIONS/ATTORNEY|01312017|240||PR340591816201|1148519||P/R DEDUCTION ($120.00 SEMI-MONTHLY)|4021020171370599171 6 | C00399063|N|M2|P|201702109049341767|15|IND|CHAUVETTE, DEREK WILLIAM|SHAKER HEIGHTS|OH|441223447|KEYBANK NATIONAL ASSOCIATION|HEAD OF PUBLIC SECTOR|01312017|230||PR54372113107|1148536||P/R DEDUCTION ($115.38 BI-WEEKLY)|4021020171370599172 7 | C00399063|N|M2|P|201702109049341767|15|IND|PAINE III, ANDREW J|CLEVELAND HEIGHTS|OH|441184027|KEYBANC CAPITAL MARKETS INC.|CO-HEAD CORPORATE BANK|01312017|384||PR56880213107|1148536||P/R DEDUCTION ($192.30 BI-WEEKLY)|4021020171370599173 8 | C00412098|N|M2|P|201702109049342765|15|IND|BUCKNER, CHARLES E.|BAKERSFILED|CA|93389|JOINT HEIRS FOOD CORPORATION|PRESIDENT|01062017|600||3170|1148557|||4021020171370599544 9 | C00412098|N|M2|P|201702109049342765|15|IND|KOHL, LARUE|GUNTERSVILLE|AL|35976|KING KOHL FOOD SERVICES, INC.|FRANCHISEE|01042017|500||3165|1148557|||4021020171370599545 10 | C00412098|N|M2|P|201702109049342765|15|IND|LAMBOS, GEORGE|MASSILLON|OH|44646|KENDALL HOUSE INC|PRESIDENT|01042017|2000||3159|1148557|||4021020171370599546 11 | C00412098|N|M2|P|201702109049342766|15|IND|MCSWAIN, LYNN|PARRISH|FL|34219|FERBER AND SONS, INC.|CFO|01052017|400||3166|1148557|||4021020171370599547 12 | C00412098|N|M2|P|201702109049342766|15|IND|OVERCASH, ERIC|KANNAPOLIS|NC|28081|O INC|CEO|01042017|800||3161|1148557|||4021020171370599548 13 | C00412098|N|M2|P|201702109049342766|15|IND|PEEPLES, VICTOR|MADISON|GA|30650|STAR BRANDS IV|FRANCHISEE|01052017|1500||3167|1148557|||4021020171370599549 14 | C00412098|N|M2|P|201702109049342767|15|IND|POTTER, NICHOLAS|FAYETTEVILLE|NC|28301|PARRIS & POTTER MANAGEMENT CORP|VICE PRESIDENT|01042017|500||3163|1148557|||4021020171370599550 15 | C00412098|N|M2|P|201702109049342767|15|IND|SANDERS, DOYLE|ADA|OK|74820|KFC OF OKLAHOMA INC|FRANCHISEE|01042017|250||3164|1148557|||4021020171370599551 16 | C00412098|N|M2|P|201702109049342767|15|IND|SHELTON, BONNY B.|DANVILLE|VA|24541|BACON ENTERPRISES, INC.|PRESIDENT|01312017|1100||3157|1148557|||4021020171370599552 17 | C00412098|N|M2|P|201702109049342768|15|IND|SIBERT, SAMUEL L.|KIRKLAND|WA|98072|NORTHWEST RESTAURANTS INC.|CEO|01042017|5000||3162|1148557|||4021020171370599553 18 | C00412098|N|M2|P|201702109049342768|15|IND|WEST, CHARLES T.|LAUREL|MS|39442|WEST QUALITY FOOD SERVICE INC|FRANCHISEE|01312017|1000||3158|1148557|||4021020171370599554 19 | C00401224|A|M3|P|201804039098807622|24T|IND|MOORE, JOHN|NEW YORK|NY|10011|||02132017|-15|C00437277|SB28A_70206576|1216764||REFUND OF CONTRIBUTION, INITIALLY EARMARKED FOR JEFF MERKLEY FOR OREGON (C00437277)|4043020181532952440 20 | C00401224|A|M3|P|201804039098807623|24T|IND|MOORE, KARYL|PRESCOTT|AZ|86301|||02072017|-25|C00500843|SB28A_70745018|1216764||REFUND OF CONTRIBUTION, INITIALLY EARMARKED FOR ELIZABETH FOR MA, INC. (C00500843)|4043020181532952442 21 | C00401224|A|M3|P|201804039098807623|22Y|IND|MOORE, LINDA|BETHLEHEM|GA|30620|||02012017|1||SB28A_67404159|1216764||REFUND OF CONTRIBUTION, INITIALLY EARMARKED FOR ACTBLUE (C00401224)|4043020181532952444 22 | C00401224|A|M3|P|201804039098807623|24T|IND|MOORE, LINDA|BETHLEHEM|GA|30620|||02012017|-5|C00000935|SB28A_67404156|1216764||REFUND OF CONTRIBUTION, INITIALLY EARMARKED FOR DCCC (C00000935)|4043020181532952446 23 | C00401224|A|M3|P|201804039098808867|22Y|IND|THIBODEAU, MARILYN R.|HOUSTON|TX|77023|||02042017|5||SB28A_62793474|1216764||REFUND OF CONTRIBUTION, INITIALLY EARMARKED FOR ACTBLUE (C00401224)|4043020181532959927 24 | C00401224|A|M3|P|201804039098808868|24T|IND|THIBODEAU, MARILYN R.|HOUSTON|TX|77023|||02042017|-15|C00213512|SB28A_67402788|1216764||REFUND OF CONTRIBUTION, INITIALLY EARMARKED FOR NANCY PELOSI FOR CONGRESS (C00213512)|4043020181532959929 25 | C00401224|A|M3|P|201804039098808868|24T|IND|THIBODEAU, MARILYN R.|HOUSTON|TX|77023|||02042017|-15|C00213512|SB28A_65863533|1216764||REFUND OF CONTRIBUTION, INITIALLY EARMARKED FOR NANCY PELOSI FOR CONGRESS (C00213512)|4043020181532959931 -------------------------------------------------------------------------------- /src/main/resources/img/classRunnerExample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paigen11/read-file-java/63c327e342cdb17e5223e70a922c901eebb7082a/src/main/resources/img/classRunnerExample.png -------------------------------------------------------------------------------- /src/main/resources/img/intellijRun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paigen11/read-file-java/63c327e342cdb17e5223e70a922c901eebb7082a/src/main/resources/img/intellijRun.png -------------------------------------------------------------------------------- /src/test/java/com/example/readFile/readFileJava/ReadFileJavaApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.readFile.readFileJava; 2 | 3 | public class ReadFileJavaApplicationTests { 4 | 5 | public void contextLoads() { 6 | assert(true); 7 | } 8 | 9 | } 10 | 11 | --------------------------------------------------------------------------------