How to get the last x lines of a string in Java? - java

I get some result from an external command (semi-api) and want to parse the result.
I'm only interested in the last few lines of the result.
How can get the last x lines of a string in Java?

Here's a simple solution:
public static List<String> getLastLines(String string, int numLines) {
List<String> lines = Arrays.asList(string.split("\n"));
return new ArrayList<>(lines.subList(Math.max(0, lines.size() - numLines), lines.size()));
}

A solution that gives the result without parsing the whole string:
/**
* Created by alik on 3/31/17.
*/
public class Main {
// TODO: Support other EndOfLines, like "\r\n".
// One way is to just replace all "\r\n" with "\n" and then run the #getLastLines method.
public static List<String> getLastLines(String string, int numLines) {
List<String> lines = new ArrayList<>();
int currentEndOfLine = string.length();
if (string.endsWith("\n")) {
currentEndOfLine = currentEndOfLine - "\n".length();
}
for (int i = 0; i < numLines; ++i) {
int lastEndOfLine = currentEndOfLine;
currentEndOfLine = string.lastIndexOf("\n", lastEndOfLine - 1);
String lastLine = string.substring(currentEndOfLine + 1, lastEndOfLine);
lines.add(0, lastLine);
}
return lines;
}
#Test
public void test1() {
String text = "111\n" +
"222\n" +
"333\n" +
"444\n" +
"555\n" +
"666\n" +
"777\n";
List<String> lastLines = getLastLines(text, 4);
Assert.assertEquals("777", lastLines.get(lastLines.size() - 1));
Assert.assertEquals(4, lastLines.size());
}
#Test
public void test2() {
String text = "111\n" +
"222\n" +
"333\n" +
"444\n" +
"555\n" +
"666\n" +
"777";
List<String> lastLines = getLastLines(text, 4);
Assert.assertEquals("777", lastLines.get(lastLines.size() - 1));
Assert.assertEquals(4, lastLines.size());
}
}
* Link to github gist

Algorithm
Split input text with line break character and save as a list lines
If number of lines required, linesRequired is less than size of lines, ie, lineCount
Then return sublist of lines starting from lineCount - linesRequired to lineCount.
Otherwise, throw exception or return all lines based on the requrement.
Sample Implementation
private static final String SEPARATOR = "\n";
public static List<String> getLastLines(String string, int numLines) {
List<String> lines = Arrays.asList(string.split(SEPARATOR));
int lineCount = lines.size();
return lineCount > numLines ? lines.subList(lineCount - numLines, lineCount) : lines;
}

Here is another possible solution:
public class LastNLines {
public static List<String> getLastNLines(String inputString, int n) {
if(n < 0) {
return new ArrayList<>();
}
String[] tmp = inputString.split("(\\n|\\r)+");
if(n < tmp.length) {
return Arrays.asList(Arrays.copyOfRange(tmp, tmp.length - n, tmp.length));
}
return Arrays.asList(tmp);
}
public static void main(String[] args) {
String myExample =
" \n\r\r\n\nsome_text_1 " +
"\n" +
"some_text_2\n\n" +
"\n" +
" some_text_3\n\r " +
"\n" +
"some_text_4\n" +
"\n" +
"some_text_5\n\n\n";
List<String> result = LastNLines.getLastNLines(myExample, 2);
System.out.println(result.toString());
}
}
This one splits by multiple new lines at once, so a text like this \n\n\n\n\n will contain no Strings after splitting and the result will be empty.

Java 8 Streams (memory friendly) answer.
Code:
public class Main
{
public static void main( String[] args )
{
String rawData = "John\n\nDavid\nGeorge\nFrank\nTom";
Pattern pattern = Pattern.compile("\\n");
System.out.println( lastN( pattern.splitAsStream( rawData ),4));
System.out.println( lastN( pattern.splitAsStream( rawData ),40));
}
public static <T> List<T> lastN( Stream<T> stream, int n )
{
Deque<T> result = new ArrayDeque<>( n );
stream.forEachOrdered( x -> {
if ( result.size() == n )
{
result.pop();
}
result.add( x );
} );
return new ArrayList<>( result );
}
}

