Can't Convert an Int Array to ASCII - java

to the point.
I don't know what make my function error but here when i want to convert an int Array to ASCII character, i got some errors which says
java.lang.OutOfMemoryError: Failed to allocate a 51529974 byte allocation with 4194304 free bytes and 30MB
I think my function doesn't right enough to convert it.
Here is my function :
public static String[] DectoASCII(int[] resultXORDec,int jumKat) {
int length = jumKat;
String ASCIIfromDec[] = new String[jumKat];
for(int i=0;i<jumKat;i++) {
StringBuilder builder = new StringBuilder(length);
for (int j = length - 1; j >= 0; i--) {
builder.append((char) ((resultXORDec[j] >> (8 * i)) & 0xFF));
}
ASCIIfromDec[i]=builder.toString();
Log.d("ascifrom",ASCIIfromDec[i]);
}
return ASCIIfromDec;
}
}
Please master, help me. Is there any other way to convert int (Decimal) to ASCII code?
Thanks..

Well, I guess the j index does not change in this loop:
for (int j = length - 1; j >= 0; i--) {
builder.append((char) ((resultXORDec[j] >> (8 * i)) & 0xFF));
}
thus you have an infinite loop, so builder gets bigger and bigger.

Related

How to create a char[] using data from a boolean array?

