How toUnit Test ZipOutputStream Or verify the CSVWriter in Java - java

public void writeEnvToCsv(int customerId, ZipOutputStream zos, List<SummaryDetailsResponse> summaryDetailsResponseList, QueryHelper queryHelper) {
//Headers size = size(No of distinct entities) * 2 + 1
final CsvWriter writer = new CsvWriter(new OutputStreamWriter(zos), new CsvWriterSettings());
final String[] headers = new String[summaryDetailsResponseList.get(0).getEntities().size() * 2 + 1];
String header;
int index = 0, i, k;
headers[index++] = Entities;
for (i = 0; i < summaryDetailsResponseList.get(0).getEntities().size(); i++) {
header = summaryDetailsResponseList.get(0).getEntities().get(i).getEntityType();
if (valueMap.get(header) != null) {
header = valueMap.get(header);
}
headers[index++] = header + " " + Count;
headers[index++] = header + "(s)";
}
writer.writeHeaders(headers);
for (index = 0; index < summaryDetailsResponseList.size(); index++) {
final String[] values = new String[summaryDetailsResponseList.get(index).getEntities().size() * 2 + 1];
i = 0;
k = 0;
values[i++] = summaryDetailsResponseList.get(index).getRecordName();
for (; i <= summaryDetailsResponseList.get(index).getEntities().size() * 2; ) {
values[i++] = String.valueOf(summaryDetailsResponseList.get(index).getEntities().get(k).getEntityData().get(0).getTotal());
try {
StringBuilder strConcat = new StringBuilder();
List<String> hostNames = queryHelper.getHostNames(customerId,
String.valueOf(summaryDetailsResponseList.get(index).getEntities().get(k).getEntityData().get(0).getQuery()));
for (String host : hostNames) {
if (strConcat.toString().equals(""))
strConcat.append(host);
else
strConcat.append(", ").append(host);
}
values[i++] = strConcat.toString();
} catch (Exception e) {
e.printStackTrace();
}
k++;
}
writer.writeRow(CSVUtils.escapeCSVRow(values));
}
writer.flush();
}
Basically I want to write UT to verify this function. Can we verify the CSVWriter that it has written correct data for headers and rows or ZipOutputStream in any way.
I was able to verify the records writer has written if I pass writer to the function instead of creating it inside the function but I don't want to do this.

Related

Handle large data receive through socket TCP by mutiple Thread Java