Related

How to increase size of array [a][b] every time I call a method?

public static int arraysize=1;
public String namabuku;
public String penulis;
public String Kategori;
public String buku[][]=new String[arraysize][3];
public static int a=0;
public void isiData(String kategori, String buku, String penulis){
this.buku[a][0]=kategori;
this.buku[a][1]=buku;
this.buku[a][2]=penulis;
arraysize++;
a++;
}
Hi guys I tried to increase my array length every time I call a method named "isiData", but it didn't work. I already checked the increment, but nothing wrong with it. Is there any way to increase its length every time I use the method? I want to make a simple way to input book, category, and its author using array.
You cannot increase the size of array.
There are 3 approaches to solve this problem:
Use ArrayList as suggested by others.
You can create another temp array of size one greater than the previous array and then copy the temp array to already created array.
You can use the copyOf(array, size) function of Arrays in Java
For example:
previousArray = Arrays.copyOf(previousArray , arraysize + 1);
arraysize += 1
Just try this Approach:
import java.util.ArrayList;
import java.util.List;
import java.util.Arrays;
/**
*
* #author Maverick
*/
public class Buku {
public static int arraysize;
public String namabuku;
public String penulis;
public String Kategori;
public List<List<String>> bukuList = new ArrayList<List<String>>();
public static void main(String[] args) {
Buku n = new Buku();
for (int i = 0; i < 5; i++) {
n.isiData("ab" + i, "cd" + i, "ef" + i);
}
n.arraysize = n.bukuList.size();
for (int i = 0; i < n.bukuList.size(); i++) {
System.out.println(n.bukuList.get(i).toString());
}
}
public void isiData(String kategori, String buku, String penulis) {
bukuList.add(Arrays.asList(kategori, buku, penulis));
}
}
Output:
[ab0, cd0, ef0]
[ab1, cd1, ef1]
[ab2, cd2, ef2]
[ab3, cd3, ef3]
[ab4, cd4, ef4]
You have to call new array to change the size of an array. I assume this is an exercise to practice using an array, so I'm going to avoid the classes like Arrays and System in the isiData method. You should look at those classes though.
So something like this:
public class BukuTest
{
public String namabuku;
public String penulis;
public String Kategori;
public String buku[][] = new String[ 0 ][ 3 ];
public void isiData( String kategori, String buku, String penulis )
{
String[][] temp = this.buku;
final int len = temp.length;
this.buku = new String[ len + 1 ][];
for( int i = 0; i < len; i++ )
this.buku[i] = temp[i];
this.buku[len] = new String[ 3 ];
this.buku[len][0] = kategori;
this.buku[len][1] = buku;
this.buku[len][2] = penulis;
// not needed
// arraysize++;
// a++;
}
public static void main(String[] args) {
BukuTest b = new BukuTest();
b.isiData( "test1", "test2", "test3" );
b.isiData( "test4", "test5", "test6" );
b.isiData( "test7", "test8", "test9" );
System.out.println(b);
}
#Override
public String toString()
{
return "BukuTest{" + "namabuku=" + namabuku + ", penulis=" + penulis +
", Kategori=" + Kategori + ", buku=" +
Arrays.deepToString(buku) + '}';
}
}
Using an ArrayList is definitely the way to go here as others have commented and displayed but, if you are absolutely bent on using a Two Dimensional String Array then this can be done with a custom method conveniently named redimPreserve() as I have shown below.
As #Jdman1699 had mentioned in his comment under your post, this is a very inefficient way of doing this sort of thing especially for larger arrays but since you asked, here is how it can be done:
// YOUR METHOD:
public int arraysize = 1;
public String[][] buku = new String[arraysize][3];
public void isiData(String kategori, String buka, String penulis){
// I have renamed the buku argument for this method to buka
// since you can not have a parameter variable named the
// same as a Class Global variable.
buku = redimPreserve(buku, arraysize, 3);
buku[arraysize-1][0] = kategori;
buku[arraysize-1][1] = buka;
buku[arraysize-1][2] = penulis;
arraysize++;
}
// THE redimPreserve() METHOD:
public static String[][] redimPreserve(String[][] yourArray, int newRowSize, int... newColSize) {
int newCol = 0;
if (newColSize.length != 0) { newCol = newColSize[0]; }
// The first row of your supplied 2D array will always establish
// the number of columns that will be contained within the entire
// scope of the array. Any column value passed to this method
// after the first row has been established is simply ignored.
if (newRowSize > 1 && yourArray.length != 0) { newCol = yourArray[0].length; }
if (newCol == 0 && newRowSize <= 1) {
throw new IllegalArgumentException("\nredimPreserve() Method Error!\n"
+ "No Column dimension provided for 2D Array!\n");
}
if (newCol > 0 && newRowSize < 1 && yourArray.length != 0) {
throw new IllegalArgumentException("\nredimPreserve() Method Error!\n"
+ "No Row dimension provided for 2D Array!\n");
}
String[][] tmp = new String[newRowSize][newCol];
if (yourArray.length != 0) {
for(int i = 0; i < yourArray.length; i++) {
System.arraycopy(yourArray[i], 0, tmp[i], 0, yourArray[i].length);
}
}
return tmp;
}