I have a Boolean array and I am trying to make a corresponding char array, so that to each true in the new array corresponds a 1 and for each false a 0. this is my code but it seems the new array is empty, because nothing prints, the Boolean nums[] prints fine.
char[] digits = new char[n];
for (int i = 0; i < n; i++) {
if (nums[i]) {
digits[i] = 1;
}
else if (!nums[i]) {
digits[i] = 0;
}
}
for (int k = 0; k < n; k++) {
System.out.print (digits[k]);
}
Your problem is that you don't have quotes surrounding the 1 and 0.
for (int i = 0; i < n; i++) {
if (nums[i]) {
digits[i] = '1';
}
else {
digits[i] = '0';
}
}
Without the quotes, they are cast from ints to chars. 0 is actually the null character (NUL), and 1 is start of heading or something like that. Java chars are encoded using UTF-16 (they're 16 bits long). The characters '0' and '1' are actually encoded by 48 and 49 respectively (in decimal).
EDIT: Actually, don't look at the ASCII table, look at the Unicode character set. Unicode is really a superset of ASCII, but it'll probably be more useful than the ascii table
According to Primitive Data Types in the Language Basics lesson of trail Learning the Java Language in Oracle's Java tutorials:
The char data type is a single 16-bit Unicode character. It has a minimum value of '\u0000' (or 0) and a maximum value of '\uffff' (or 65,535 inclusive).
Unicode value 0 (zero) is a non-printing character, as is unicode value 1 (one). That's why you aren't seeing anything printed. Either change digits to a int array or fill it with character literals such as '0' or '1'
If you use int array, the following code will suffice:
int[] digits = new int[n];
for (int i=0; i<n; i++) {
if (nums[i]) {
digits[i] = 1;
}
}
for (int k=0; k<n; k++) {
System.out.print (digits[k]);
}
Note that a int array is implicitly initialized such that all the elements are initially 0 (zero).
you can do something like that
char[] myChars = new char[n/16];
for(int i=0;i<nums.length/16;i++);{
String myChar ="";
for(int j=0;j<16;j++){
if(nums[i*16+j])
myChar+="1";
else
myChar+="0";
}
myChars[i]=Integer.parseInt(myChar,2);
}
You can convert like this:
public static void main(String[] args) {
int n = 5;
boolean[] nums = { true, false, true, false, true };
char[] digits = new char[n];
for (int i = 0; i < n; i++) {
digits[i] = nums[i] ? '1' : '0';
}
}

Need help changing a method from recursive to iterative

I'm working on a program that will fix data corruption given the data and the hash of the correct data. It starts to get slow after about 4 or 5 bits are corrupted even when only dealing with only a few bytes of data, so I thought I would make it iterative instead of recursive. After doing some research, I found that I could use a stack to do so. I'm currently having trouble with finding the correct place to pop the variables off of the stack. Here's the original method.
private static void fixFile(byte[] data, byte[] hash, byte[] correctHash, MessageDigest hasher, long depth)
{
int len = data.length;
outer: for(int i = 0; i < len; i++)
{
byte origVal = data[i];
for(int j = 0; j < 8; j++)
{
data[i] = (byte) (data[i] ^ (1 << j));
if(depth > 1)
fixFile(data, hash, correctHash, hasher, depth - 1);
hash = hasher.digest(data);
if(!Arrays.equals(correctHash, hash))
data[i] = origVal;
else
break outer;
}
}
}
Here's the modified method where I tried to make it iterative.
private static void fixFile(byte[] data, byte[] hash, byte[] correctHash, MessageDigest hasher, long depth)
{
Stack stack = new Stack<Integer>();
int len = data.length;
outer: for(int i = 0; i < len; i++)
{
byte origVal = data[i];
for(int j = 0; j < 8; j++)
{
data[i] = (byte) (data[i] ^ (1 << j));
if(depth > 1)
{
stack.push(depth);
stack.push(i);
stack.push(j);
depth--;
i = -1;
j = 0;
continue outer;
}
else
{
// where do I put this to make it work.
j = stack.pop();
i = stack.pop();
depth = stack.pop();
}
hash = hasher.digest(data);
if(!Arrays.equals(correctHash, hash))
data[i] = origVal;
else
break outer;
}
}
}
I think your recursive approach is ideal for this problem and all the time will be being spent in the digest function.
However, when you are fixing depth bits you can get a factorial(depth) improvement in the speed of the program. (So for 6 bits this will make the program go 6*5*4*3*2*1 = 720 times faster.)
The issue is that your current code currently toggles depth bits in your data, but in any order. i.e. when it toggles three bits it will try toggling bits 1,2,3 and 2,1,3 and 3,1,2 and 3,2,1 and 1,3,2 and 2,3,1 (amongst many other choices). Note that in each of these cases exactly the same 3 bits are toggled so there is no point testing them all.
You can fix this by passing additional parameters to your code saying where the last bit was toggled (i.e. pass in i and j as i_base and j_base), and then only allow your code to toggle new bits if they are at a later position in the data (i.e. if i>i_base || (i==i_base && j>j_base)).

What will this constructor look like?

public byte[] d
In this byte array, each byte represents a digits, where d[0] is the least significant digit, and a[d.length-1] is the most significant digit. For example, 543210 is stored as {0,1,2,3,4,5}. The most significant digit can't be a zero;
In the real implementation, this array should be private.
Constructor Detail: AdditionOnlyInt
public AdditionOnlyInt(java.lang.String a)
This is a constructor that construct an AdditionOnlyInt with value presented by the input string. For example, if input a = "00012340", this constructor will set the byte array to have value {0,4,3,2,1}. Note that the leading zeros in the input string should not be stored.
Parameters:a - is a string such as "00012340"
I do not know how to do this constructor does anyone?
I know its very wrong but I tried this
public AdditionOnlyInt(String number) {
int counter = number.length();
number.replace("0","");
data = new byte[number.length()];
int i = 0;
while(i<number.length()) {
data[i] = (byte)number.charAt(counter);
i++;
counter--;
}
}
and I do know converting to byte gives you different values.
You're in luck: only a handful of modifications need to be made to your program. You weren't entirely wrong. :)
First, these three statements are giving you fits:
int counter = number.length();
number.replace("0","");
data = new byte[number.length()];
You get a counter, which is the unbiased String (that is, with zeroes), which will undoubtedly be smaller than the String, without zeroes. You'd also be creating the array with the size of the unbiased list.
Well...it would be if your second statement did something. String is immutable, so anything that's done to modify it would only generate a new String, leaving the old one unmodified. That's fixable by this:
number = number.replace("0", "");
...but in reality, given your input set, it should be fixed by this:
number = String.valueOf(Integer.parseInt(number));
This way, you keep internal zeroes.
Now assuming that your byte[] is actually called data and not d, there's one little issue we have to fix: numbers in terms of a byte are quite large (that is, the character for '7' is 0x37, which is 55).
So we need to bias it. Whatever our byte number is, we need to subtract '0' from it; that is, we need to subtract 48 from it, to give us our correct value. I'll show you what that looks like in a moment.
Now, for your loop:
int i = 0;
while(i<number.length()) {
data[i] = (byte)number.charAt(counter);
i++;
counter--;
}
I'm not sold on the necessity of counter, so let's get rid of it. Now we'll use i from now on. Essentially, what this means is that we have to move charAt from the end of the String to the front of the String, placing the values into the array as such. What that (mostly) looks like is this:
data[i] = (byte) (number.charAt(number.length() - 1 - i);
Pay close attention here - we have to subtract 1 from the length right off the bat, since we don't have a place on the String that's exactly equal to its maximum length. We then subtract i from that, so we get the effect of moving backwards on the String.
That is, for a string of length 10 without zeroes, if we start at i = 0, we get the character at 10 - 1 - 0 = 9, or the last character.
Remember what I said about biasing the result of that, though? After you've got the data, be sure to subtract '0' from it.
data[i] = (byte) (number.charAt(number.length() - 1 - i) - '0';
And really, that's all there is to it. You mostly got it, except the iteration and sanitization was a bit wonky.
public AdditionOnlyInt(String input)
{
//remove trailing 0s
int relevStart = 0;
while(input.charAt(relevStart) == '0')
{
relevStart++;
}
String relevantTerms = input.substring(relevStart);
//flip the remaining chars
int length = relevantTerms.length();
data = new byte[length];
for(int iter = 0; iter < length; iter++)
{
data[iter] = (byte) (relevantTerms.charAt(length - iter - 1) - '0');
}
}
Hope this helps.
Step 1: Check whether its a number by using Integer value = Integer.valueOf(args);
Step 2: convert the Integer into a byte array by calling byte array[] = value.toString().getBytes();
Step 3: the byte array contains the value in forward fashion, So swapping all the values in the array will make the digit reverse as user requested.
for (int i = 0, j = array.length - 1; i < array.length / 2; i++, j--) {
byte temp = array[i];
array[i] = array[j];
array[j] = temp;
}
find the complete program below:
public class AdditionOnlyInt {
public static void main(String[] args) {
// TODO Auto-generated method stub
new AdditionOnlyInt("01010120");
}
public AdditionOnlyInt(String args) {
try {
Integer value = Integer.valueOf(args);
byte array[] = value.toString().getBytes();
for (int i = 0, j = array.length - 1; i < array.length / 2; i++, j--) {
byte temp = array[i];
array[i] = array[j];
array[j] = temp;
}
for (int i = 0; i < array.length; i++) {
System.out.print((char) array[i]);
}
} catch (Exception e) {
}
}
}

What's wrong with my bit vector?

I am trying to create a bit vector backed by an int[].
So I have the following code:
public class BitVector {
int[] vector = new int[1 << 16];
public void setBit(int nextInt) {
nextInt = nextInt & 0xFFFF;
int pos = nextInt / 32;
int offset = nextInt % 32;
vector[pos] |= (1 << offset);
}
public int findClearedBit() {
for(int i = 0; i < vector.length; i++){
for(int j = 0; j < 8; j++){
if((vector[i] & (1 << j)) == 0)
return i * 32 + j;
}
}
return -1;
}
}
I know that perhaps I should have used byte[] instead etc but I was wondering why this way it does not work.
The idea is that I pass in int from a stream and keep the lower 16 bits and mark the corresponding bit as set. So when I iterate over the vector I will find the number (indicate by the lower 16 bits) missing.
But I get wrong result. So I believe my handing is wrong.
Any ideas?
Update:
I have a stream of 32-bit integers. As I read them in I try to mark a number missing by using the lower 16-bits and setting the bitvector (code posted).
I also try to find the upper 16 bits missing reading the stream a second time.
So while the missing number is: 231719592 = (1101110011111100001010101000) = (3535-49832)
When I read the stream I don't get 49832 as the missing lower bits but 65536
Update2:
public int findMissingInt(File f)throws Exception{
Scanner sc = new Scanner(f);
int SIZE = 1 << 16;
int[] occurences = new int[SIZE];
while(sc.hasNext()){
occurences[getIdx(sc.nextInt())]++;
}
int missingUpper = -1;
for(int i = 0; i < occurences.length; i++){
if(occurences[i] < SIZE){
System.out.println("Found upper bits:"+i);
missingUpper = i;
break;
}
}
if(missingUpper == -1){
return -1;
}
//Arrays.fill(occurences, 0); //I reused this. Bellow changed after answer of Peter de Rivaz
BitVector v = new BitVector(new int[1 << (16-5)]);
sc = new Scanner(f);
while(sc.hasNext()){
v.setBit(sc.nextInt());
}
int missingLower = v.findClearedBit();
System.out.println("Lower bits:"+missingLower);
return createNumber(missingUpper, missingLower);
}
private int createNumber(int missingUpper, int missingLower) {
int result = missingUpper;
result = result << 16;
return result | missingLower;
}
public int getIdx(int nextInt) {
return (nextInt >>> 16);
}
I get:
Missing number=231719592
Found upper bits:3535 //CORRECT
Lower bits:-1 //WRONG
Actual missing number=-1 //WRONG
I think there are two problems:
Your array has 65536 entries, but you store 32 bits in each entry, so you only need 65536/32 entries in it.
You store 32 bits in each int, but only check j from 0 to 7 when finding gaps
The first bug means that your program reports 65536 as a missing 16bit number.
The second bug means that your program does not spot the missing number.
i.e. change
int[] vector = new int[1 << 16];
to
int[] vector = new int[1 << (16-5)];
and change
for(int j = 0; j < 8; j++)
to
for(int j = 0; j < 32; j++)
EDIT
Judging from the comments, the question is actually how to find a missing number with limited RAM. The answer to this question can be found here on stackoverflow.
There is an additional bug in the higher level code.
During the second pass that populates the bitset, you should only include numbers that have the matching upper bits.
i.e. change
v.setBit(sc.nextInt());
to something like
int nx = sc.nextInt();
if (getIdx(nx)==missingUpper)
v.setBit(nx);

Converting array with samples into byte array

I have two-dimensional array of integers. First index indicates the number of channels. The second one indicates the number of sample in the channel. How can I save this array into the audio file? I know, I have to convert it to byte array, but I have no idea how to do that.
// edit
More info. I already have a class for drawing a waveform. It is here:
http://javafaq.nu/java-example-code-716.html
now I want to cut part of this wave and save it to the new file. So I have to cut part of int[][] samplesContainer, convert it to byte array (I don't know how) and then save it to file with the same format as audioInputStream.
// edit
OK. So the biggest problem is to write inverted function to this one:
protected int[][] getSampleArray(byte[] eightBitByteArray) {
int[][] toReturn = new int[getNumberOfChannels()][eightBitByteArray.length / (2 * getNumberOfChannels())];
int index = 0;
//loop through the byte[]
for (int t = 0; t < eightBitByteArray.length;) {
//for each iteration, loop through the channels
for (int a = 0; a < getNumberOfChannels(); a++) {
//do the byte to sample conversion
//see AmplitudeEditor for more info
int low = (int) eightBitByteArray[t];
t++;
int high = (int) eightBitByteArray[t];
t++;
int sample = (high << 8) + (low & 0x00ff);
if (sample < sampleMin) {
sampleMin = sample;
} else if (sample > sampleMax) {
sampleMax = sample;
}
//set the value.
toReturn[a][index] = sample;
}
index++;
}
return toReturn;
}
I don't understand why there is second incrementation of t, after high. I also have no idea how can i get high and low from sample.
The code you posted reads a sample stream, byte by byte, into the samples array. The code assumes that, in the stream, every two 8-bit bytes form a 16-bit sample, and that there is one sample for each of the NumOfChannels channels.
So, given an array of samples like the one returned by that code,
int[][] samples;
and a byte array for streaming,
byte[] stream;
you might build the converse stream of bytes this way
for (int i=0; i<NumOfSamples; i++) {
for (int j=0; j<NumOfChannels; j++) {
int sample=samples[i][j];
byte low = (byte) (sample & 0xff) ;
byte high = (byte) ((sample & 0xff00 ) >> 8);
stream[((i*NumOfChannels)+j)*2] = low;
stream[(((i*NumOfChannels)+j)*2)+1] = high;
}
}

Categories