I Have a server Socker, each seconds, Client will send data to server. Data is a String contain about 5000 lines, I want to split that data into 5 parts to handle by 5 threads at the same time.
private void listening() {
while (true) {
try {
clientSocket = serverSocket.accept();
System.out.println(clientSocket.getInetAddress());
BufferedReader os = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
new Thread(() -> {
try {
while (true) {
String data = os.readLine();
}
} catch (IOException e) {
e.printStackTrace();
}
}).start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Here is example code, What should I do to split data to 5 parts?
Example Data:
NVL01_1,20210624045425,172.67.216.146,5027,227.1.50.52,8870,212.133.114.73,2017
NVL01_1,20210624045425,193.25.63.53,6313,216.243.18.239,4445,227.236.233.188,2528
NVL01_1,20210624045425,111.176.240.164,2254,53.3.85.55,3829,72.195.203.220,8903
NVL01_1,20210624045425,223.224.123.173,1596,237.81.112.22,5669,25.193.178.6,5719
NVL01_1,20210624045425,178.89.46.197,489,140.87.132.177,4772,154.172.63.136,3045
NVL01_1,20210624045425,25.201.145.226,3004,234.138.243.22,6831,107.122.249.80,9609
NVL01_1,20210624045425,94.163.66.108,6041,37.190.105.119,9280,89.212.205.137,7483
NVL01_1,20210624045425,90.119.3.94,8881,96.137.66.26,7281,1.99.109.175,9525
NVL01_1,20210624045425,106.116.39.233,1280,196.62.122.91,1649,60.112.241.253,6697
NVL01_1,20210624045425,179.187.138.181,3870,62.38.25.158,4272,74.152.247.34,5220
NVL01_1,20210624045425,204.11.249.30,4749,234.133.240.8,7808,105.193.120.29,9638
NVL01_1,20210624045425,2.99.210.82,6924,206.153.6.165,7520,81.157.119.248,7638
NVL01_1,20210624045425,84.205.46.70,4275,188.189.94.143,4304,172.70.59.8,1226
NVL01_1,20210624045425,38.133.52.221,9577,87.183.254.244,9694,230.209.104.133,164
NVL01_1,20210624045425,13.43.85.59,2894,10.190.222.113,2948,96.155.28.151,9891
NVL01_1,20210624045425,16.79.32.72,7628,57.163.233.173,1,138.67.131.44,5079
NVL01_1,20210624045425,99.123.115.184,5113,197.56.206.97,9480,222.162.213.230,9564
NVL01_1,20210624045425,133.126.151.28,7437,3.80.234.183,5566,235.50.191.69,744
NVL01_1,20210624045425,71.86.226.128,5212,163.29.130.8,6954,160.182.239.31,1622
NVL01_1,20210624045425,145.78.71.65,2124,197.135.78.117,340,247.187.243.124,6136
NVL01_1,20210624045425,145.208.217.4,9493,8.138.165.8,8975,11.13.156.146,6828
NVL01_1,20210624045425,46.23.207.136,5328,151.197.27.17,3823,253.221.4.92,7230
NVL01_1,20210624045425,189.204.114.107,6709,44.199.81.116,5490,178.66.79.37,1437
NVL01_1,20210624045425,114.48.39.253,9602,27.38.239.223,1566,224.207.76.203,1899
NVL01_1,20210624045425,42.55.138.38,4812,51.93.10.2,7836,95.189.159.240,9574
NVL01_1,20210624045425,141.24.136.19,422,248.144.61.220,2427,138.88.193.240,2284
NVL01_1,20210624045425,146.176.9.78,6852,198.41.131.88,1094,227.242.134.106,5715
NVL01_1,20210624045425,134.47.77.168,7825,90.1.25.81,9125,175.143.184.94,5291
NVL01_1,20210624045425,131.180.238.244,7408,20.87.233.210,592,148.178.232.143,2782
NVL01_1,20210624045425,127.144.113.136,1375,197.9.246.61,7113,181.163.124.51,4290
NVL01_1,20210624045425,131.204.107.100,7185,192.181.253.8,2237,207.147.69.181,4239
NVL01_1,20210624045425,123.28.117.19,5432,89.11.193.31,9282,34.193.75.180,8747
NVL01_1,20210624045425,96.24.44.203,9186,73.65.43.110,4013,174.193.2.241,8762
NVL01_1,20210624045425,164.248.38.5,3122,245.59.114.8,5506,231.212.210.94,8837
NVL01_1,20210624045425,144.86.166.14,8583,123.127.122.39,8625,6.132.112.158,1653
NVL01_1,20210624045425,195.6.162.254,3597,24.218.41.173,1357,24.55.15.35,921
NVL01_1,20210624045425,75.13.49.219,9779,9.202.212.168,2309,11.142.118.22,1955
NVL01_1,20210624045425,245.132.44.122,9659,12.116.75.191,7258,88.91.180.73,2457
NVL01_1,20210624045425,223.31.193.225,5257,194.245.37.73,4567,197.134.216.13,6327
NVL01_1,20210624045425,251.30.222.188,4178,106.83.17.52,4045,142.99.100.174,6164
NVL01_1,20210624045425,209.115.15.248,9416,124.213.26.22,128,145.6.19.210,2801
NVL01_1,20210624045425,189.174.30.164,7052,24.191.53.184,8172,20.57.226.30,8362
NVL01_1,20210624045425,235.148.200.174,5072,162.253.12.169,7542,205.85.11.196,553
NVL01_1,20210624045425,164.121.163.241,9549,60.225.45.42,7108,255.147.26.90,7637
NVL01_1,20210624045425,145.3.148.142,7128,76.29.166.83,6432,152.25.4.242,1605
NVL01_1,20210624045425,194.170.50.219,6973,229.63.113.168,5698,164.5.6.101,6650
NVL01_1,20210624045425,39.184.47.229,367,17.180.188.224,5841,70.42.225.241,6074
NVL01_1,20210624045425,36.62.110.27,2587,105.252.86.145,7262,57.63.203.247,4518
NVL01_1,20210624045425,225.173.252.217,4665,115.177.84.223,4614,62.203.148.102,7514
NVL01_1,20210624045425,146.128.170.11,2411,76.187.243.147,4396,224.224.170.32,4872
NVL01_1,20210624045425,27.209.151.174,4614,0.125.68.119,2427,39.208.125.100,940
NVL01_1,20210624045425,88.90.208.193,7722,35.102.255.5,3604,214.45.25.189,7213
NVL01_1,20210624045425,96.33.115.231,5202,128.192.0.70,4048,160.221.24.37,3806
NVL01_1,20210624045425,84.26.118.109,2940,109.36.178.60,3276,170.183.57.80,6159
NVL01_1,20210624045425,225.67.85.90,3034,73.62.181.134,291,97.92.65.165,6845
NVL01_1,20210624045425,160.177.222.98,5610,134.70.105.214,65,24.69.80.75,5193
NVL01_1,20210624045425,142.49.198.59,7820,176.83.196.180,2107,40.68.245.29,9761
NVL01_1,20210624045425,59.199.111.242,734,222.236.118.31,7964,210.83.178.184,4373
NVL01_1,20210624045425,115.106.166.229,5409,77.171.38.150,2611,4.217.213.148,9342
NVL01_1,20210624045425,18.54.5.157,9803,48.47.15.108,4348,224.211.21.208,6431
NVL01_1,20210624045425,135.21.210.96,3068,203.5.250.83,9397,221.89.166.128,3374
NVL01_1,20210624045425,191.223.45.133,9746,227.252.45.227,2955,105.233.104.84,4350
NVL01_1,20210624045425,113.39.211.171,2688,63.230.236.139,2083,213.155.51.185,1973
NVL01_1,20210624045425,92.242.126.24,7434,30.44.168.146,3950,177.251.17.214,7967
NVL01_1,20210624045425,194.134.48.232,8858,14.13.21.182,9196,236.92.11.13,9344
NVL01_1,20210624045425,130.3.48.196,9380,112.89.224.216,4645,157.199.7.200,1790
NVL01_1,20210624045425,229.36.230.48,8815,116.98.169.138,505,134.232.82.65,727
NVL01_1,20210624045425,67.133.95.171,7594,214.33.143.109,5649,71.73.166.217,3153
NVL01_1,20210624045425,225.153.10.77,5447,139.209.199.128,2845,71.108.112.231,4144
NVL01_1,20210624045425,108.253.199.77,3088,203.35.58.102,8689,138.78.85.194,7954
NVL01_1,20210624045425,48.242.189.77,49,56.20.207.122,9542,179.159.117.240,9634
NVL01_1,20210624045425,47.46.208.195,9766,145.154.85.14,2952,189.187.53.186,7724
NVL01_1,20210624045425,95.124.222.197,9549,227.219.232.255,4794,161.166.17.242,4141
How about using data.split() and then creating a thread for each data like this?
//this will split the data in 5 where the text is marked by /'/
String[] splitdata = data.split("/'/", 5);
for(int i=0;i<5;i++)
startThread(splitdata[5]);
to call
public void startThread(String data){
//starts the thread with the split data
}
here is an example:
String data="...NVL01_...5719 /'/NVL01_...3045... etc."
String[] splitdata = data.split("/'/", 5);
System.out.println(splitdata[0]) //...NVL01_...5719
System.out.println(splitdata[1]) //...NVL01_...3045
etc.
you would just need to put some kind of sign where you want the string to be split before sending the data.
With this example, you could do the work.
public static String[] splitFive(String data) {
int factor = 1;
String [] parts = new String[5];
if(data.length() >= 5){
//
factor = data.length() / 5;
parts[0] = data.substring(0, factor);
parts[1] = data.substring(factor, factor * 2);
parts[2] = data.substring(factor*2, factor * 3);
parts[3] = data.substring(factor*3, factor * 4);
parts[4] = data.substring(factor*4);
} else {
for(int i = 0; i < data.length(); i++){
parts[i] = String.valueOf(data.charAt(i));
}
}
return parts;
}
String [] result = splitFive("1234");
String [] result2 = splitFive("12345678901234567890--");
Will return:
field String[] result = String[5] { "1", "2", "3", "4", null }
field String[] result2 = String[5] { "1234", "5678", "9012", "3456", "7890--" }
Edited example method to work with lines:
public static List[] splitFive(String data) {
List [] parts = new List [5];
String [] allLines = data.split("\n");
int factor = 1;
List<String> allLinesList = Arrays.asList(allLines);
if(allLines.length >= 5){
factor = allLines.length / 5;
parts[0] = allLinesList.subList(0, factor);
parts[1] = allLinesList.subList(factor, factor * 2);
parts[2] = allLinesList.subList(factor*2, factor * 3);
parts[3] = allLinesList.subList(factor*3, factor * 4);
parts[4] = allLinesList.subList(factor*4, allLinesList.size());
} else {
for(int i = 0; i < allLines.length ; i++){
parts[i] = Collections.singletonList(allLinesList.get(i));
}
}
return parts;
}
StringBuilder sb = new StringBuilder();
for(int i = 0; i <10; i++){
sb.append("Line-"+i+"\n");
}
List [] result = splitFive("1234\n4567\n464646464654654\n");
List [] result2 = splitFive(sb.toString());
This will return
field List[] result = List[5] { [1234], [4567], [464646464654654], null, null }
field List[] result2 = List[5] { [Line-0, Line-1], [Line-2, Line-3], [Line-4, Line-5], [Line-6, Line-7], [Line-8, Line-9] }

Set boolean to true, but filewriter still overwrites the file, any advice?

I have created a simple program that sorts integers in an input file using different algorithms. I also use filewriter to output results to another file. Unfortunately no matter how I change my code, file gets overridden. Any advice?
Been searching for answer on google and tried changing the way I input the syntax but nothing works.
important bits:
setting the writer up
try {
FileWriter fileWriter = new FileWriter ("Sorted output.txt");
//BufferedWriter bufferedWriter = new BufferedWriter (fileWriter);
PrintWriter out = new PrintWriter (new FileWriter("Sorted output.txt", true));
outputting to the file
out.println("User's own data set sorted using bubble sort.");
out.println(unsortedArray + Arrays.deepToString(FileOne));
out.println("Sorted Array looks like this:" + Arrays.toString(intArrayBubble));
out.println(timeToSort + bubbleSortIs + bubbleTime + "ms");
it works fine, however its used in a do while loop, with nested if statements, and each one overrides the other.
Rest of code in case its required - UPDATED - still not working
import java.io.*;
import java.util.*;
import java.util.concurrent.TimeUnit;
public class PDD_Sorting {
public static void main (String [] pArgs)
{
//Array for a file
String[] FileOne;
FileOne = new String[0];
int optionOne = 1,
optionTwo = 2,
optionThree = 3,
secondaryOptionOne = 1,
secondaryOptionTwo = 2,
secondaryOptionThree = 3,
userSelection,
subUserSelection;
String unsortedArray = "Unsorted array is: ",
bubbleSort = "Sorted array using bubble sort: ",
selectionSort = "Sorted array using selection sort: ",
insertionSort = "Sorted array using insertion sort: ",
timeToSort = "Time needed to sort this array using ",
bubbleSortIs = "bubble sort is ",
selectionSortIs = "selection sort is ",
insertionSortIs = "insertion sort is ",
welcomeToSorter = "Welcome to the SORTER - program that can sort your txt files containing integeres in an ascending order!",
notFiles = "Integers, not files :)",
pleaseSelect = "Please select one of the following options, by enetering a number asociated with it.",
optionOneUserInput = "1. Sort your own data set - input your own set of data (integers, separated by colons, no spaces) into the Input file.",
optionTwoPredefined = "2. Use predetermind set of data to test the algorythms.",
optionThreeExit = "3. Exit the program.",
subMenuPleaseSelect = "Please select which algorythm would you like to use to sort this file.",
optionBubble = "(1) - Bubble Sort.",
optionSelection = "(2) - Selection Sort.",
optionInsertion = "(3) - Insertion Sort.",
usersDataBubble = "User's own data set sorted using bubble sort.",
sortedArrayLooks = "Sorted Array looks like this:",
msTime = "ms",
usersDataSelection = "User's own data set sorted using selection sort.",
usersDataInsertion = "User's own data set sorted using insertion sort.",
validOption = "Please enter a valid option i.e. 1,2 or 3",
lessThanZero = "If time shown in ms is 0, that means the time needed to conduct the sort is shorter than 1ms.",
fileCreated = "File created.",
terminatingProgram = "Terminating the program.",
unableToWriteFile = "Unable to write to file";
System.out.println(welcomeToSorter);
System.out.println(notFiles);
Scanner tInput = new Scanner (System.in);
try {
FileWriter fileWriter = new FileWriter ("Sorted output.txt");
//BufferedWriter bufferedWriter = new BufferedWriter (fileWriter);
PrintWriter out = new PrintWriter (new FileWriter("Sorted output.txt", true));
do {
System.out.println(pleaseSelect);
System.out.println(optionOneUserInput);
System.out.println(optionTwoPredefined);
System.out.println(optionThreeExit);
// Scanner tInput = new Scanner (System.in);
userSelection = tInput.nextInt();
if (userSelection == optionOne) {
//System.out.println("Please enter a valid path for your file.");
String[] splitFile = null;
//String userFile = tInput.next();
FileOne = getAndPrepareFile(splitFile);
System.out.println(subMenuPleaseSelect);
System.out.println(optionBubble);
System.out.println(optionSelection);
System.out.println(optionInsertion);
subUserSelection = tInput.nextInt();
if (subUserSelection == secondaryOptionOne) {
int size = FileOne.length;
int [] intArrayBubble = new int [size];
for(int i=0; i<size; i++) {
intArrayBubble[i] = Integer.parseInt(FileOne[i]);
}
bubbleSort(intArrayBubble);
long bubbleTime = timeCount(intArrayBubble);
out.println(usersDataBubble);
out.println(unsortedArray + Arrays.deepToString(FileOne));
out.println(sortedArrayLooks + Arrays.toString(intArrayBubble));
out.println(timeToSort + bubbleSortIs + bubbleTime + msTime);
}
else if (subUserSelection == secondaryOptionTwo) {
int size2 = FileOne.length;
int [] intArraySelection = new int [size2];
for(int i=0; i<size2; i++) {
intArraySelection[i] = Integer.parseInt(FileOne[i]);
}
doSelectionSort(intArraySelection);
long selectionTime = timeCount(intArraySelection);
out.println(usersDataSelection);
out.println(unsortedArray + Arrays.deepToString(FileOne));
out.println(sortedArrayLooks + Arrays.toString(intArraySelection));
out.println(timeToSort + selectionSortIs + selectionTime + msTime);
}
else if (subUserSelection == secondaryOptionThree) {
int size3 = FileOne.length;
int [] intArrayInsertion = new int [size3];
for(int i=0; i<size3; i++) {
intArrayInsertion[i] = Integer.parseInt(FileOne[i]);
}
doInsertionSort(intArrayInsertion);
long insertionTime = timeCount(intArrayInsertion);
out.println(usersDataInsertion);
out.println(unsortedArray + Arrays.deepToString(FileOne));
out.println(sortedArrayLooks + Arrays.toString(intArrayInsertion));
out.println(timeToSort + insertionSortIs + insertionTime + msTime);
}
else {
System.out.println(validOption);
tInput.next();
}
}
else if (userSelection == optionTwo){
//file being prepared and loaded via function
String[] splitFilePredefined = null;
FileOne = getAndPrepareFilePredefined(splitFilePredefined);
//converting string array into int array so the method can sort it.
int size = FileOne.length;
int [] intArrayBubble = new int [size];
for(int i=0; i<size; i++) {
intArrayBubble[i] = Integer.parseInt(FileOne[i]);
}
int size2 = FileOne.length;
int [] intArraySelection = new int [size2];
for(int i=0; i<size2; i++) {
intArraySelection[i] = Integer.parseInt(FileOne[i]);
}
int size3 = FileOne.length;
int [] intArrayInsertion = new int [size3];
for(int i=0; i<size3; i++) {
intArrayInsertion[i] = Integer.parseInt(FileOne[i]);
}
//inserting pre-prepared int arrays into variables including a timecount method
int bubbleTime = timeCount(intArrayBubble);
int selectionTime = timeCount(intArraySelection);
int insertionTime = timeCount(intArrayInsertion);
//sorting array using various sorts
bubbleSort(intArrayBubble);
doSelectionSort(intArraySelection);
doInsertionSort(intArrayInsertion);
//out.println("Sorted arrray using insertion sort looks like this: " + Arrays.toString(intArrayInsertion));
out.println(timeToSort + bubbleSortIs + bubbleTime + "ms");
out.println(timeToSort + selectionSortIs + selectionTime + "ms");
out.println(timeToSort + insertionSortIs + insertionTime + "ms");
out.println(lessThanZero);
System.out.println(fileCreated);
}
else if (userSelection == optionThree){
System.out.println(terminatingProgram);
System.exit(0);
}
else {
System.out.println(validOption);
tInput.next();
}
out.flush();
out.close();
//tInput.close();
}while (userSelection != optionThree);
}
catch (Exception e)
{
System.out.println(unableToWriteFile);
tInput.next();
}
tInput.close();
}//end main
//method that fetches the file from predefined, hardcoded location and removes comas, esentially prepares the file for the next phase
private static String[] getAndPrepareFile (String[] splitFile)
{
Scanner fileIn = null;
try
{
fileIn = new Scanner(new FileInputStream("C:\\Users\\Greg\\Documents\\Programming\\PDD - Assignment 1\\Input.txt"));
String fileNew = fileIn.next();
splitFile = fileNew.split(",");
//System.err.println(Arrays.toString(splitFile)); //Arrays.toString needed to print the array correctly, otherwise it prints the address of the object
fileIn.close();
}
catch (IOException e)
{
System.out.println("File not found.");
//System.exit(0);
}
return splitFile;
}
//as above but works for predefined file, that can be generated using randomNumber.java program
private static String[] getAndPrepareFilePredefined (String[] splitFilePredefined)
{
Scanner fileIn = null;
try
{
fileIn = new Scanner(new FileInputStream("C:\\Users\\Greg\\Documents\\Programming\\PDD - Assignment 1\\Generated input.txt"));
String fileNew = fileIn.next();
splitFilePredefined = fileNew.split(",");
//System.err.println(Arrays.toString(splitFile)); //Arrays.toString needed to print the array correctly, otherwise it prints the address of the object
fileIn.close();
}
catch (IOException e)
{
System.out.println("File not found.");
//System.exit(0);
}
return splitFilePredefined;
}
//method used to sort a file using bubble sort
private static void bubbleSort(int[] arr) {
int n = arr.length;
int temp = 0;
for(int i=0; i < n; i++){
for(int j=1; j < (n-i); j++){
if(arr[j-1] > arr[j]){
//swap elements
temp = arr[j-1];
arr[j-1] = arr[j];
arr[j] = temp;
}
}
}
}
//method used to sort a file using selection sort
private static int[] doSelectionSort(int[] arr){
for (int i = 0; i < arr.length - 1; i++)
{
int index = i;
for (int j = i + 1; j < arr.length; j++)
if (arr[j] < arr[index])
index = j;
int smallerNumber = arr[index];
arr[index] = arr[i];
arr[i] = smallerNumber;
}
return arr;
}
//method used to sort a file using sinsertion sort
private static int[] doInsertionSort(int[] input){
int temp;
for (int i = 1; i < input.length; i++) {
for(int j = i ; j > 0 ; j--){
if(input[j] < input[j-1]){
temp = input[j];
input[j] = input[j-1];
input[j-1] = temp;
}
}
}
return input;
}
//method used to calculate how much time has lapsed while using any of the given sort methods, outputs in ms, if less than 1 ms, outputs 0ms
private static int timeCount (int[] anArray)
{
long start = System.nanoTime();
Arrays.sort(anArray);
long end = System.nanoTime();
long timeInMillis = TimeUnit.MILLISECONDS.convert(end - start, TimeUnit.NANOSECONDS);
//System.out.println("Time spend in ms: " + timeInMillis);
return (int) timeInMillis;
}
}//end class
File gets constantly overridden, how do i stop this and make it add to file instead?
You don't need the first FileWriter fileWriter = new FileWriter("Sorted output.txt");; this is actually creating/overwriting the file, after which your PrintWriter opens it again for appending.
So, just change
// ... omitting beginning
try {
FileWriter fileWriter = new FileWriter ("Sorted output.txt");
//BufferedWriter bufferedWriter = new BufferedWriter (fileWriter);
PrintWriter out = new PrintWriter (new FileWriter("Sorted output.txt", true));
do {
// ... omitting rest
to
// ... omitting beginning
try {
//BufferedWriter bufferedWriter = new BufferedWriter (fileWriter);
PrintWriter out = new PrintWriter (new FileWriter("Sorted output.txt", true));
do {
// ... omitting rest
Move out.close() outside the loop
else {
System.out.println("Please enter a valid option i.e. 1,2 or 3");
tInput.next();
}
out.flush();
/* THIS -> out.close(); <- THIS */
//tInput.close();
}while (userSelection != optionThree);
out.close();
}
I tried your code and your problem is not that the file is being overwritten, but that you are closing the outputstream in the first iteration.

String index out of Bounds Exception error

I am making a program to read .java files and extract all comments from it and write it to an html file. The file works mostly but i am having trouble extracting the names of each method as it confuses "Exception{" as a separate class/method.
So far this is the code i have and i believe it is almost done.
http://pastebin.com/qrbJAaW3
public class ParseDoc {
static String fileName = null;
static String outputR = "";
static String inputR = "";
static String[] lines;
static String [] classnames;
static StringBuilder classn = new StringBuilder();
static String classnam = "";
/**
* This Method asks the user for path to input and output file
* then it reads the file and places it on a string for easier sorting.
* The string is sorted line by line into an array and cleaned.
* #return Array of DOC comments
* #throws Exception
*/
public static String[] scanread() throws Exception{
System.out.println("NOTICE: If a valid file path is not entered, the program will not return a DOCHTML document.");
Scanner inputReader = new Scanner(System.in);
System.out.println("Please enter path to input file (ex: C:/Program Files/Code.java : " );
inputR = inputReader.nextLine();
System.out.println("Please enter path to html output file (ex: C:/Program Files/Output.html : " );
outputR = inputReader.nextLine();
inputReader.close();
FileReader file = new FileReader(inputR);
BufferedReader reader = new BufferedReader(file);
String line = reader.readLine();
//NAME OF THE SOURCE FILE
int index = inputR.lastIndexOf("/");
fileName = inputR.substring(index + 1);
int z = 0;
//This loop turns the input file into an String for easier access
while (line!= null){
line = reader.readLine();
z += 1;
}
reader.close();
file.close();
FileReader file2 = new FileReader(inputR);
BufferedReader reader2 = new BufferedReader(file2);
String line2 = reader2.readLine();
lines = new String[z];
int j = 0;
while(line2 != null)
{
line2 = line2.trim();
lines[j] = line2;
line2 = reader2.readLine();
j += 1;
}
reader2.close();
file2.close();
return lines;
}
/**
* Removes all the comments from the Array containing strings
* #param lines contains strings made of input file
* #return Array with removed strings
*/
public static String[] removeComments(String[] lines){
for (int i=0; i <lines.length;i++){
if (lines[i].startsWith("//"))
{
lines[i]="";
}
}
return lines;
}
/**
* This method scans the entire code for name of the classes and methods
* along with their parameters and stores them in an Array for further use
* #param lines
* #return lines array without changing any content
*/
public static String[] classNames(String[] lines)
{
int total = 0;
String[] matches = new String[] {"public ", "class ","private "};
for(int b = 0; b <lines.length;b++)
{
Matcher num = Pattern.compile("\\S+\\s*\\(([^)]*)\\)").matcher(lines[b]);
for (int n = 0; n < 3 ;n++)
{
if (lines[b].contains(matches[n]))
{
while(num.find())
{
total += 1;
}
}
}
}
classnames = new String[total];
for(int z = 0; z<lines.length;z++)
{
Matcher mzz = Pattern.compile("\\w+\\s*\\{").matcher(lines[z]);
for (int k = 0; k < 3; k++)
{
if (lines[z].contains(matches[k])&& !(lines[z].contains("throws "))) //&& !(lines[z].contains("throws "))
{
while(mzz.find())
{
classn.append( mzz.group()+"break");
}
}
}
}
for(int z = 0; z <lines.length;z++)
{
//This matcher with Regex looks for class/method names along with any parameters inside
Matcher m = Pattern.compile("\\S+\\s*\\(([^)]*)\\)").matcher(lines[z]);
int i = 0;
for (int k = 0; k < 3; k++)
{
if (lines[z].contains(matches[k]) )
{
while(m.find())
{
classn.append( m.group()+"break");
continue;
}
}
}
}
classnam = classn.toString();
classnames = classnam.split("break");
/*for(int step = 0; step<classnames.length;step++)
{
System.out.println(classnames[step]);
}*/
return lines;
}
/**
* This method removes all the code from the Array and leaves on the
* Doc comments intact.
* #param lines
* #return lines array with only comments remaining ( code is removed )
*/
public static String[] removeCode(String[] lines)
{
int rep = 0;
while ( rep <lines.length){
lines[rep] = lines[rep].replaceAll("\\*", "Z");
if(!(lines[rep].startsWith("Z") || (lines[rep].startsWith("/")))){
lines[rep]="";
}
lines[rep] = lines[rep].replaceAll("Z", "\\*");
rep += 1;
}
for(int num = 0; num <lines.length; num++)
{
if(lines[num].isEmpty()){
lines[num] = null;
}
}
return lines;
}
/**
* This method removes the remaining stars, slashes and properly formats each comment
* before printing it.
* #param lines The array contains parsed Java Doc comments
* #return
* #throws Exception
*/
public static String[] writeTo(String[] lines) throws Exception
{
BufferedWriter outputWriter = null;
outputWriter = new BufferedWriter(new FileWriter(outputR));
StringBuilder writeTo = new StringBuilder();
writeTo.append("<html>\n<body>\n<h2><mark> JAVA DOC COMMENTS</mark> </h2>\n<pre>\n"
+"<big><b>Source File:</b> </big>" +"<big>"+ fileName+"</big>" + "\n\n");
for(int step = 0; step<lines.length;step++)
{
if(!(lines[step] == null))
{
lines[step] = lines[step].replace("#author", "<b>Author: </b>\n&nbsp&nbsp&nbsp");
lines[step] = lines[step].replace("#since", "<b>Since: </b>\n&nbsp&nbsp&nbsp");
lines[step] = lines[step].replace("#version", "<b>Version: </b>\n&nbsp&nbsp&nbsp");
lines[step] = lines[step].replace("#param", "<b>Parameter: </b>\n&nbsp&nbsp&nbsp");
lines[step] = lines[step].replace("#return", "<b>Return: </b>\n&nbsp&nbsp&nbsp");
//lines[step] = lines[step].replace("*", "");
}
}
outputWriter.write(writeTo.toString());
//write to HTML
int countz = 0;
int comcount = 0;
//classnames[]
for(int resum = 0; resum<lines.length;resum++)
{
if(lines[resum] != null)
{
if( lines[resum].charAt(0) == '*' )
{
lines[resum] = lines[resum].replace("*","");
}
}
}
for(int i = 0; i < classnames.length; i++)
{
System.out.println(classnames[i]);
}
for(int resum = 0; resum<lines.length;resum++)
{
if(lines[resum] != null)
{
if( lines[resum].charAt(0) == '/' )
{
if(lines[resum].endsWith("*"))
{
lines[resum] = lines[resum].replace("/**","<b>"+classnames[countz]+"</b>");
countz++;
}
}
if( lines[resum].charAt(0) == '/' )
{
lines[resum] = lines[resum].replace("/","\n");
}
}
}
/*for(int resum = 0; resum<lines.length;resum++)
{
}*/
for(int f = 0; f<lines.length;f++)
{
if(lines[f] != null)
{
/*if(lines[f].startsWith("//") && lines[f].length() == 2)
{
lines[f] = "TEEEST";
countz++;
}*/
outputWriter.write(lines[f]+"\n");
}
}
outputWriter.close();
return null;
}
}
Console:
Please enter path to input file (ex: C:/Program Files/Code.java :
I:\ICS4U0\DocParse\src\java_doc_parse\ParseDoc.java
Please enter path to html output file (ex: C:/Program Files/Output.html :
I:\ICS4U0\DocParse\src\java_doc_parse\ParseDochh.html
ParseDoc {
scanread()
removeComments(String[] lines)
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 0
at java.lang.String.charAt(Unknown Source)
at java_doc_parse.ParseDoc.writeTo(ParseDoc.java:285)
at java_doc_parse.Execute.main(Execute.java:14)
classNames(String[] lines)
removeCode(String[] lines)
writeTo(String[] lines)
I am not sure what is causing this error. Is there a way to fix it or should i just give up on adding class names to comments altogether?
Sorry if i am lacking some information, but i am quite confused myself.
The error seems to be because you call charAt(0) on what appears to be an empty string.
You already have a null check above, I don't know if it's valid (can your lines ever be null?), but I would change that to a length check, possibly combined with the existing null check.
if (lines[resum] != null && lines[resum].length > 0) {
I think this is where your error resides:
for(int resum = 0; resum<lines.length;resum++)
{
if(lines[resum] != null)
{
if( lines[resum].charAt(0) == '/' )
{
if(lines[resum].endsWith("*"))
{
lines[resum] = lines[resum].replace("/**","<b>"+classnames[countz]+"</b>");
countz++;
}
}
if( lines[resum].charAt(0) == '/' )
{
lines[resum] = lines[resum].replace("/","\n");
}
}
}
Try this instead, move the null check before entering the for loop:
if(lines[0] != null)
{
for(int resum = 0; resum<lines.length;resum++)
{
if( lines[resum].charAt(0) == '/' )
{
if(lines[resum].endsWith("*"))
{
lines[resum] = lines[resum].replace("/**","<b>"+classnames[countz]+"</b>");
countz++;
}
}
if( lines[resum].charAt(0) == '/' )
{
lines[resum] = lines[resum].replace("/","\n");
}
}
}

How to convert multipage PDF to multipage TIFF

I am using Ghost4j to convert multipage PDFs to multipage TIFF images. I haven't found an example of how this is done.
Using below code I'm able to convert the multipage PDF to images but how do I create a single multipage TIFF image out of it?
PDFDocument lDocument = new PDFDocument();
lDocument.load(filePath);
// create renderer
SimpleRenderer lRenderer = new SimpleRenderer();
// set resolution (in DPI)
lRenderer.setResolution(300);
// render as images
List<Image> lImages = lRenderer.render(lDocument);
Iterator<Image> lImageIterator = lImages.iterator();
//how to convert the images to a single TIFF image?
While this is not exactly what you are doing I did something similar. I combined multiple images in one directory into a tiff file with separate pages. Take a look at this code and see if you can pick out what you need. Also you will need external jars/libraries for this to work they can be downloaded just google them. I hope this helps you.
public class CombineImages {
private static String directory = null;
private static String combinedImageLocation = null;
private static DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
private static int folderCount = 0;
private static int totalFolderCount = 0;
public static void main(String[] args) throws IOException {
Scanner scanner = new Scanner(System.in);
System.out.println("Please enter the directory path that contains the images: ");
directory = scanner.nextLine(); //initialize directory
System.out.println("Please enter a location for the new combined images to be placed: ");
combinedImageLocation = scanner.nextLine(); //initialize directory
if(!(combinedImageLocation.charAt((combinedImageLocation.length() - 1)) == '\\'))
{
combinedImageLocation += "\\";
}
if(!(directory.charAt((directory.length() - 1)) == '\\'))
{
directory += "\\";
}
scanner.close();
//directory = "C:\\Users\\sorensenb\\Desktop\\CombinePhotos\\";
//combinedImageLocation = "C:\\Users\\sorensenb\\Desktop\\NewImages\\";
File filesDirectory;
filesDirectory = new File(directory);
File[] files; //holds files in given directory
if(filesDirectory.exists())
{
files = filesDirectory.listFiles();
totalFolderCount = files.length;
folderCount = 0;
if(files != null && (files.length > 0))
{
System.out.println("Start Combining Files...");
System.out.println("Start Time: " + dateFormat.format(new Date()));
combineImages(files);
System.out.println("Finished Combining Files.");
System.out.println("Finish Time: " + dateFormat.format(new Date()));
}
}
else
{
System.out.println("Directory does not exist!");
System.exit(1);
}
}
public static void combineImages(File[] files)
{
int fileCounter = 1;
ArrayList<String> allFiles = new ArrayList<String>();
String folderBase = "";
String parentFolder = "";
String currentFileName = "";
String previousFileName = "";
File previousFile = null;
int counter = 0;
for(File file:files)
{
if(file.isDirectory())
{
folderCount++;
System.out.println("Folder " + folderCount + " out of " + totalFolderCount + " folders.");
combineImages(file.listFiles());
}
else
{
try {
folderBase = file.getParentFile().getCanonicalPath();
parentFolder = file.getParentFile().getName();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(counter == 0)
{
allFiles.add(file.getName().substring(0, file.getName().indexOf('.')));
}
else
{
currentFileName = file.getName();
previousFileName = previousFile.getName();
currentFileName = currentFileName.substring(0, currentFileName.indexOf('.'));
previousFileName = previousFileName.substring(0, previousFileName.indexOf('.'));
if(!currentFileName.equalsIgnoreCase(previousFileName))
{
allFiles.add(currentFileName);
}
}
}
previousFile = file;
counter++;
}
System.out.println("Total Files to be Combined: " + allFiles.size());
for(String currentFile:allFiles)
{
System.out.println("File " + fileCounter + " out of " + allFiles.size() + " CurrentFile: " + currentFile);
try {
createNewImage(currentFile, files, folderBase, parentFolder);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
fileCounter++;
}
}
***public static void createNewImage(String currentFile, File[] files, String folderBase, String parentFolder) throws IOException
{
//BufferedImage image;
int totalHeight = 0;
int maxWidth = 0;
int currentHeight = 0;
ArrayList<String> allFiles = new ArrayList<String>();
for(File file:files)
{
if((file.getName().substring(0, file.getName().indexOf('.'))).equalsIgnoreCase(currentFile))
{
allFiles.add(file.getName());
}
}
allFiles = sortFiles(allFiles);
BufferedImage image[] = new BufferedImage[allFiles.size()];
SeekableStream ss = null;
PlanarImage op = null;
for (int i = 0; i < allFiles.size(); i++) {
ss = new FileSeekableStream(folderBase + "\\" + allFiles.get(i));
ImageDecoder decoder = ImageCodec.createImageDecoder("tiff", ss, null);
op = new NullOpImage(decoder.decodeAsRenderedImage(0),
null, null, OpImage.OP_IO_BOUND);
image[i] = op.getAsBufferedImage();
}
op.dispose();
ss.close();
/*BufferedImage convertImage;
for(int i = 0; i < image.length; i++)
{
convertImage = new BufferedImage(image[i].getWidth(),image[i].getHeight(), BufferedImage.TYPE_BYTE_GRAY);
Graphics g = convertImage.getGraphics();
g.drawImage(convertImage, 0, 0, null);
g.dispose();
image[i] = convertImage;
}*/
File folderExists = new File(combinedImageLocation);
if(!folderExists.exists())
{
folderExists.mkdirs();
}
TIFFEncodeParam params = new TIFFEncodeParam();
params.setCompression(TIFFEncodeParam.COMPRESSION_GROUP3_1D);
int changeName = 1;
String tempCurrentFile = currentFile;
while((new File(combinedImageLocation + tempCurrentFile + "Combined.tif").exists()))
{
tempCurrentFile = currentFile;
tempCurrentFile += ("(" + changeName + ")");
changeName++;
}
currentFile = tempCurrentFile;
OutputStream out = new FileOutputStream(combinedImageLocation + currentFile + "Combined" + ".tif");
ImageEncoder encoder = ImageCodec.createImageEncoder("tiff", out, params);
Vector vector = new Vector();
for (int i = 1; i < allFiles.size(); i++) {
vector.add(image[i]);
}
params.setExtraImages(vector.iterator());
encoder.encode(image[0]);
for(int i = 0; i < image.length; i++)
{
image[i].flush();
}
out.close();
System.gc();
/*for(String file:allFiles)
{
image = ImageIO.read(new File(folderBase, file));
int w = image.getWidth();
int h = image.getHeight();
totalHeight += h;
if(w > maxWidth)
{
maxWidth = w;
}
image.flush();
}
BufferedImage combined = new BufferedImage((maxWidth), (totalHeight), BufferedImage.TYPE_BYTE_GRAY);
for(String file:allFiles)
{
Graphics g = combined.getGraphics();
image = ImageIO.read(new File(folderBase, file));
int h = image.getHeight();
g.drawImage(image, 0, currentHeight, null);
currentHeight += h;
image.flush();
g.dispose();
}
File folderExists = new File(combinedImageLocation + parentFolder + "\\");
if(!folderExists.exists())
{
folderExists.mkdirs();
}
ImageIO.write(combined, "TIFF", new File(combinedImageLocation, (parentFolder + "\\" + currentFile + "Combined.tif")));
combined.flush();
System.gc();*/
}***
public static ArrayList<String> sortFiles(ArrayList<String> allFiles)
{
ArrayList<String> sortedFiles = new ArrayList<String>();
ArrayList<String> numbers = new ArrayList<String>();
ArrayList<String> letters = new ArrayList<String>();
for(String currentFile:allFiles)
{
try
{
Integer.parseInt(currentFile.substring((currentFile.indexOf('.') + 1)));
numbers.add(currentFile);
}catch(Exception e)
{
letters.add(currentFile);
}
}
//String[] numbersArray = new String[numbers.size()];
//String[] lettersArray = new String[letters.size()];
for(int i = 0; i < numbers.size(); i++)
{
sortedFiles.add(numbers.get(i));
}
for(int i = 0; i < letters.size(); i++)
{
sortedFiles.add(letters.get(i));
}
return sortedFiles;
}
}

Using the JGIT, how can I retrieve the line numbers of added/deleted lines

Assuming the following piece of code is committed to a Git repository:
int test(){
int a = 3;
int b = 4;
int c = a + b;
return c;
}
and is later updated to
int test(){
return 7;
}
I currently have a method which uses the JGit API in order to access the Git repository where the above are committed and outputs a string which is similar to the following:
int test(){
-int a = 3;
-int b = 4;
-int c = a + b;
-return c;
+return 7;
}
Now, my requirements have changed and would like to know the line numbers of the changed lines only. So I would want something like the following:
2 -int a = 3;
3 -int b = 4;
4 -int c = a + b;
5 -return c;
2 +return 7;
Basically, the same information that the GitHub application gives when an update is made.
Any help would be greatly appreciated :)
snippet of how the -/+ lines are computed:
String oldHash = "ee3e216ab5047748a22e9ec5ad3e92834704f0cc";
Git git = null;
try {
//the path where the repo is.
git = Git.open(new File("C:\\Users\\Administrator\\Documents\\GitHub\\Trial"));
} catch (IOException e1) {
e1.printStackTrace();
}
Repository repository = git.getRepository();
ObjectId old = null;
ObjectId head = null;
//a new reader to read objects from getObjectDatabase()
ObjectReader reader = repository.newObjectReader();
//Create a new parser.
CanonicalTreeParser oldTreeIter = new CanonicalTreeParser();
CanonicalTreeParser newTreeIter = new CanonicalTreeParser();
List<DiffEntry> diffs = null;
try {
//parse a git repository string and return an ObjectId
old = repository.resolve(oldHash + "^{tree}");
head = repository.resolve("HEAD^{tree}");
//Reset this parser to walk through the given tree
oldTreeIter.reset(reader, old);
newTreeIter.reset(reader, head);
diffs = git.diff()//Returns a command object to execute a diff command
.setNewTree(newTreeIter)
.setOldTree(oldTreeIter)
.call();//returns a DiffEntry for each path which is different
} catch (RevisionSyntaxException | IOException | GitAPIException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//DiffLineCountFilter d = new DiffLineCountFilter();
//out is the stream the formatter will write to
ByteArrayOutputStream out = new ByteArrayOutputStream();
//Create a new formatter with a default level of context.
DiffFormatter df = new DiffFormatter(out);
//Set the repository the formatter can load object contents from.
df.setRepository(git.getRepository());
ArrayList<String> diffText = new ArrayList<String>();
//A DiffEntry is 'A value class representing a change to a file' therefore for each file you have a diff entry
for(DiffEntry diff : diffs)
{
try {
//Format a patch script for one file entry.
df.format(diff);
RawText r = new RawText(out.toByteArray());
r.getLineDelimiter();
diffText.add(out.toString());
out.reset();
} catch (IOException e) {
e.printStackTrace();
}
}
You need to do the difference between the A line indexes and B line indexes from the diff result:
int linesAdded = 0;
int linesDeleted = 0;
int filesChanged = 0;
try {
repo = new FileRepository(new File("repo/.git"));
RevWalk rw = new RevWalk(repo);
RevCommit commit = rw.parseCommit(repo.resolve("486817d67b")); // Any ref will work here (HEAD, a sha1, tag, branch)
RevCommit parent = rw.parseCommit(commit.getParent(0).getId());
DiffFormatter df = new DiffFormatter(DisabledOutputStream.INSTANCE);
df.setRepository(repo);
df.setDiffComparator(RawTextComparator.DEFAULT);
df.setDetectRenames(true);
List<DiffEntry> diffs;
diffs = df.scan(parent.getTree(), commit.getTree());
filesChanged = diffs.size();
for (DiffEntry diff : diffs) {
for (Edit edit : df.toFileHeader(diff).toEditList()) {
linesDeleted += edit.getEndA() - edit.getBeginA();
linesAdded += edit.getEndB() - edit.getBeginB();
}
}
} catch (IOException e1) {
throw new RuntimeException(e1);
}
Just a tip for anyone who might have this problem. I did not manage to get the line numbers of the added and deleted lines but I did manage to get a string which contains only the added and deleted lines without the other lines which were not changed.
This was simply done by adding the line:
df.setContext(0);
in the snippet I provided above right before the line
df.format(diff);
I do it this way but I don't know if it is correct
public void linesChangeInFile(Git git, List<RevCommit> commits, String fileName, String pathRepository) {
try {
List<RevCommit> commitsComparer = new ArrayList<>();
List<String> linesChange = new ArrayList<>();
for (int i = 0; i < commits.size() - 1; i++) {
ObjectId commitIDOld = commits.get(i).getId();
if (Validador.isFileExistInCommit(commits.get(i), getRepository(), fileName)) {
if (i != commits.size() - 1 && !commitsComparer.contains(commits.get(i))) {
ObjectId commitIDNew = commits.get(i + 1);
commitsComparer.add(commits.get(i));
linesChange.add(diff(git, commitIDOld.getName(), commitIDNew.getName(), fileName));
}
try (final FileInputStream input = new FileInputStream(pathRepository + "\\" + fileName)) {
currentLines = IOUtils.readLines(input, "UTF-8").size();
}
}
}
Integer sumLinesAdd = 0;
Integer sumLinesDel = 0;
for (String lineChange : linesChange) {
String[] lChange = lineChange.split(";");
sumLinesAdd += Integer.parseInt(lChange[0]);
sumLinesDel += Integer.parseInt(lChange[1]);
}
System.out.println("Lines Add total:" + sumLinesAdd);
System.out.println("Lines Del total:" + sumLinesDel);
System.out.println("Total lines change:" + (sumLinesAdd + sumLinesDel));
} catch (RevisionSyntaxException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private String diff(Git git, String commitIDOld, String commitIDNew, String fileName) {
int linesAdded = 0;
int linesDeleted = 0;
DiffFormatter df = null;
try {
AbstractTreeIterator oldTreeParser = prepareTreeParser(getRepository(), commitIDOld);
AbstractTreeIterator newTreeParser = prepareTreeParser(getRepository(), commitIDNew);
List<DiffEntry> diffs = git.diff().setOldTree(oldTreeParser).setNewTree(newTreeParser)
.setPathFilter(PathFilter.create(fileName)).call();
df = new DiffFormatter(DisabledOutputStream.INSTANCE);
df.setRepository(getRepository());
df.setDiffComparator(RawTextComparator.DEFAULT);
df.setDetectRenames(true);
for (DiffEntry entry : diffs) {
// System.out.println("Entry: " + entry + ", from: " + entry.getOldId() + ", to:
// " + entry.getNewId());
// try (DiffFormatter formatter = new DiffFormatter(System.out)) {
// formatter.setContext(0);
// formatter.setRepository(repository);
// formatter.format(entry);
// }
for (Edit edit : df.toFileHeader(entry).toEditList()) {
linesDeleted += edit.getEndA() - edit.getBeginA();
linesAdded += edit.getEndB() - edit.getBeginB();
}
}
} catch (IOException | GitAPIException e) {
System.err.println("Error:" + e.getMessage());
}
return linesAdded + ";" + linesDeleted;
}

Categories

Resources