Social.java and SocialRunner.java

I am doing a social security program where you take apart a SS #, remove the hyphens (-), and parse the 3 parts into integers and add up.
Here is the main runner:
import static java.lang.System.*;
public class SocialRunner
{
public static void main( String args[] )
{
Social social = new Social("1-1-1");
//add test cases
//social.Social("1-1-1");
//social.chopAndAdd();
//boolean check = stringlivesmatter.checkEquality();
out.println(social);
}
}
And here is the main program:
import static java.lang.System.*;
public class Social
{
private String socialNum;
private String ssNum1, ssNum2, ssNum3, sub;
private int sum;
public Social()
{
}
public Social(String soc)
{
socialNum = soc;
}
public void setWord(String w)
{
/*String ssNum1 = socialNum.substring(0,socialNum.indexOf("-"));
String ssNum2 = socialNum.substring(socialNum.indexOf("-")+1,socialNum.indexOf("-"));
String ssNum3 = socialNum.substring(socialNum.indexOf("-")+1,socialNum.indexOf("-"));
*/
}
public void chopAndAdd()
{
sub = socialNum;
ssNum1 = socialNum.substring(0,socialNum.indexOf("-"));
ssNum2 = socialNum.substring(socialNum.indexOf("-")+1,socialNum.lastIndexOf("-"));
ssNum3 = socialNum.substring(socialNum.lastIndexOf("-")+1,0);
sum = Integer.parseInt(ssNum1) + Integer.parseInt(ssNum2) + Integer.parseInt(ssNum3);
}
public String toString()
{
sum = Integer.parseInt(ssNum1) + Integer.parseInt(ssNum2) + Integer.parseInt(ssNum3);
/*
String ssNum1 = socialNum.substring(0,socialNum.indexOf("-"));
String ssNum2 = socialNum.substring(socialNum.indexOf("-")+1,socialNum.indexOf("-"));
String ssNum3 = socialNum.substring(socialNum.indexOf("-")+1,socialNum.indexOf("-"));
sum = Integer.parseInt(ssNum1) + Integer.parseInt(ssNum2) + Integer.parseInt(ssNum3);
*/
return "SS# " + socialNum + " has a total of " + sum + "\n";
}
}
With the way the two programs above are written, I am given a runtime error:
Exception in thread "main" java.lang.NumberFormatException: null
at java.lang.Integer.parseInt(Integer.java:542)
at java.lang.Integer.parseInt(Integer.java:615)
at Social.toString(Social.java:46)
at java.lang.String.valueOf(String.java:2994)
at java.io.PrintStream.println(PrintStream.java:821)
at SocialRunner.main(SocialRunner.java:20)
If I comment/delete:
sum = Integer.parseInt(ssNum1) + Integer.parseInt(ssNum2) + Integer.parseInt(ssNum3);
from
public String toString()
I get:
SS# 1-1-1 has a total of 0
How can I avoid a runtime or logic error?
You only need to remove the dashes to get your number.
public void chopAndAdd()
{
String con = socialNum.replaceAll("-", "");
sum = Integer.parseInt(ssNum1) ;
}
You probably may need to modify this as well
public String toString()
{
this.chopAndAdd();
return "SS# " + socialNum + " has a total of " + sum + "\n";
}
and
public static void main( String args[] )
{
Social social = new Social("1-1-1");
social.chopAndAdd();
out.println(social.toString(););
}
Take your time go through and analyse very well to your understanding
Change your constructor in Social as follows so that the ssNum variables are actually set.
public Social(String soc)
{
socialNum = soc;
String[] chunks = soc.split("-");
ssNum1 = chunks[0];
ssNum2 = chunks[1];
ssNum3 = chunks[2];
}
Using String.split will break up the ssn into a String[3], each element of which will contain the numbers excluding what you split on, in this case hyphens.
e.g. [123, 12, 1234]
Then all you need to do is parse them and sum them up.
public static void main(String[] args)
{
String socialString = "123-12-1234";
System.out.println(chopAndAdd(socialString));
}
public static int chopAndAdd(String s)
{
String[] chunks = s.split("-");
int first = Integer.parseInt(chunks[0]);
int second = Integer.parseInt(chunks[1]);
int third = Integer.parseInt(chunks[2]);
return first + second + third;
}

How to design a test interface that times only some part of the code?

I want to time how long my code takes to perform on average over many test runs. In each test run, doWork() performs the work that I want to time. But I also want to checkWork() in each test run without it counting towards the time. I'm going to have many similar Exercise# classes, so I'd like to abstract the testing via a TestInterface. Is my current way a reasonable approach? Or is there a better design pattern / standard approach? Thanks in advance.
#FunctionalInterface
public interface TestInterface {
void test(final int NUM_TESTS);
}
public class TimeTests {
public static void test(TestInterface ti, final int NUM_TESTS, String testName) {
DecimalFormat df = new DecimalFormat("#.####");
long start = System.nanoTime();
ti.test(NUM_TESTS);
System.out.println("DEBUG: " + testName + " took "
+ df.format((System.nanoTime() - start) * 1.0 / NUM_TESTS)
+ " nanoseconds on average for " + NUM_TESTS + " tests");
}
}
public class Exercise1 {
private static final int NUM_TESTS = (int) Math.pow(10, 6);
private static void mainWork(List<Integer> A) {
// do stuff and time it
}
private static void checkWork(List<Integer> A) {
// do stuff but don't count it towards the time
}
public static void main(String[] args) {
TimeTests.test((NUM_TESTS_LOCAL) -> {
for (int i = 0; i < NUM_TESTS_LOCAL; ++i) {
List<Integer> A = new ArrayList<>();
// add random elements to A
mainWork(A);
checkWork(A);
}
}, NUM_TESTS, "Exercise1");
}
}
Okay, I think I managed to put together a decent framework (is this the right word?) for this task. If anybody could chime in to let me know if my approach is any good, I'd really appreciate it.
While my code seems to work fine for my use cases so far, I have a few questions:
In the interface definition of public interface CloneableTestInput<T extends CloneableTestInput<T>>, how is the type template <T extends CloneableTestInput<T> not a circular definition? I'm not sure I fully understand what that type template is saying.
Is there a way to make a generic CloneableList class that implements CloneableTestInput<List>? Currently, I need to make a separate implementation for each Collection type (e.g. ArrayList, LinkedList, ...). Similarly, is it possible to make a generic CloneableSet class that implements CloneableTestInput<Set>?
Thanks in advance :)
Testing Framework
Part I - An interface for test inputs
This allows TimeTests.java to work for generic input types.
public interface CloneableTestInput<T extends CloneableTestInput<T>> extends Cloneable {
T clone();
}
public class CloneableString implements CloneableTestInput<CloneableString> {
public String data;
public CloneableString() {}
public CloneableString(String input) { data = input; }
public CloneableString clone() { return new CloneableString(String.valueOf(data)); }
}
public class CloneableArrayList extends ArrayList implements CloneableTestInput<CloneableArrayList> {
public CloneableArrayList(ArrayList input) {
this.addAll(input);
}
#Override
public CloneableArrayList clone() {
return new CloneableArrayList(this);
}
}
Part II - An interface for timing tests
#FunctionalInterface
public interface TimeTestsInterface<outputType> {
void test(Callable<CloneableTestInput> formInput
, Function<CloneableTestInput, outputType> runAlgorithm
, Function<CloneableTestInput, outputType> getKnownOutput
, BiFunction<outputType, outputType, Boolean> checkResults
, final int NUM_TESTS, String testName);
}
public class TimeTests<outputType> implements TimeTestsInterface<outputType> {
public void test(Callable<CloneableTestInput> formInput
, Function<CloneableTestInput, outputType> runAlgorithm
, Function<CloneableTestInput, outputType> getKnownOutput
, BiFunction<outputType, outputType, Boolean> checkResults
, final int NUM_TESTS, String testName) {
try {
DecimalFormat df = new DecimalFormat("#.####");
long total = 0, start;
for (int i=0; i < NUM_TESTS; ++i) {
CloneableTestInput input = formInput.call();
CloneableTestInput orig_input = input.clone();
start = System.nanoTime();
outputType algorithmResult = runAlgorithm.apply(input);
total += System.nanoTime() - start;
outputType expectedResult = getKnownOutput.apply(orig_input);
assert(checkResults.apply(algorithmResult, expectedResult));
}
System.out.println("DEBUG: " + testName + " took "
+ df.format(total * 1.0 / NUM_TESTS)
+ " nanoseconds on average for " + NUM_TESTS + " tests");
} catch (Exception|AssertionError e) {
System.out.println(e.toString() + " - " + e.getMessage() + " - ");
e.printStackTrace();
}
}
}
Example Usages
Increment a BigInteger (uses CloneableArrayList)
/**
* Problem 6.2 from EPI
* Given an array A of digits encodiing a decimal number D,
* with MSD at A[0]. Update A to hold D + 1.
*/
public class PlusOne {
private static final int NUM_TESTS = (int) Math.pow(10, 5);
private static final int ARR_LENGTH = (int) Math.pow(10, 2);
private static ArrayList<Integer> plusOne(ArrayList<Integer> A) {
int n = A.size() - 1;
A.set(n, A.get(n) + 1);
for (int i = n; i > 0 && A.get(i) == 10; --i) {
A.set(i, 0);
A.set(i-1, A.get(i-1) + 1);
}
if (A.get(0) == 10) {
// Need additional digit up front as MSD
A.set(0,0);
A.add(0,1);
}
return A;
}
private static ArrayList<Integer> randArray(int len) {
ArrayList<Integer> A = new ArrayList<>();
if (len == 0) return A;
Random rgen = new Random();
A.add(rgen.nextInt(9) + 1);
--len;
while (len != 0) {
A.add(rgen.nextInt(10));
--len;
}
return A;
}
public static void main(String[] args) {
Callable<CloneableTestInput> formInput = () -> new CloneableArrayList(randArray(ARR_LENGTH));
Function<CloneableTestInput, ArrayList<Integer>> runAlgorithm =
(input) -> plusOne((ArrayList<Integer>) input);
Function<CloneableTestInput, ArrayList<Integer>> getKnownOutput =
(orig_input) -> {
BigInteger B = new BigInteger(Joiner.on("").join((ArrayList<Integer>) orig_input));
B = B.add(BigInteger.valueOf(1));
ArrayList<Integer> expectedOutput = new ArrayList<>();
while (B.compareTo(BigInteger.valueOf(0)) > 0) {
expectedOutput.add(0, B.mod(BigInteger.valueOf(10)).intValue());
B = B.divide(BigInteger.valueOf(10));
}
return expectedOutput;
};
BiFunction<ArrayList<Integer>, ArrayList<Integer>, Boolean> checkResults = List::equals;
TimeTests<ArrayList<Integer>> algTimer = new TimeTests<>();
algTimer.test(formInput, runAlgorithm, getKnownOutput, checkResults, NUM_TESTS, "PlusOne");
}
}
Can String be rearranged as a palindrome? (uses CloneableString)
public class CanStringBePalindrome {
private static final int INPUT_STRING_LENGTH = (int) Math.pow(10, 2);
private static final int NUM_TESTS = (int) Math.pow(10, 6);
private static boolean canFormPalindromeHash(final String s) {
Map<Character, Integer> charFreqs = new HashMap<>();
for (int i = 0; i < s.length(); ++i) {
char c = s.charAt(i);
if (!charFreqs.containsKey(c))
charFreqs.put(c, 1);
else
charFreqs.put(c, charFreqs.get(c) + 1);
}
int oddFreqCount = 0;
for (Map.Entry<Character, Integer> entry : charFreqs.entrySet()) {
if ((entry.getValue() % 2) != 0 && (++oddFreqCount > 1))
return false;
}
return true;
}
private static boolean canFormPalindromeSorting(final String s) {
// TODO : find faster/simpler way of getting frequency counts
char[] a = s.toCharArray();
Arrays.sort(a);
int oddFreqCount = 0;
int numCurrChar =1;
for (int i = 1; i < a.length && oddFreqCount <= 1; ++i) {
if(a[i] != a[i-1]) {
if ((numCurrChar & 1) != 0)
++oddFreqCount;
numCurrChar = 1;
} else
++numCurrChar;
}
if ((numCurrChar & 1) != 0)
++oddFreqCount;
return oddFreqCount <= 1;
}
private static String randString(int len) {
StringBuilder sb = new StringBuilder();
Random rgen = new Random();
while (len-- > 0)
sb.append((char)(rgen.nextInt(26) + 'A'));
return sb.toString();
}
public static void main(String[] args) {
Callable<CloneableTestInput> formInput = () -> new CloneableString(randString(INPUT_STRING_LENGTH));
Function<CloneableTestInput, Boolean > runAlgorithm =
(input) -> canFormPalindromeHash(((CloneableString)input).data);
Function<CloneableTestInput, Boolean> getKnownOutput =
(orig_input) -> canFormPalindromeSorting(((CloneableString)orig_input).data);
BiFunction<Boolean, Boolean, Boolean> checkResults = Boolean::equals;
TimeTests<Boolean> algTimer = new TimeTests<>();
algTimer.test(formInput, runAlgorithm, getKnownOutput, checkResults
, NUM_TESTS, "CanStringBePalindrome");
}
}

Converting Integer to a String

public enum TrafficLight {
RED(20),
YELLOW(3),
GREEN(10);
int duration;
TrafficLight(int newDuraction) {
duration = newDuraction;
}
public int getDuraction() {
return duration;
}
in the test class it's like:
public class TrafficLightTest {
public static void main(String[] args) {
for (TrafficLight trafficLight : TrafficLight.values()) {
System.out.println(trafficLight.name() + ": duraction " + trafficLight.getDuraction());
}
}
}
and i would like for example: "GREEN: duraction 10 " the number 10 to be like "**********".
10 = "**********" (ten asterisks)
3 = "***" (three asterisks)
i hope you get the idea. Thanks :)
Just use a for loop for printing "*" the required number of times
System.out.print(trafficLight.name() + ": duraction " ); //change this to Print instead of println
for(int i=0;i<trafficLight.getDuraction();i++)
System.out.print("*");
System.out.println();
Hope that helps.
You could do something like :-
public class TrafficLightTest {
public static String getAsteric(int input){ // return * using the int input
StringBuilder sb = new StringBuilder();
for(int i =0 ; i< input; i++)
sb.append("*");
return sb.toString();
}
public static void main(String[] args) {
for (TrafficLight trafficLight : TrafficLight.values()) {
System.out.println(trafficLight.name() + ": duraction " + TrafficLightTest.getAsteric(trafficLight.getDuraction())); // prints * equal to int input
}
}
}

Convert Hex value to ASCII character from array and how to eliminate null value?

I'm in the middle trying to convert the hex value that I retrieved from my method, compareHexaRGB to ASCII character which I want to know what output is going to produce. I don't know if I'm doing it wrong or I missed to code somewhere.
Code for extractMessage() method to convert hex value to ASCII:
public class extractMessage
{
private static String[][] char1;
private static String[][] char2;
private static String[][] in;
private static String[][] combine;
public static void extractMessage(String[][] inn, String[][] comb)
{
in = inn;
combine = comb;
}
public static void printString2DArray(String[][] in)
{
for (int i = 0; i < in.length; i++)
{
for(int j = 0; j < in[i].length; j++)
{
System.out.println(in[i][j] + " ");
}
System.out.println();
}
}
public static void charExtract()
{
compareHexaRGB hexRGB = new compareHexaRGB();
char1 = hexRGB.getCheck_hex2();
char2 = hexRGB.getCheck_hex4();
combine = new String[char1.length][char1[0].length];
for(int i = 0; i < char1.length; i++)
{
for(int j = 0; j < char1[i].length; j++)
{
//concatenate string
combine[i][j] = char1[i][j] + char2[i][j];
}
}
System.out.println("Char 1 + Char 2: ");
printString2DArray(combine);
}
public static String convertHexToString()
{
extractMessage em = new extractMessage();
StringBuilder sb = new StringBuilder();
StringBuilder temp = new StringBuilder();
String out = em.charExtract(); //error stated incompatible types: void cannot be converted to String
int decimal;
for(int i = 0; i < out.length(); i += 2)
{
String output = out.substring(i, (i + 2));
decimal = Integer.parseInt(output, 16);
sb.append((char)decimal);
temp.append(decimal);
}
System.out.println("Output: " + temp.toString());
return sb.toString();
}
}
Second, I still cannot eliminate the NULL value from the retrieved value. Someone said I need to add a place to hold the characters which in this case the NULL value. I've done that but when I try to run the code then, here we go again, the nullpointerexception occur. I'm still new to java and lack of experience handling with java arrays and advanced java but I'm eager to learn. Java is very interesting language and I hope one day I could master on this language.
Code for compareHexaRGB() :
public class compareHexaRGB
{
private static int w;
private static int h;
private static BufferedImage img;
private static BufferedImage img2;
private static String[][] check_hex2;
private static String[][] check_hex4;
private static String[][] not_stega2;
private static String[][] not_stega4;
public static void compareHexaRGB(BufferedImage image, BufferedImage image2, int width, int height) throws IOException
{
w = width;
h = height;
img = image;
img2 = image2;
}
public void check() throws IOException
{
getPixelRGB1 pixel = new getPixelRGB1();
getPixelData1 newPD = new getPixelData1();
int[] rgb;
int count = 0;
int[][] pixelData = new int[w * h][3];
check_hex2 = new String[w][h];
check_hex4 = new String[w][h];
for(int i = 0; i < w; i++)
{
for(int j = 0; j < h; j++)
{
rgb = newPD.getPixelData(img, i, j);
for(int k = 0; k < rgb.length; k++)
{
pixelData[count][k] = rgb[k];
}
if(pixel.display_imgHex2()[i][j].equals(pixel.display_img2Hex2()[i][j]))
{
System.out.println("\nPixel values at position 2 are the same." + "\n" + pixel.display_imgHex2()[i][j] + " " + pixel.display_img2Hex2()[i][j]);
not_stega2[i][j] = pixel.display_img2Hex2()[i][j]; // i've done the same as check_hex2 and check_hex4 method but why the error still occur?
}
if(pixel.display_imgHex4()[i][j].equals(pixel.display_img2Hex4()[i][j]))
{
System.out.println("\nPixel values at position 4 are the same." + "\n" + pixel.display_imgHex4()[i][j] + " " + pixel.display_img2Hex4()[i][j]);
not_stega4[i][j] = pixel.display_img2Hex4()[i][j];
}
if(!pixel.display_imgHex2()[i][j].equals(pixel.display_img2Hex2()[i][j]))
{
System.out.println("\nPixel values at position 2 are not the same." + "\n" + pixel.display_imgHex2()[i][j] + " " + pixel.display_img2Hex2()[i][j]);
check_hex2[i][j] = pixel.display_img2Hex2()[i][j];
System.out.println("\nOutput Hex 2: " + check_hex2[i][j]);
}
if(!pixel.display_imgHex4()[i][j].equals(pixel.display_img2Hex4()[i][j]))
{
System.out.println("\nPixel values at position 4 are not the same." + "\n" + pixel.display_imgHex4()[i][j] + " " + pixel.display_img2Hex4()[i][j]);
check_hex4[i][j] = pixel.display_img2Hex4()[i][j];
System.out.println("\nOutput Hex 4: " + check_hex4[i][j]);
}
if(!pixel.display_imgHex2()[i][j].equals(pixel.display_img2Hex2()[i][j]) || (!pixel.display_imgHex4()[i][j].equals(pixel.display_img2Hex4()[i][j])))
{
System.out.println("\nOne of the pixel values at position 2 and 4 are not the same." + "\n" + pixel.display_imgHex2()[i][j] + " " + pixel.display_img2Hex2()[i][j] + "\n" + pixel.display_imgHex4()[i][j] + " " + pixel.display_img2Hex4()[i][j]);
if(!pixel.display_imgHex2()[i][j].equals(pixel.display_img2Hex2()[i][j]) || (pixel.display_imgHex2()[i][j].equals(pixel.display_img2Hex2()[i][j])))
{
check_hex2[i][j] = pixel.display_img2Hex2()[i][j];
System.out.println("\nOutput Hex 2: " + check_hex2[i][j]);
}
if(!pixel.display_imgHex4()[i][j].equals(pixel.display_img2Hex4()[i][j]) || (pixel.display_imgHex4()[i][j].equals(pixel.display_img2Hex4()[i][j])))
{
check_hex4[i][j] = pixel.display_img2Hex4()[i][j];
System.out.println("\nOutput Hex 4: " + check_hex4[i][j]);
}
}
count++;
System.out.println("\nOutput Count: " + count);
}
}
}
public String[][] getCheck_hex2()
{
return check_hex2;
}
public String[][] getCheck_hex4()
{
return check_hex4;
}
public String[][] getCheck_notStega2()
{
return not_stega2;
}
public String[][] getCheck_notStega4()
{
return not_stega4;
}
}
Hoping to eliminate these problems fast. Appreciate any help!
As i see there are 2 flaws in your code::
1. If charExtract() method is static then you need to access it in a static way as::
String out = extractMessage.charExtract();
2. Secondly as you are storing the value from charExtract() to a String variable "out"
so you need to return a string from the charExtract() method ,Declare it as
public static String charExtract()
{ ...
}
and return some value from charExtract like:
return combine[o][1];
public static void charExtract()
{ ...
}
and
String out = em.charExtract(); //error stated incompatible types
obviously don't match. Besides, why are you trying to call the static method charExtract() upon the instance em?
What do you store in those String[][] arrays?
char1 = hexRGB.getCheck_hex2();
char2 = hexRGB.getCheck_hex4();
Without knowing what they are supposed to contain, we cannot help you convert their content to anything.
At the moment I assume that you don't really want to deal with "hex" numbers; calculations are much easier performed on ints than on any String representation of numbers.

Categories

Resources